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