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