xref: /dpdk/app/test/test_bpf.c (revision fc0ec740)
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_HAS_LIBPCAP
3254 #include <pcap/pcap.h>
3255 
3256 static void
3257 test_bpf_dump(struct bpf_program *cbf, const struct rte_bpf_prm *prm)
3258 {
3259 	printf("cBPF program (%u insns)\n", cbf->bf_len);
3260 	bpf_dump(cbf, 1);
3261 
3262 	printf("\neBPF program (%u insns)\n", prm->nb_ins);
3263 	rte_bpf_dump(stdout, prm->ins, prm->nb_ins);
3264 }
3265 
3266 static int
3267 test_bpf_match(pcap_t *pcap, const char *str,
3268 	       struct rte_mbuf *mb)
3269 {
3270 	struct bpf_program fcode;
3271 	struct rte_bpf_prm *prm = NULL;
3272 	struct rte_bpf *bpf = NULL;
3273 	int ret = -1;
3274 	uint64_t rc;
3275 
3276 	if (pcap_compile(pcap, &fcode, str, 1, PCAP_NETMASK_UNKNOWN)) {
3277 		printf("%s@%d: pcap_compile(\"%s\") failed: %s;\n",
3278 		       __func__, __LINE__,  str, pcap_geterr(pcap));
3279 		return -1;
3280 	}
3281 
3282 	prm = rte_bpf_convert(&fcode);
3283 	if (prm == NULL) {
3284 		printf("%s@%d: bpf_convert('%s') failed,, error=%d(%s);\n",
3285 		       __func__, __LINE__, str, rte_errno, strerror(rte_errno));
3286 		goto error;
3287 	}
3288 
3289 	bpf = rte_bpf_load(prm);
3290 	if (bpf == NULL) {
3291 		printf("%s@%d: failed to load bpf code, error=%d(%s);\n",
3292 			__func__, __LINE__, rte_errno, strerror(rte_errno));
3293 		goto error;
3294 	}
3295 
3296 	rc = rte_bpf_exec(bpf, mb);
3297 	/* The return code from bpf capture filter is non-zero if matched */
3298 	ret = (rc == 0);
3299 error:
3300 	if (bpf)
3301 		rte_bpf_destroy(bpf);
3302 	rte_free(prm);
3303 	pcap_freecode(&fcode);
3304 	return ret;
3305 }
3306 
3307 /* Basic sanity test can we match a IP packet */
3308 static int
3309 test_bpf_filter_sanity(pcap_t *pcap)
3310 {
3311 	const uint32_t plen = 100;
3312 	struct rte_mbuf mb, *m;
3313 	uint8_t tbuf[RTE_MBUF_DEFAULT_BUF_SIZE];
3314 	struct {
3315 		struct rte_ether_hdr eth_hdr;
3316 		struct rte_ipv4_hdr ip_hdr;
3317 	} *hdr;
3318 
3319 	dummy_mbuf_prep(&mb, tbuf, sizeof(tbuf), plen);
3320 	m = &mb;
3321 
3322 	hdr = rte_pktmbuf_mtod(m, typeof(hdr));
3323 	hdr->eth_hdr = (struct rte_ether_hdr) {
3324 		.dst_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
3325 		.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4),
3326 	};
3327 	hdr->ip_hdr = (struct rte_ipv4_hdr) {
3328 		.version_ihl = RTE_IPV4_VHL_DEF,
3329 		.total_length = rte_cpu_to_be_16(plen),
3330 		.time_to_live = IPDEFTTL,
3331 		.next_proto_id = IPPROTO_RAW,
3332 		.src_addr = rte_cpu_to_be_32(RTE_IPV4_LOOPBACK),
3333 		.dst_addr = rte_cpu_to_be_32(RTE_IPV4_BROADCAST),
3334 	};
3335 
3336 	if (test_bpf_match(pcap, "ip", m) != 0) {
3337 		printf("%s@%d: filter \"ip\" doesn't match test data\n",
3338 		       __func__, __LINE__);
3339 		return -1;
3340 	}
3341 	if (test_bpf_match(pcap, "not ip", m) == 0) {
3342 		printf("%s@%d: filter \"not ip\" does match test data\n",
3343 		       __func__, __LINE__);
3344 		return -1;
3345 	}
3346 
3347 	return 0;
3348 }
3349 
3350 /*
3351  * Some sample pcap filter strings from
3352  * https://wiki.wireshark.org/CaptureFilters
3353  */
3354 static const char * const sample_filters[] = {
3355 	"host 172.18.5.4",
3356 	"net 192.168.0.0/24",
3357 	"src net 192.168.0.0/24",
3358 	"src net 192.168.0.0 mask 255.255.255.0",
3359 	"dst net 192.168.0.0/24",
3360 	"dst net 192.168.0.0 mask 255.255.255.0",
3361 	"port 53",
3362 	"host 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_HAS_LIBPCAP */
3451