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