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