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