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