xref: /minix3/tests/lib/libbpfjit/t_cop.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: t_cop.c,v 1.4 2014/07/13 21:35:33 alnsn Exp $ */
2*0a6a1f1dSLionel Sambuc 
3*0a6a1f1dSLionel Sambuc /*-
4*0a6a1f1dSLionel Sambuc  * Copyright (c) 2013-2014 Alexander Nasonov.
5*0a6a1f1dSLionel Sambuc  * All rights reserved.
6*0a6a1f1dSLionel Sambuc  *
7*0a6a1f1dSLionel Sambuc  * Redistribution and use in source and binary forms, with or without
8*0a6a1f1dSLionel Sambuc  * modification, are permitted provided that the following conditions
9*0a6a1f1dSLionel Sambuc  * are met:
10*0a6a1f1dSLionel Sambuc  *
11*0a6a1f1dSLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
12*0a6a1f1dSLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
13*0a6a1f1dSLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
14*0a6a1f1dSLionel Sambuc  *    notice, this list of conditions and the following disclaimer in
15*0a6a1f1dSLionel Sambuc  *    the documentation and/or other materials provided with the
16*0a6a1f1dSLionel Sambuc  *    distribution.
17*0a6a1f1dSLionel Sambuc  *
18*0a6a1f1dSLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19*0a6a1f1dSLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20*0a6a1f1dSLionel Sambuc  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21*0a6a1f1dSLionel Sambuc  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22*0a6a1f1dSLionel Sambuc  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23*0a6a1f1dSLionel Sambuc  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24*0a6a1f1dSLionel Sambuc  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*0a6a1f1dSLionel Sambuc  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26*0a6a1f1dSLionel Sambuc  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27*0a6a1f1dSLionel Sambuc  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28*0a6a1f1dSLionel Sambuc  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*0a6a1f1dSLionel Sambuc  * SUCH DAMAGE.
30*0a6a1f1dSLionel Sambuc  */
31*0a6a1f1dSLionel Sambuc 
32*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
33*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: t_cop.c,v 1.4 2014/07/13 21:35:33 alnsn Exp $");
34*0a6a1f1dSLionel Sambuc 
35*0a6a1f1dSLionel Sambuc #include <atf-c.h>
36*0a6a1f1dSLionel Sambuc #include <stdint.h>
37*0a6a1f1dSLionel Sambuc #include <string.h>
38*0a6a1f1dSLionel Sambuc 
39*0a6a1f1dSLionel Sambuc #define __BPF_PRIVATE
40*0a6a1f1dSLionel Sambuc #include <net/bpf.h>
41*0a6a1f1dSLionel Sambuc #include <net/bpfjit.h>
42*0a6a1f1dSLionel Sambuc 
43*0a6a1f1dSLionel Sambuc static uint32_t retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
44*0a6a1f1dSLionel Sambuc static uint32_t retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
45*0a6a1f1dSLionel Sambuc static uint32_t retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
46*0a6a1f1dSLionel Sambuc static uint32_t retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
47*0a6a1f1dSLionel Sambuc static uint32_t setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
48*0a6a1f1dSLionel Sambuc 
49*0a6a1f1dSLionel Sambuc static const bpf_copfunc_t copfuncs[] = {
50*0a6a1f1dSLionel Sambuc 	&retA,
51*0a6a1f1dSLionel Sambuc 	&retBL,
52*0a6a1f1dSLionel Sambuc 	&retWL,
53*0a6a1f1dSLionel Sambuc 	&retNF,
54*0a6a1f1dSLionel Sambuc 	&setARG
55*0a6a1f1dSLionel Sambuc };
56*0a6a1f1dSLionel Sambuc 
57*0a6a1f1dSLionel Sambuc static const bpf_ctx_t ctx = {
58*0a6a1f1dSLionel Sambuc 	.copfuncs = copfuncs,
59*0a6a1f1dSLionel Sambuc 	.nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]),
60*0a6a1f1dSLionel Sambuc 	.extwords = 0
61*0a6a1f1dSLionel Sambuc };
62*0a6a1f1dSLionel Sambuc 
63*0a6a1f1dSLionel Sambuc static uint32_t
retA(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)64*0a6a1f1dSLionel Sambuc retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
65*0a6a1f1dSLionel Sambuc {
66*0a6a1f1dSLionel Sambuc 
67*0a6a1f1dSLionel Sambuc 	return A;
68*0a6a1f1dSLionel Sambuc }
69*0a6a1f1dSLionel Sambuc 
70*0a6a1f1dSLionel Sambuc static uint32_t
retBL(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)71*0a6a1f1dSLionel Sambuc retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
72*0a6a1f1dSLionel Sambuc {
73*0a6a1f1dSLionel Sambuc 
74*0a6a1f1dSLionel Sambuc 	return args->buflen;
75*0a6a1f1dSLionel Sambuc }
76*0a6a1f1dSLionel Sambuc 
77*0a6a1f1dSLionel Sambuc static uint32_t
retWL(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)78*0a6a1f1dSLionel Sambuc retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
79*0a6a1f1dSLionel Sambuc {
80*0a6a1f1dSLionel Sambuc 
81*0a6a1f1dSLionel Sambuc 	return args->wirelen;
82*0a6a1f1dSLionel Sambuc }
83*0a6a1f1dSLionel Sambuc 
84*0a6a1f1dSLionel Sambuc static uint32_t
retNF(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)85*0a6a1f1dSLionel Sambuc retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
86*0a6a1f1dSLionel Sambuc {
87*0a6a1f1dSLionel Sambuc 
88*0a6a1f1dSLionel Sambuc 	return bc->nfuncs;
89*0a6a1f1dSLionel Sambuc }
90*0a6a1f1dSLionel Sambuc 
91*0a6a1f1dSLionel Sambuc /*
92*0a6a1f1dSLionel Sambuc  * COP function with a side effect.
93*0a6a1f1dSLionel Sambuc  */
94*0a6a1f1dSLionel Sambuc static uint32_t
setARG(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)95*0a6a1f1dSLionel Sambuc setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
96*0a6a1f1dSLionel Sambuc {
97*0a6a1f1dSLionel Sambuc 	bool *arg = (bool *)args->arg;
98*0a6a1f1dSLionel Sambuc 	bool old = *arg;
99*0a6a1f1dSLionel Sambuc 
100*0a6a1f1dSLionel Sambuc 	*arg = true;
101*0a6a1f1dSLionel Sambuc 	return old;
102*0a6a1f1dSLionel Sambuc }
103*0a6a1f1dSLionel Sambuc 
104*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_cop_no_ctx);
ATF_TC_HEAD(libbpfjit_cop_no_ctx,tc)105*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_cop_no_ctx, tc)
106*0a6a1f1dSLionel Sambuc {
107*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COP "
108*0a6a1f1dSLionel Sambuc 	    "instruction isn't valid without a context");
109*0a6a1f1dSLionel Sambuc }
110*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_cop_no_ctx,tc)111*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_cop_no_ctx, tc)
112*0a6a1f1dSLionel Sambuc {
113*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
114*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 0),
115*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_K, 7)
116*0a6a1f1dSLionel Sambuc 	};
117*0a6a1f1dSLionel Sambuc 
118*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
119*0a6a1f1dSLionel Sambuc 
120*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
121*0a6a1f1dSLionel Sambuc 
122*0a6a1f1dSLionel Sambuc 	ATF_CHECK(!bpf_validate(insns, insn_count));
123*0a6a1f1dSLionel Sambuc 
124*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(NULL, insns, insn_count);
125*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code == NULL);
126*0a6a1f1dSLionel Sambuc }
127*0a6a1f1dSLionel Sambuc 
128*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_cop_ret_A);
ATF_TC_HEAD(libbpfjit_cop_ret_A,tc)129*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_cop_ret_A, tc)
130*0a6a1f1dSLionel Sambuc {
131*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
132*0a6a1f1dSLionel Sambuc 	    "that returns a content of the A register");
133*0a6a1f1dSLionel Sambuc }
134*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_cop_ret_A,tc)135*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_cop_ret_A, tc)
136*0a6a1f1dSLionel Sambuc {
137*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
138*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
139*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 0), // retA
140*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
141*0a6a1f1dSLionel Sambuc 	};
142*0a6a1f1dSLionel Sambuc 
143*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
144*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
145*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
146*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
147*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
148*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt),
149*0a6a1f1dSLionel Sambuc 	};
150*0a6a1f1dSLionel Sambuc 
151*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
152*0a6a1f1dSLionel Sambuc 
153*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
154*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
155*0a6a1f1dSLionel Sambuc 
156*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == 13);
157*0a6a1f1dSLionel Sambuc 
158*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
159*0a6a1f1dSLionel Sambuc }
160*0a6a1f1dSLionel Sambuc 
161*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_cop_ret_buflen);
ATF_TC_HEAD(libbpfjit_cop_ret_buflen,tc)162*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_cop_ret_buflen, tc)
163*0a6a1f1dSLionel Sambuc {
164*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
165*0a6a1f1dSLionel Sambuc 	    "that returns the buflen argument");
166*0a6a1f1dSLionel Sambuc }
167*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_cop_ret_buflen,tc)168*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_cop_ret_buflen, tc)
169*0a6a1f1dSLionel Sambuc {
170*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
171*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
172*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 1), // retBL
173*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
174*0a6a1f1dSLionel Sambuc 	};
175*0a6a1f1dSLionel Sambuc 
176*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
177*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
178*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
179*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
180*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
181*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt)
182*0a6a1f1dSLionel Sambuc 	};
183*0a6a1f1dSLionel Sambuc 
184*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
185*0a6a1f1dSLionel Sambuc 
186*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
187*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
188*0a6a1f1dSLionel Sambuc 
189*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
190*0a6a1f1dSLionel Sambuc 
191*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
192*0a6a1f1dSLionel Sambuc }
193*0a6a1f1dSLionel Sambuc 
194*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_cop_ret_wirelen);
ATF_TC_HEAD(libbpfjit_cop_ret_wirelen,tc)195*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_cop_ret_wirelen, tc)
196*0a6a1f1dSLionel Sambuc {
197*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
198*0a6a1f1dSLionel Sambuc 	    "that returns the wirelen argument");
199*0a6a1f1dSLionel Sambuc }
200*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_cop_ret_wirelen,tc)201*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_cop_ret_wirelen, tc)
202*0a6a1f1dSLionel Sambuc {
203*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
204*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
205*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 2), // retWL
206*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
207*0a6a1f1dSLionel Sambuc 	};
208*0a6a1f1dSLionel Sambuc 
209*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
210*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
211*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
212*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
213*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
214*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt)
215*0a6a1f1dSLionel Sambuc 	};
216*0a6a1f1dSLionel Sambuc 
217*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
218*0a6a1f1dSLionel Sambuc 
219*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
220*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
221*0a6a1f1dSLionel Sambuc 
222*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
223*0a6a1f1dSLionel Sambuc 
224*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
225*0a6a1f1dSLionel Sambuc }
226*0a6a1f1dSLionel Sambuc 
227*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_cop_ret_nfuncs);
ATF_TC_HEAD(libbpfjit_cop_ret_nfuncs,tc)228*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_cop_ret_nfuncs, tc)
229*0a6a1f1dSLionel Sambuc {
230*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
231*0a6a1f1dSLionel Sambuc 	    "that returns nfuncs member of the context argument");
232*0a6a1f1dSLionel Sambuc }
233*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_cop_ret_nfuncs,tc)234*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_cop_ret_nfuncs, tc)
235*0a6a1f1dSLionel Sambuc {
236*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
237*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
238*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 3), // retNF
239*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
240*0a6a1f1dSLionel Sambuc 	};
241*0a6a1f1dSLionel Sambuc 
242*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
243*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
244*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
245*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
246*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
247*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt)
248*0a6a1f1dSLionel Sambuc 	};
249*0a6a1f1dSLionel Sambuc 
250*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
251*0a6a1f1dSLionel Sambuc 
252*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
253*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
254*0a6a1f1dSLionel Sambuc 
255*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == ctx.nfuncs);
256*0a6a1f1dSLionel Sambuc 
257*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
258*0a6a1f1dSLionel Sambuc }
259*0a6a1f1dSLionel Sambuc 
260*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_cop_side_effect);
ATF_TC_HEAD(libbpfjit_cop_side_effect,tc)261*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_cop_side_effect, tc)
262*0a6a1f1dSLionel Sambuc {
263*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr",
264*0a6a1f1dSLionel Sambuc 	    "Test that ABC optimization doesn't skip BPF_COP call");
265*0a6a1f1dSLionel Sambuc }
266*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_cop_side_effect,tc)267*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_cop_side_effect, tc)
268*0a6a1f1dSLionel Sambuc {
269*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
270*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
271*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),
272*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 4), // setARG
273*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999),
274*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
275*0a6a1f1dSLionel Sambuc 	};
276*0a6a1f1dSLionel Sambuc 
277*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
278*0a6a1f1dSLionel Sambuc 	bool arg = false;
279*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
280*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
281*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
282*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
283*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt),
284*0a6a1f1dSLionel Sambuc 		.mem = NULL,
285*0a6a1f1dSLionel Sambuc 		.arg = &arg
286*0a6a1f1dSLionel Sambuc 	};
287*0a6a1f1dSLionel Sambuc 
288*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
289*0a6a1f1dSLionel Sambuc 
290*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
291*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
292*0a6a1f1dSLionel Sambuc 
293*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == 0);
294*0a6a1f1dSLionel Sambuc 	ATF_CHECK(arg == true);
295*0a6a1f1dSLionel Sambuc 
296*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
297*0a6a1f1dSLionel Sambuc }
298*0a6a1f1dSLionel Sambuc 
299*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_cop_copx);
ATF_TC_HEAD(libbpfjit_cop_copx,tc)300*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_cop_copx, tc)
301*0a6a1f1dSLionel Sambuc {
302*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr",
303*0a6a1f1dSLionel Sambuc 	    "Test BPF_COP call followed by BPF_COPX call");
304*0a6a1f1dSLionel Sambuc }
305*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_cop_copx,tc)306*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_cop_copx, tc)
307*0a6a1f1dSLionel Sambuc {
308*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
309*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 1),         /* A <- 1    */
310*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 0),       /* retA      */
311*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_TAX, 0),       /* X <- A    */
312*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),   /* A = P[0]  */
313*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
314*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_TAX, 0),       /* X <- A    */
315*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COPX, 0),      /* retNF     */
316*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
317*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
318*0a6a1f1dSLionel Sambuc 	};
319*0a6a1f1dSLionel Sambuc 
320*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
321*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 2 };
322*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
323*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
324*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
325*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt),
326*0a6a1f1dSLionel Sambuc 	};
327*0a6a1f1dSLionel Sambuc 
328*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
329*0a6a1f1dSLionel Sambuc 
330*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
331*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
332*0a6a1f1dSLionel Sambuc 
333*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == 3 + ctx.nfuncs);
334*0a6a1f1dSLionel Sambuc 
335*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
336*0a6a1f1dSLionel Sambuc }
337*0a6a1f1dSLionel Sambuc 
338*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_cop_invalid_index);
ATF_TC_HEAD(libbpfjit_cop_invalid_index,tc)339*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_cop_invalid_index, tc)
340*0a6a1f1dSLionel Sambuc {
341*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr",
342*0a6a1f1dSLionel Sambuc 	    "Test that out-of-range coprocessor function fails validation");
343*0a6a1f1dSLionel Sambuc }
344*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_cop_invalid_index,tc)345*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_cop_invalid_index, tc)
346*0a6a1f1dSLionel Sambuc {
347*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
348*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
349*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 6), // invalid index
350*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_K, 27)
351*0a6a1f1dSLionel Sambuc 	};
352*0a6a1f1dSLionel Sambuc 
353*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
354*0a6a1f1dSLionel Sambuc 
355*0a6a1f1dSLionel Sambuc 	ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL);
356*0a6a1f1dSLionel Sambuc }
357*0a6a1f1dSLionel Sambuc 
358*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_copx_no_ctx);
ATF_TC_HEAD(libbpfjit_copx_no_ctx,tc)359*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_copx_no_ctx, tc)
360*0a6a1f1dSLionel Sambuc {
361*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COPX "
362*0a6a1f1dSLionel Sambuc 	    "instruction isn't valid without a context");
363*0a6a1f1dSLionel Sambuc }
364*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_copx_no_ctx,tc)365*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_copx_no_ctx, tc)
366*0a6a1f1dSLionel Sambuc {
367*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
368*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 0),
369*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_K, 7)
370*0a6a1f1dSLionel Sambuc 	};
371*0a6a1f1dSLionel Sambuc 
372*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
373*0a6a1f1dSLionel Sambuc 
374*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
375*0a6a1f1dSLionel Sambuc 
376*0a6a1f1dSLionel Sambuc 	ATF_CHECK(!bpf_validate(insns, insn_count));
377*0a6a1f1dSLionel Sambuc 
378*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(NULL, insns, insn_count);
379*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code == NULL);
380*0a6a1f1dSLionel Sambuc }
381*0a6a1f1dSLionel Sambuc 
382*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_copx_ret_A);
ATF_TC_HEAD(libbpfjit_copx_ret_A,tc)383*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_copx_ret_A, tc)
384*0a6a1f1dSLionel Sambuc {
385*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
386*0a6a1f1dSLionel Sambuc 	    "that returns a content of the A register");
387*0a6a1f1dSLionel Sambuc }
388*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_copx_ret_A,tc)389*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_copx_ret_A, tc)
390*0a6a1f1dSLionel Sambuc {
391*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
392*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
393*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LDX+BPF_IMM, 0), // retA
394*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
395*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
396*0a6a1f1dSLionel Sambuc 	};
397*0a6a1f1dSLionel Sambuc 
398*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
399*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
400*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
401*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
402*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
403*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt),
404*0a6a1f1dSLionel Sambuc 	};
405*0a6a1f1dSLionel Sambuc 
406*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
407*0a6a1f1dSLionel Sambuc 
408*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
409*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
410*0a6a1f1dSLionel Sambuc 
411*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == 13);
412*0a6a1f1dSLionel Sambuc 
413*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
414*0a6a1f1dSLionel Sambuc }
415*0a6a1f1dSLionel Sambuc 
416*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_copx_ret_buflen);
ATF_TC_HEAD(libbpfjit_copx_ret_buflen,tc)417*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_copx_ret_buflen, tc)
418*0a6a1f1dSLionel Sambuc {
419*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
420*0a6a1f1dSLionel Sambuc 	    "that returns the buflen argument");
421*0a6a1f1dSLionel Sambuc }
422*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_copx_ret_buflen,tc)423*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_copx_ret_buflen, tc)
424*0a6a1f1dSLionel Sambuc {
425*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
426*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
427*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LDX+BPF_IMM, 1), // retBL
428*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
429*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
430*0a6a1f1dSLionel Sambuc 	};
431*0a6a1f1dSLionel Sambuc 
432*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
433*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
434*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
435*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
436*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
437*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt)
438*0a6a1f1dSLionel Sambuc 	};
439*0a6a1f1dSLionel Sambuc 
440*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
441*0a6a1f1dSLionel Sambuc 
442*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
443*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
444*0a6a1f1dSLionel Sambuc 
445*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
446*0a6a1f1dSLionel Sambuc 
447*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
448*0a6a1f1dSLionel Sambuc }
449*0a6a1f1dSLionel Sambuc 
450*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_copx_ret_wirelen);
ATF_TC_HEAD(libbpfjit_copx_ret_wirelen,tc)451*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_copx_ret_wirelen, tc)
452*0a6a1f1dSLionel Sambuc {
453*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
454*0a6a1f1dSLionel Sambuc 	    "that returns the wirelen argument");
455*0a6a1f1dSLionel Sambuc }
456*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_copx_ret_wirelen,tc)457*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_copx_ret_wirelen, tc)
458*0a6a1f1dSLionel Sambuc {
459*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
460*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LDX+BPF_IMM, 2), // retWL
461*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
462*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
463*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
464*0a6a1f1dSLionel Sambuc 	};
465*0a6a1f1dSLionel Sambuc 
466*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
467*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
468*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
469*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
470*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
471*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt)
472*0a6a1f1dSLionel Sambuc 	};
473*0a6a1f1dSLionel Sambuc 
474*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
475*0a6a1f1dSLionel Sambuc 
476*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
477*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
478*0a6a1f1dSLionel Sambuc 
479*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
480*0a6a1f1dSLionel Sambuc 
481*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
482*0a6a1f1dSLionel Sambuc }
483*0a6a1f1dSLionel Sambuc 
484*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_copx_ret_nfuncs);
ATF_TC_HEAD(libbpfjit_copx_ret_nfuncs,tc)485*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_copx_ret_nfuncs, tc)
486*0a6a1f1dSLionel Sambuc {
487*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
488*0a6a1f1dSLionel Sambuc 	    "that returns nfuncs member of the context argument");
489*0a6a1f1dSLionel Sambuc }
490*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_copx_ret_nfuncs,tc)491*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_copx_ret_nfuncs, tc)
492*0a6a1f1dSLionel Sambuc {
493*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
494*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
495*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LDX+BPF_IMM, 3), // retNF
496*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
497*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
498*0a6a1f1dSLionel Sambuc 	};
499*0a6a1f1dSLionel Sambuc 
500*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
501*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
502*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
503*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
504*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
505*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt)
506*0a6a1f1dSLionel Sambuc 	};
507*0a6a1f1dSLionel Sambuc 
508*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
509*0a6a1f1dSLionel Sambuc 
510*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
511*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
512*0a6a1f1dSLionel Sambuc 
513*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == ctx.nfuncs);
514*0a6a1f1dSLionel Sambuc 
515*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
516*0a6a1f1dSLionel Sambuc }
517*0a6a1f1dSLionel Sambuc 
518*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_copx_side_effect);
ATF_TC_HEAD(libbpfjit_copx_side_effect,tc)519*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_copx_side_effect, tc)
520*0a6a1f1dSLionel Sambuc {
521*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr",
522*0a6a1f1dSLionel Sambuc 	    "Test that ABC optimization doesn't skip BPF_COPX call");
523*0a6a1f1dSLionel Sambuc }
524*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_copx_side_effect,tc)525*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_copx_side_effect, tc)
526*0a6a1f1dSLionel Sambuc {
527*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
528*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_IMM, 13),
529*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),
530*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LDX+BPF_IMM, 4), // setARG
531*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
532*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999),
533*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
534*0a6a1f1dSLionel Sambuc 	};
535*0a6a1f1dSLionel Sambuc 
536*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
537*0a6a1f1dSLionel Sambuc 	bool arg = false;
538*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
539*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
540*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
541*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
542*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt),
543*0a6a1f1dSLionel Sambuc 		.mem = NULL,
544*0a6a1f1dSLionel Sambuc 		.arg = &arg
545*0a6a1f1dSLionel Sambuc 	};
546*0a6a1f1dSLionel Sambuc 
547*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
548*0a6a1f1dSLionel Sambuc 
549*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
550*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
551*0a6a1f1dSLionel Sambuc 
552*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == 0);
553*0a6a1f1dSLionel Sambuc 	ATF_CHECK(arg == true);
554*0a6a1f1dSLionel Sambuc 
555*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
556*0a6a1f1dSLionel Sambuc }
557*0a6a1f1dSLionel Sambuc 
558*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_copx_cop);
ATF_TC_HEAD(libbpfjit_copx_cop,tc)559*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_copx_cop, tc)
560*0a6a1f1dSLionel Sambuc {
561*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr",
562*0a6a1f1dSLionel Sambuc 	    "Test BPF_COPX call followed by BPF_COP call");
563*0a6a1f1dSLionel Sambuc }
564*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_copx_cop,tc)565*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_copx_cop, tc)
566*0a6a1f1dSLionel Sambuc {
567*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
568*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LDX+BPF_IMM, 2),        /* X <- 2    */
569*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COPX, 0),      /* retWL     */
570*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
571*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_TAX, 0),       /* X <- A    */
572*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),   /* A = P[0]  */
573*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
574*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_TAX, 0),       /* X <- A    */
575*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COP, 3),      /* retNF     */
576*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
577*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_A, 0)
578*0a6a1f1dSLionel Sambuc 	};
579*0a6a1f1dSLionel Sambuc 
580*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
581*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 2 };
582*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
583*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
584*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
585*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt),
586*0a6a1f1dSLionel Sambuc 	};
587*0a6a1f1dSLionel Sambuc 
588*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
589*0a6a1f1dSLionel Sambuc 
590*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
591*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
592*0a6a1f1dSLionel Sambuc 
593*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == 5 + ctx.nfuncs);
594*0a6a1f1dSLionel Sambuc 
595*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
596*0a6a1f1dSLionel Sambuc }
597*0a6a1f1dSLionel Sambuc 
598*0a6a1f1dSLionel Sambuc ATF_TC(libbpfjit_copx_invalid_index);
ATF_TC_HEAD(libbpfjit_copx_invalid_index,tc)599*0a6a1f1dSLionel Sambuc ATF_TC_HEAD(libbpfjit_copx_invalid_index, tc)
600*0a6a1f1dSLionel Sambuc {
601*0a6a1f1dSLionel Sambuc 	atf_tc_set_md_var(tc, "descr",
602*0a6a1f1dSLionel Sambuc 	    "Test that out-of-range BPF_COPX call fails at runtime");
603*0a6a1f1dSLionel Sambuc }
604*0a6a1f1dSLionel Sambuc 
ATF_TC_BODY(libbpfjit_copx_invalid_index,tc)605*0a6a1f1dSLionel Sambuc ATF_TC_BODY(libbpfjit_copx_invalid_index, tc)
606*0a6a1f1dSLionel Sambuc {
607*0a6a1f1dSLionel Sambuc 	static struct bpf_insn insns[] = {
608*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_LDX+BPF_IMM, 5), // invalid index
609*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
610*0a6a1f1dSLionel Sambuc 		BPF_STMT(BPF_RET+BPF_K, 27)
611*0a6a1f1dSLionel Sambuc 	};
612*0a6a1f1dSLionel Sambuc 
613*0a6a1f1dSLionel Sambuc 	bpfjit_func_t code;
614*0a6a1f1dSLionel Sambuc 	uint8_t pkt[1] = { 0 };
615*0a6a1f1dSLionel Sambuc 	bpf_args_t args = {
616*0a6a1f1dSLionel Sambuc 		.pkt = pkt,
617*0a6a1f1dSLionel Sambuc 		.buflen = sizeof(pkt),
618*0a6a1f1dSLionel Sambuc 		.wirelen = sizeof(pkt)
619*0a6a1f1dSLionel Sambuc 	};
620*0a6a1f1dSLionel Sambuc 
621*0a6a1f1dSLionel Sambuc 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
622*0a6a1f1dSLionel Sambuc 
623*0a6a1f1dSLionel Sambuc 	code = bpfjit_generate_code(&ctx, insns, insn_count);
624*0a6a1f1dSLionel Sambuc 	ATF_REQUIRE(code != NULL);
625*0a6a1f1dSLionel Sambuc 
626*0a6a1f1dSLionel Sambuc 	ATF_CHECK(code(&ctx, &args) == 0);
627*0a6a1f1dSLionel Sambuc 
628*0a6a1f1dSLionel Sambuc 	bpfjit_free_code(code);
629*0a6a1f1dSLionel Sambuc }
630*0a6a1f1dSLionel Sambuc 
ATF_TP_ADD_TCS(tp)631*0a6a1f1dSLionel Sambuc ATF_TP_ADD_TCS(tp)
632*0a6a1f1dSLionel Sambuc {
633*0a6a1f1dSLionel Sambuc 
634*0a6a1f1dSLionel Sambuc 	/*
635*0a6a1f1dSLionel Sambuc 	 * For every new test please also add a similar test
636*0a6a1f1dSLionel Sambuc 	 * to ../../net/bpfjit/t_cop.c
637*0a6a1f1dSLionel Sambuc 	 */
638*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_cop_no_ctx);
639*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_A);
640*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_buflen);
641*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_wirelen);
642*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_nfuncs);
643*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_cop_side_effect);
644*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_cop_copx);
645*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_cop_invalid_index);
646*0a6a1f1dSLionel Sambuc 
647*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_copx_no_ctx);
648*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_A);
649*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_buflen);
650*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_wirelen);
651*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_nfuncs);
652*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_copx_side_effect);
653*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_copx_cop);
654*0a6a1f1dSLionel Sambuc 	ATF_TP_ADD_TC(tp, libbpfjit_copx_invalid_index);
655*0a6a1f1dSLionel Sambuc 
656*0a6a1f1dSLionel Sambuc 	return atf_no_error();
657*0a6a1f1dSLionel Sambuc }
658