t_cop.c revision 1.2 1 /* $NetBSD: t_cop.c,v 1.2 2014/07/09 15:56:12 alnsn Exp $ */
2
3 /*-
4 * Copyright (c) 2014 Alexander Nasonov.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
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.
17 *
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.
30 */
31
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: t_cop.c,v 1.2 2014/07/09 15:56:12 alnsn Exp $");
34
35 #include <stdint.h>
36 #include <string.h>
37
38 #define __BPF_PRIVATE
39 #include <net/bpf.h>
40 #include <net/bpfjit.h>
41
42 #include "../../net/bpf/h_bpf.h"
43
44 /* XXX: atf-c.h has collisions with mbuf */
45 #undef m_type
46 #undef m_data
47 #include <atf-c.h>
48
49 #include "../../h_macros.h"
50
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);
56
57 static const bpf_copfunc_t copfuncs[] = {
58 &retA,
59 &retBL,
60 &retWL,
61 &retNF,
62 &setARG
63 };
64
65 static const bpf_ctx_t ctx = {
66 .copfuncs = copfuncs,
67 .nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]),
68 .extwords = 0
69 };
70
71 static uint32_t
72 retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
73 {
74
75 return A;
76 }
77
78 static uint32_t
79 retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
80 {
81
82 return args->buflen;
83 }
84
85 static uint32_t
86 retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
87 {
88
89 return args->wirelen;
90 }
91
92 static uint32_t
93 retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
94 {
95
96 return bc->nfuncs;
97 }
98
99 /*
100 * COP function with a side effect.
101 */
102 static uint32_t
103 setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
104 {
105 bool *arg = (bool *)args->arg;
106 bool old = *arg;
107
108 *arg = true;
109 return old;
110 }
111
112 ATF_TC(bpfjit_cop_no_ctx);
113 ATF_TC_HEAD(bpfjit_cop_no_ctx, tc)
114 {
115 atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COP "
116 "instruction isn't valid without a context");
117 }
118
119 ATF_TC_BODY(bpfjit_cop_no_ctx, tc)
120 {
121 static struct bpf_insn insns[] = {
122 BPF_STMT(BPF_MISC+BPF_COP, 0),
123 BPF_STMT(BPF_RET+BPF_K, 7)
124 };
125
126 bpfjit_func_t code;
127
128 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
129
130 RZ(rump_init());
131
132 ATF_CHECK(!prog_validate(insns, insn_count));
133
134 rump_schedule();
135 code = rumpns_bpfjit_generate_code(NULL, insns, insn_count);
136 rump_unschedule();
137 ATF_CHECK(code == NULL);
138 }
139
140 ATF_TC(bpfjit_cop_ret_A);
141 ATF_TC_HEAD(bpfjit_cop_ret_A, tc)
142 {
143 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
144 "that returns a content of the A register");
145 }
146
147 ATF_TC_BODY(bpfjit_cop_ret_A, tc)
148 {
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)
153 };
154
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),
161 };
162
163 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
164
165 RZ(rump_init());
166
167 rump_schedule();
168 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
169 rump_unschedule();
170 ATF_REQUIRE(code != NULL);
171
172 ATF_CHECK(code(&ctx, &args) == 13);
173
174 rump_schedule();
175 rumpns_bpfjit_free_code(code);
176 rump_unschedule();
177 }
178
179 ATF_TC(bpfjit_cop_ret_buflen);
180 ATF_TC_HEAD(bpfjit_cop_ret_buflen, tc)
181 {
182 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
183 "that returns the buflen argument");
184 }
185
186 ATF_TC_BODY(bpfjit_cop_ret_buflen, tc)
187 {
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)
192 };
193
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)
200 };
201
202 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
203
204 RZ(rump_init());
205
206 rump_schedule();
207 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
208 rump_unschedule();
209 ATF_REQUIRE(code != NULL);
210
211 ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
212
213 rump_schedule();
214 rumpns_bpfjit_free_code(code);
215 rump_unschedule();
216 }
217
218 ATF_TC(bpfjit_cop_ret_wirelen);
219 ATF_TC_HEAD(bpfjit_cop_ret_wirelen, tc)
220 {
221 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
222 "that returns the wirelen argument");
223 }
224
225 ATF_TC_BODY(bpfjit_cop_ret_wirelen, tc)
226 {
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)
231 };
232
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)
239 };
240
241 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
242
243 RZ(rump_init());
244
245 rump_schedule();
246 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
247 rump_unschedule();
248 ATF_REQUIRE(code != NULL);
249
250 ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
251
252 rump_schedule();
253 rumpns_bpfjit_free_code(code);
254 rump_unschedule();
255 }
256
257 ATF_TC(bpfjit_cop_ret_nfuncs);
258 ATF_TC_HEAD(bpfjit_cop_ret_nfuncs, tc)
259 {
260 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
261 "that returns nfuncs member of the context argument");
262 }
263
264 ATF_TC_BODY(bpfjit_cop_ret_nfuncs, tc)
265 {
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)
270 };
271
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)
278 };
279
280 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
281
282 RZ(rump_init());
283
284 rump_schedule();
285 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
286 rump_unschedule();
287 ATF_REQUIRE(code != NULL);
288
289 ATF_CHECK(code(&ctx, &args) == ctx.nfuncs);
290
291 rump_schedule();
292 rumpns_bpfjit_free_code(code);
293 rump_unschedule();
294 }
295
296 ATF_TC(bpfjit_cop_side_effect);
297 ATF_TC_HEAD(bpfjit_cop_side_effect, tc)
298 {
299 atf_tc_set_md_var(tc, "descr",
300 "Test that ABC optimization doesn't skip BPF_COP call");
301 }
302
303 ATF_TC_BODY(bpfjit_cop_side_effect, tc)
304 {
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)
311 };
312
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
322 };
323
324 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
325
326 RZ(rump_init());
327
328 rump_schedule();
329 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
330 rump_unschedule();
331 ATF_REQUIRE(code != NULL);
332
333 ATF_CHECK(code(&ctx, &args) == 0);
334 ATF_CHECK(arg == true);
335
336 rump_schedule();
337 rumpns_bpfjit_free_code(code);
338 rump_unschedule();
339 }
340
341 ATF_TC(bpfjit_cop_invalid_index);
342 ATF_TC_HEAD(bpfjit_cop_invalid_index, tc)
343 {
344 atf_tc_set_md_var(tc, "descr",
345 "Test that out-of-range coprocessor function fails validation");
346 }
347
348 ATF_TC_BODY(bpfjit_cop_invalid_index, tc)
349 {
350 static struct bpf_insn insns[] = {
351 BPF_STMT(BPF_LD+BPF_IMM, 13),
352 BPF_STMT(BPF_MISC+BPF_COP, 6), // invalid index
353 BPF_STMT(BPF_RET+BPF_K, 27)
354 };
355
356 bpfjit_func_t code;
357 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
358
359 RZ(rump_init());
360
361 rump_schedule();
362 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
363 rump_unschedule();
364 ATF_CHECK(code == NULL);
365 }
366
367 ATF_TC(bpfjit_copx_no_ctx);
368 ATF_TC_HEAD(bpfjit_copx_no_ctx, tc)
369 {
370 atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COPX "
371 "instruction isn't valid without a context");
372 }
373
374 ATF_TC_BODY(bpfjit_copx_no_ctx, tc)
375 {
376 static struct bpf_insn insns[] = {
377 BPF_STMT(BPF_MISC+BPF_COP, 0),
378 BPF_STMT(BPF_RET+BPF_K, 7)
379 };
380
381 bpfjit_func_t code;
382
383 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
384
385 RZ(rump_init());
386
387 ATF_CHECK(!prog_validate(insns, insn_count));
388
389 rump_schedule();
390 code = rumpns_bpfjit_generate_code(NULL, insns, insn_count);
391 rump_unschedule();
392 ATF_CHECK(code == NULL);
393 }
394
395 ATF_TC(bpfjit_copx_ret_A);
396 ATF_TC_HEAD(bpfjit_copx_ret_A, tc)
397 {
398 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
399 "that returns a content of the A register");
400 }
401
402 ATF_TC_BODY(bpfjit_copx_ret_A, tc)
403 {
404 static struct bpf_insn insns[] = {
405 BPF_STMT(BPF_LD+BPF_IMM, 13),
406 BPF_STMT(BPF_LDX+BPF_IMM, 0), // retA
407 BPF_STMT(BPF_MISC+BPF_COPX, 0),
408 BPF_STMT(BPF_RET+BPF_A, 0)
409 };
410
411 bpfjit_func_t code;
412 uint8_t pkt[1] = { 0 };
413 bpf_args_t args = {
414 .pkt = pkt,
415 .buflen = sizeof(pkt),
416 .wirelen = sizeof(pkt),
417 };
418
419 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
420
421 RZ(rump_init());
422
423 rump_schedule();
424 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
425 rump_unschedule();
426 ATF_REQUIRE(code != NULL);
427
428 ATF_CHECK(code(&ctx, &args) == 13);
429
430 rump_schedule();
431 rumpns_bpfjit_free_code(code);
432 rump_unschedule();
433 }
434
435 ATF_TC(bpfjit_copx_ret_buflen);
436 ATF_TC_HEAD(bpfjit_copx_ret_buflen, tc)
437 {
438 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
439 "that returns the buflen argument");
440 }
441
442 ATF_TC_BODY(bpfjit_copx_ret_buflen, tc)
443 {
444 static struct bpf_insn insns[] = {
445 BPF_STMT(BPF_LD+BPF_IMM, 13),
446 BPF_STMT(BPF_LDX+BPF_IMM, 1), // retBL
447 BPF_STMT(BPF_MISC+BPF_COPX, 0),
448 BPF_STMT(BPF_RET+BPF_A, 0)
449 };
450
451 bpfjit_func_t code;
452 uint8_t pkt[1] = { 0 };
453 bpf_args_t args = {
454 .pkt = pkt,
455 .buflen = sizeof(pkt),
456 .wirelen = sizeof(pkt)
457 };
458
459 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
460
461 RZ(rump_init());
462
463 rump_schedule();
464 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
465 rump_unschedule();
466 ATF_REQUIRE(code != NULL);
467
468 ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
469
470 rump_schedule();
471 rumpns_bpfjit_free_code(code);
472 rump_unschedule();
473 }
474
475 ATF_TC(bpfjit_copx_ret_wirelen);
476 ATF_TC_HEAD(bpfjit_copx_ret_wirelen, tc)
477 {
478 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
479 "that returns the wirelen argument");
480 }
481
482 ATF_TC_BODY(bpfjit_copx_ret_wirelen, tc)
483 {
484 static struct bpf_insn insns[] = {
485 BPF_STMT(BPF_LDX+BPF_IMM, 2), // retWL
486 BPF_STMT(BPF_LD+BPF_IMM, 13),
487 BPF_STMT(BPF_MISC+BPF_COPX, 0),
488 BPF_STMT(BPF_RET+BPF_A, 0)
489 };
490
491 bpfjit_func_t code;
492 uint8_t pkt[1] = { 0 };
493 bpf_args_t args = {
494 .pkt = pkt,
495 .buflen = sizeof(pkt),
496 .wirelen = sizeof(pkt)
497 };
498
499 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
500
501 RZ(rump_init());
502
503 rump_schedule();
504 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
505 rump_unschedule();
506 ATF_REQUIRE(code != NULL);
507
508 ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
509
510 rump_schedule();
511 rumpns_bpfjit_free_code(code);
512 rump_unschedule();
513 }
514
515 ATF_TC(bpfjit_copx_ret_nfuncs);
516 ATF_TC_HEAD(bpfjit_copx_ret_nfuncs, tc)
517 {
518 atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
519 "that returns nfuncs member of the context argument");
520 }
521
522 ATF_TC_BODY(bpfjit_copx_ret_nfuncs, tc)
523 {
524 static struct bpf_insn insns[] = {
525 BPF_STMT(BPF_LD+BPF_IMM, 13),
526 BPF_STMT(BPF_LDX+BPF_IMM, 3), // retNF
527 BPF_STMT(BPF_MISC+BPF_COPX, 0),
528 BPF_STMT(BPF_RET+BPF_A, 0)
529 };
530
531 bpfjit_func_t code;
532 uint8_t pkt[1] = { 0 };
533 bpf_args_t args = {
534 .pkt = pkt,
535 .buflen = sizeof(pkt),
536 .wirelen = sizeof(pkt)
537 };
538
539 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
540
541 RZ(rump_init());
542
543 rump_schedule();
544 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
545 rump_unschedule();
546 ATF_REQUIRE(code != NULL);
547
548 ATF_CHECK(code(&ctx, &args) == ctx.nfuncs);
549
550 rump_schedule();
551 rumpns_bpfjit_free_code(code);
552 rump_unschedule();
553 }
554
555 ATF_TC(bpfjit_copx_side_effect);
556 ATF_TC_HEAD(bpfjit_copx_side_effect, tc)
557 {
558 atf_tc_set_md_var(tc, "descr",
559 "Test that ABC optimization doesn't skip BPF_COPX call");
560 }
561
562 ATF_TC_BODY(bpfjit_copx_side_effect, tc)
563 {
564 static struct bpf_insn insns[] = {
565 BPF_STMT(BPF_LD+BPF_IMM, 13),
566 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),
567 BPF_STMT(BPF_LDX+BPF_IMM, 4), // setARG
568 BPF_STMT(BPF_MISC+BPF_COPX, 0),
569 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999),
570 BPF_STMT(BPF_RET+BPF_A, 0)
571 };
572
573 bpfjit_func_t code;
574 bool arg = false;
575 uint8_t pkt[1] = { 0 };
576 bpf_args_t args = {
577 .pkt = pkt,
578 .buflen = sizeof(pkt),
579 .wirelen = sizeof(pkt),
580 .mem = NULL,
581 .arg = &arg
582 };
583
584 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
585
586 RZ(rump_init());
587
588 rump_schedule();
589 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
590 rump_unschedule();
591 ATF_REQUIRE(code != NULL);
592
593 ATF_CHECK(code(&ctx, &args) == 0);
594 ATF_CHECK(arg == true);
595
596 rump_schedule();
597 rumpns_bpfjit_free_code(code);
598 rump_unschedule();
599 }
600
601 ATF_TC(bpfjit_copx_invalid_index);
602 ATF_TC_HEAD(bpfjit_copx_invalid_index, tc)
603 {
604 atf_tc_set_md_var(tc, "descr",
605 "Test that out-of-range BPF_COPX call fails at runtime");
606 }
607
608 ATF_TC_BODY(bpfjit_copx_invalid_index, tc)
609 {
610 static struct bpf_insn insns[] = {
611 BPF_STMT(BPF_LDX+BPF_IMM, 5), // invalid index
612 BPF_STMT(BPF_MISC+BPF_COPX, 0),
613 BPF_STMT(BPF_RET+BPF_K, 27)
614 };
615
616 bpfjit_func_t code;
617 uint8_t pkt[1] = { 0 };
618 bpf_args_t args = {
619 .pkt = pkt,
620 .buflen = sizeof(pkt),
621 .wirelen = sizeof(pkt)
622 };
623
624 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
625
626 RZ(rump_init());
627
628 rump_schedule();
629 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
630 rump_unschedule();
631 ATF_REQUIRE(code != NULL);
632
633 ATF_CHECK(code(&ctx, &args) == 0);
634
635 rump_schedule();
636 rumpns_bpfjit_free_code(code);
637 rump_unschedule();
638 }
639
640 ATF_TP_ADD_TCS(tp)
641 {
642
643 /*
644 * For every new test please also add a similar test
645 * to ../../lib/libbpfjit/t_cop.c
646 */
647 ATF_TP_ADD_TC(tp, bpfjit_cop_no_ctx);
648 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_A);
649 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_buflen);
650 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_wirelen);
651 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_nfuncs);
652 ATF_TP_ADD_TC(tp, bpfjit_cop_side_effect);
653 ATF_TP_ADD_TC(tp, bpfjit_cop_invalid_index);
654
655 ATF_TP_ADD_TC(tp, bpfjit_copx_no_ctx);
656 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_A);
657 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_buflen);
658 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_wirelen);
659 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_nfuncs);
660 ATF_TP_ADD_TC(tp, bpfjit_copx_side_effect);
661 ATF_TP_ADD_TC(tp, bpfjit_copx_invalid_index);
662
663 return atf_no_error();
664 }
665