etc/protocols - sync with NetBSD-8
[minix.git] / tests / net / bpfjit / t_cop.c
blob5a007e6510a555949c87f8ed2e22c78854e9c3fe
1 /* $NetBSD: t_cop.c,v 1.3 2014/07/13 21:35:33 alnsn Exp $ */
3 /*-
4 * Copyright (c) 2014 Alexander Nasonov.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: t_cop.c,v 1.3 2014/07/13 21:35:33 alnsn Exp $");
35 #include <stdint.h>
36 #include <string.h>
38 #define __BPF_PRIVATE
39 #include <net/bpf.h>
40 #include <net/bpfjit.h>
42 #include "../../net/bpf/h_bpf.h"
44 /* XXX: atf-c.h has collisions with mbuf */
45 #undef m_type
46 #undef m_data
47 #include <atf-c.h>
49 #include "../../h_macros.h"
51 static uint32_t retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
52 static uint32_t retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
53 static uint32_t retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
54 static uint32_t retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
55 static uint32_t setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
57 static const bpf_copfunc_t copfuncs[] = {
58 &retA,
59 &retBL,
60 &retWL,
61 &retNF,
62 &setARG
65 static const bpf_ctx_t ctx = {
66 .copfuncs = copfuncs,
67 .nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]),
68 .extwords = 0
71 static uint32_t
72 retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
75 return A;
78 static uint32_t
79 retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
82 return args->buflen;
85 static uint32_t
86 retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
89 return args->wirelen;
92 static uint32_t
93 retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
96 return bc->nfuncs;
100 * COP function with a side effect.
102 static uint32_t
103 setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
105 bool *arg = (bool *)args->arg;
106 bool old = *arg;
108 *arg = true;
109 return old;
112 ATF_TC(bpfjit_cop_no_ctx);
113 ATF_TC_HEAD(bpfjit_cop_no_ctx, tc)
115 atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COP "
116 "instruction isn't valid without a context");
119 ATF_TC_BODY(bpfjit_cop_no_ctx, tc)
121 static struct bpf_insn insns[] = {
122 BPF_STMT(BPF_MISC+BPF_COP, 0),
123 BPF_STMT(BPF_RET+BPF_K, 7)
126 bpfjit_func_t code;
128 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
130 RZ(rump_init());
132 ATF_CHECK(!prog_validate(insns, insn_count));
134 rump_schedule();
135 code = rumpns_bpfjit_generate_code(NULL, insns, insn_count);
136 rump_unschedule();
137 ATF_CHECK(code == NULL);
140 ATF_TC(bpfjit_cop_ret_A);
141 ATF_TC_HEAD(bpfjit_cop_ret_A, tc)
143 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
144 "that returns a content of the A register");
147 ATF_TC_BODY(bpfjit_cop_ret_A, tc)
149 static struct bpf_insn insns[] = {
150 BPF_STMT(BPF_LD+BPF_IMM, 13),
151 BPF_STMT(BPF_MISC+BPF_COP, 0), // retA
152 BPF_STMT(BPF_RET+BPF_A, 0)
155 bpfjit_func_t code;
156 uint8_t pkt[1] = { 0 };
157 bpf_args_t args = {
158 .pkt = pkt,
159 .buflen = sizeof(pkt),
160 .wirelen = sizeof(pkt),
163 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
165 RZ(rump_init());
167 rump_schedule();
168 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
169 rump_unschedule();
170 ATF_REQUIRE(code != NULL);
172 ATF_CHECK(code(&ctx, &args) == 13);
174 rump_schedule();
175 rumpns_bpfjit_free_code(code);
176 rump_unschedule();
179 ATF_TC(bpfjit_cop_ret_buflen);
180 ATF_TC_HEAD(bpfjit_cop_ret_buflen, tc)
182 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
183 "that returns the buflen argument");
186 ATF_TC_BODY(bpfjit_cop_ret_buflen, tc)
188 static struct bpf_insn insns[] = {
189 BPF_STMT(BPF_LD+BPF_IMM, 13),
190 BPF_STMT(BPF_MISC+BPF_COP, 1), // retBL
191 BPF_STMT(BPF_RET+BPF_A, 0)
194 bpfjit_func_t code;
195 uint8_t pkt[1] = { 0 };
196 bpf_args_t args = {
197 .pkt = pkt,
198 .buflen = sizeof(pkt),
199 .wirelen = sizeof(pkt)
202 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
204 RZ(rump_init());
206 rump_schedule();
207 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
208 rump_unschedule();
209 ATF_REQUIRE(code != NULL);
211 ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
213 rump_schedule();
214 rumpns_bpfjit_free_code(code);
215 rump_unschedule();
218 ATF_TC(bpfjit_cop_ret_wirelen);
219 ATF_TC_HEAD(bpfjit_cop_ret_wirelen, tc)
221 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
222 "that returns the wirelen argument");
225 ATF_TC_BODY(bpfjit_cop_ret_wirelen, tc)
227 static struct bpf_insn insns[] = {
228 BPF_STMT(BPF_LD+BPF_IMM, 13),
229 BPF_STMT(BPF_MISC+BPF_COP, 2), // retWL
230 BPF_STMT(BPF_RET+BPF_A, 0)
233 bpfjit_func_t code;
234 uint8_t pkt[1] = { 0 };
235 bpf_args_t args = {
236 .pkt = pkt,
237 .buflen = sizeof(pkt),
238 .wirelen = sizeof(pkt)
241 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
243 RZ(rump_init());
245 rump_schedule();
246 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
247 rump_unschedule();
248 ATF_REQUIRE(code != NULL);
250 ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
252 rump_schedule();
253 rumpns_bpfjit_free_code(code);
254 rump_unschedule();
257 ATF_TC(bpfjit_cop_ret_nfuncs);
258 ATF_TC_HEAD(bpfjit_cop_ret_nfuncs, tc)
260 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
261 "that returns nfuncs member of the context argument");
264 ATF_TC_BODY(bpfjit_cop_ret_nfuncs, tc)
266 static struct bpf_insn insns[] = {
267 BPF_STMT(BPF_LD+BPF_IMM, 13),
268 BPF_STMT(BPF_MISC+BPF_COP, 3), // retNF
269 BPF_STMT(BPF_RET+BPF_A, 0)
272 bpfjit_func_t code;
273 uint8_t pkt[1] = { 0 };
274 bpf_args_t args = {
275 .pkt = pkt,
276 .buflen = sizeof(pkt),
277 .wirelen = sizeof(pkt)
280 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
282 RZ(rump_init());
284 rump_schedule();
285 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
286 rump_unschedule();
287 ATF_REQUIRE(code != NULL);
289 ATF_CHECK(code(&ctx, &args) == ctx.nfuncs);
291 rump_schedule();
292 rumpns_bpfjit_free_code(code);
293 rump_unschedule();
296 ATF_TC(bpfjit_cop_side_effect);
297 ATF_TC_HEAD(bpfjit_cop_side_effect, tc)
299 atf_tc_set_md_var(tc, "descr",
300 "Test that ABC optimization doesn't skip BPF_COP call");
303 ATF_TC_BODY(bpfjit_cop_side_effect, tc)
305 static struct bpf_insn insns[] = {
306 BPF_STMT(BPF_LD+BPF_IMM, 13),
307 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),
308 BPF_STMT(BPF_MISC+BPF_COP, 4), // setARG
309 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999),
310 BPF_STMT(BPF_RET+BPF_A, 0)
313 bpfjit_func_t code;
314 bool arg = false;
315 uint8_t pkt[1] = { 0 };
316 bpf_args_t args = {
317 .pkt = pkt,
318 .buflen = sizeof(pkt),
319 .wirelen = sizeof(pkt),
320 .mem = NULL,
321 .arg = &arg
324 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
326 RZ(rump_init());
328 rump_schedule();
329 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
330 rump_unschedule();
331 ATF_REQUIRE(code != NULL);
333 ATF_CHECK(code(&ctx, &args) == 0);
334 ATF_CHECK(arg == true);
336 rump_schedule();
337 rumpns_bpfjit_free_code(code);
338 rump_unschedule();
341 ATF_TC(bpfjit_cop_copx);
342 ATF_TC_HEAD(bpfjit_cop_copx, tc)
344 atf_tc_set_md_var(tc, "descr",
345 "Test BPF_COP call followed by BPF_COPX call");
348 ATF_TC_BODY(bpfjit_cop_copx, tc)
350 static struct bpf_insn insns[] = {
351 BPF_STMT(BPF_LD+BPF_IMM, 1), /* A <- 1 */
352 BPF_STMT(BPF_MISC+BPF_COP, 0), /* retA */
353 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */
354 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A = P[0] */
355 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */
356 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */
357 BPF_STMT(BPF_MISC+BPF_COPX, 0), /* retNF */
358 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */
359 BPF_STMT(BPF_RET+BPF_A, 0)
362 bpfjit_func_t code;
363 uint8_t pkt[1] = { 2 };
364 bpf_args_t args = {
365 .pkt = pkt,
366 .buflen = sizeof(pkt),
367 .wirelen = sizeof(pkt),
370 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
372 RZ(rump_init());
374 rump_schedule();
375 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
376 rump_unschedule();
377 ATF_REQUIRE(code != NULL);
379 ATF_CHECK(code(&ctx, &args) == 3 + ctx.nfuncs);
381 rump_schedule();
382 rumpns_bpfjit_free_code(code);
383 rump_unschedule();
386 ATF_TC(bpfjit_cop_invalid_index);
387 ATF_TC_HEAD(bpfjit_cop_invalid_index, tc)
389 atf_tc_set_md_var(tc, "descr",
390 "Test that out-of-range coprocessor function fails validation");
393 ATF_TC_BODY(bpfjit_cop_invalid_index, tc)
395 static struct bpf_insn insns[] = {
396 BPF_STMT(BPF_LD+BPF_IMM, 13),
397 BPF_STMT(BPF_MISC+BPF_COP, 6), // invalid index
398 BPF_STMT(BPF_RET+BPF_K, 27)
401 bpfjit_func_t code;
402 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
404 RZ(rump_init());
406 rump_schedule();
407 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
408 rump_unschedule();
409 ATF_CHECK(code == NULL);
412 ATF_TC(bpfjit_copx_no_ctx);
413 ATF_TC_HEAD(bpfjit_copx_no_ctx, tc)
415 atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COPX "
416 "instruction isn't valid without a context");
419 ATF_TC_BODY(bpfjit_copx_no_ctx, tc)
421 static struct bpf_insn insns[] = {
422 BPF_STMT(BPF_MISC+BPF_COP, 0),
423 BPF_STMT(BPF_RET+BPF_K, 7)
426 bpfjit_func_t code;
428 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
430 RZ(rump_init());
432 ATF_CHECK(!prog_validate(insns, insn_count));
434 rump_schedule();
435 code = rumpns_bpfjit_generate_code(NULL, insns, insn_count);
436 rump_unschedule();
437 ATF_CHECK(code == NULL);
440 ATF_TC(bpfjit_copx_ret_A);
441 ATF_TC_HEAD(bpfjit_copx_ret_A, tc)
443 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
444 "that returns a content of the A register");
447 ATF_TC_BODY(bpfjit_copx_ret_A, tc)
449 static struct bpf_insn insns[] = {
450 BPF_STMT(BPF_LD+BPF_IMM, 13),
451 BPF_STMT(BPF_LDX+BPF_IMM, 0), // retA
452 BPF_STMT(BPF_MISC+BPF_COPX, 0),
453 BPF_STMT(BPF_RET+BPF_A, 0)
456 bpfjit_func_t code;
457 uint8_t pkt[1] = { 0 };
458 bpf_args_t args = {
459 .pkt = pkt,
460 .buflen = sizeof(pkt),
461 .wirelen = sizeof(pkt),
464 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
466 RZ(rump_init());
468 rump_schedule();
469 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
470 rump_unschedule();
471 ATF_REQUIRE(code != NULL);
473 ATF_CHECK(code(&ctx, &args) == 13);
475 rump_schedule();
476 rumpns_bpfjit_free_code(code);
477 rump_unschedule();
480 ATF_TC(bpfjit_copx_ret_buflen);
481 ATF_TC_HEAD(bpfjit_copx_ret_buflen, tc)
483 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
484 "that returns the buflen argument");
487 ATF_TC_BODY(bpfjit_copx_ret_buflen, tc)
489 static struct bpf_insn insns[] = {
490 BPF_STMT(BPF_LD+BPF_IMM, 13),
491 BPF_STMT(BPF_LDX+BPF_IMM, 1), // retBL
492 BPF_STMT(BPF_MISC+BPF_COPX, 0),
493 BPF_STMT(BPF_RET+BPF_A, 0)
496 bpfjit_func_t code;
497 uint8_t pkt[1] = { 0 };
498 bpf_args_t args = {
499 .pkt = pkt,
500 .buflen = sizeof(pkt),
501 .wirelen = sizeof(pkt)
504 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
506 RZ(rump_init());
508 rump_schedule();
509 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
510 rump_unschedule();
511 ATF_REQUIRE(code != NULL);
513 ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
515 rump_schedule();
516 rumpns_bpfjit_free_code(code);
517 rump_unschedule();
520 ATF_TC(bpfjit_copx_ret_wirelen);
521 ATF_TC_HEAD(bpfjit_copx_ret_wirelen, tc)
523 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
524 "that returns the wirelen argument");
527 ATF_TC_BODY(bpfjit_copx_ret_wirelen, tc)
529 static struct bpf_insn insns[] = {
530 BPF_STMT(BPF_LDX+BPF_IMM, 2), // retWL
531 BPF_STMT(BPF_LD+BPF_IMM, 13),
532 BPF_STMT(BPF_MISC+BPF_COPX, 0),
533 BPF_STMT(BPF_RET+BPF_A, 0)
536 bpfjit_func_t code;
537 uint8_t pkt[1] = { 0 };
538 bpf_args_t args = {
539 .pkt = pkt,
540 .buflen = sizeof(pkt),
541 .wirelen = sizeof(pkt)
544 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
546 RZ(rump_init());
548 rump_schedule();
549 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
550 rump_unschedule();
551 ATF_REQUIRE(code != NULL);
553 ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
555 rump_schedule();
556 rumpns_bpfjit_free_code(code);
557 rump_unschedule();
560 ATF_TC(bpfjit_copx_ret_nfuncs);
561 ATF_TC_HEAD(bpfjit_copx_ret_nfuncs, tc)
563 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
564 "that returns nfuncs member of the context argument");
567 ATF_TC_BODY(bpfjit_copx_ret_nfuncs, tc)
569 static struct bpf_insn insns[] = {
570 BPF_STMT(BPF_LD+BPF_IMM, 13),
571 BPF_STMT(BPF_LDX+BPF_IMM, 3), // retNF
572 BPF_STMT(BPF_MISC+BPF_COPX, 0),
573 BPF_STMT(BPF_RET+BPF_A, 0)
576 bpfjit_func_t code;
577 uint8_t pkt[1] = { 0 };
578 bpf_args_t args = {
579 .pkt = pkt,
580 .buflen = sizeof(pkt),
581 .wirelen = sizeof(pkt)
584 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
586 RZ(rump_init());
588 rump_schedule();
589 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
590 rump_unschedule();
591 ATF_REQUIRE(code != NULL);
593 ATF_CHECK(code(&ctx, &args) == ctx.nfuncs);
595 rump_schedule();
596 rumpns_bpfjit_free_code(code);
597 rump_unschedule();
600 ATF_TC(bpfjit_copx_side_effect);
601 ATF_TC_HEAD(bpfjit_copx_side_effect, tc)
603 atf_tc_set_md_var(tc, "descr",
604 "Test that ABC optimization doesn't skip BPF_COPX call");
607 ATF_TC_BODY(bpfjit_copx_side_effect, tc)
609 static struct bpf_insn insns[] = {
610 BPF_STMT(BPF_LD+BPF_IMM, 13),
611 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),
612 BPF_STMT(BPF_LDX+BPF_IMM, 4), // setARG
613 BPF_STMT(BPF_MISC+BPF_COPX, 0),
614 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999),
615 BPF_STMT(BPF_RET+BPF_A, 0)
618 bpfjit_func_t code;
619 bool arg = false;
620 uint8_t pkt[1] = { 0 };
621 bpf_args_t args = {
622 .pkt = pkt,
623 .buflen = sizeof(pkt),
624 .wirelen = sizeof(pkt),
625 .mem = NULL,
626 .arg = &arg
629 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
631 RZ(rump_init());
633 rump_schedule();
634 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
635 rump_unschedule();
636 ATF_REQUIRE(code != NULL);
638 ATF_CHECK(code(&ctx, &args) == 0);
639 ATF_CHECK(arg == true);
641 rump_schedule();
642 rumpns_bpfjit_free_code(code);
643 rump_unschedule();
646 ATF_TC(bpfjit_copx_cop);
647 ATF_TC_HEAD(bpfjit_copx_cop, tc)
649 atf_tc_set_md_var(tc, "descr",
650 "Test BPF_COPX call followed by BPF_COP call");
653 ATF_TC_BODY(bpfjit_copx_cop, tc)
655 static struct bpf_insn insns[] = {
656 BPF_STMT(BPF_LDX+BPF_IMM, 2), /* X <- 2 */
657 BPF_STMT(BPF_MISC+BPF_COPX, 0), /* retWL */
658 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */
659 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */
660 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A = P[0] */
661 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */
662 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */
663 BPF_STMT(BPF_MISC+BPF_COP, 3), /* retNF */
664 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */
665 BPF_STMT(BPF_RET+BPF_A, 0)
668 bpfjit_func_t code;
669 uint8_t pkt[1] = { 2 };
670 bpf_args_t args = {
671 .pkt = pkt,
672 .buflen = sizeof(pkt),
673 .wirelen = sizeof(pkt),
676 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
678 RZ(rump_init());
680 rump_schedule();
681 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
682 rump_unschedule();
683 ATF_REQUIRE(code != NULL);
685 ATF_CHECK(code(&ctx, &args) == 5 + ctx.nfuncs);
687 rump_schedule();
688 rumpns_bpfjit_free_code(code);
689 rump_unschedule();
692 ATF_TC(bpfjit_copx_invalid_index);
693 ATF_TC_HEAD(bpfjit_copx_invalid_index, tc)
695 atf_tc_set_md_var(tc, "descr",
696 "Test that out-of-range BPF_COPX call fails at runtime");
699 ATF_TC_BODY(bpfjit_copx_invalid_index, tc)
701 static struct bpf_insn insns[] = {
702 BPF_STMT(BPF_LDX+BPF_IMM, 5), // invalid index
703 BPF_STMT(BPF_MISC+BPF_COPX, 0),
704 BPF_STMT(BPF_RET+BPF_K, 27)
707 bpfjit_func_t code;
708 uint8_t pkt[1] = { 0 };
709 bpf_args_t args = {
710 .pkt = pkt,
711 .buflen = sizeof(pkt),
712 .wirelen = sizeof(pkt)
715 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
717 RZ(rump_init());
719 rump_schedule();
720 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
721 rump_unschedule();
722 ATF_REQUIRE(code != NULL);
724 ATF_CHECK(code(&ctx, &args) == 0);
726 rump_schedule();
727 rumpns_bpfjit_free_code(code);
728 rump_unschedule();
731 ATF_TP_ADD_TCS(tp)
735 * For every new test please also add a similar test
736 * to ../../lib/libbpfjit/t_cop.c
738 ATF_TP_ADD_TC(tp, bpfjit_cop_no_ctx);
739 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_A);
740 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_buflen);
741 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_wirelen);
742 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_nfuncs);
743 ATF_TP_ADD_TC(tp, bpfjit_cop_side_effect);
744 ATF_TP_ADD_TC(tp, bpfjit_cop_copx);
745 ATF_TP_ADD_TC(tp, bpfjit_cop_invalid_index);
747 ATF_TP_ADD_TC(tp, bpfjit_copx_no_ctx);
748 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_A);
749 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_buflen);
750 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_wirelen);
751 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_nfuncs);
752 ATF_TP_ADD_TC(tp, bpfjit_copx_side_effect);
753 ATF_TP_ADD_TC(tp, bpfjit_copx_cop);
754 ATF_TP_ADD_TC(tp, bpfjit_copx_invalid_index);
756 return atf_no_error();