1/*	$NetBSD: h_bpf.h,v 1.2 2014/07/08 21:44:26 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
29#ifndef _TESTS_NET_BPF_H_BPF_H_
30#define _TESTS_NET_BPF_H_BPF_H_
31
32#include <sys/param.h>
33#include <sys/mbuf.h>
34
35#include <net/bpf.h>
36#include <net/bpfjit.h>
37
38#include <rump/rump.h>
39#include <rump/rump_syscalls.h>
40
41#include <stdint.h>
42#include <string.h>
43
44/* XXX These declarations don't look kosher. */
45int rumpns_bpf_validate(const struct bpf_insn *, int);
46unsigned int rumpns_bpf_filter_ext(const bpf_ctx_t *,
47    const struct bpf_insn *, bpf_args_t *);
48bpfjit_func_t rumpns_bpfjit_generate_code(const bpf_ctx_t *,
49    const struct bpf_insn *, size_t);
50void rumpns_bpfjit_free_code(bpfjit_func_t);
51
52/*
53 * Init mbuf chain with one or two chunks. The first chunk holds
54 * [pkt, pkt + split] bytes, the second chunk (if it's not empty)
55 * holds (pkt + split, pkt + pktsize) bytes.
56 * The function returns (const uint8_t *)mb1.
57 */
58static inline const uint8_t *
59init_mchain2(struct mbuf *mb1, struct mbuf *mb2,
60    unsigned char pkt[], size_t pktsize, size_t split)
61{
62
63	(void)memset(mb1, 0, sizeof(*mb1));
64	mb1->m_data = (char *)pkt;
65	mb1->m_next = (split < pktsize) ? mb2 : NULL;
66	mb1->m_len = (split < pktsize) ? split : pktsize;
67
68	if (split < pktsize) {
69		(void)memset(mb2, 0, sizeof(*mb2));
70		mb2->m_next = NULL;
71		mb2->m_data = (char *)&pkt[split];
72		mb2->m_len = pktsize - split;
73	}
74
75	return (const uint8_t*)mb1;
76}
77
78/*
79 * Compile and run a filter program.
80 */
81static inline unsigned int
82exec_prog(struct bpf_insn *insns, size_t insn_count,
83    unsigned char pkt[], size_t pktsize)
84{
85	bpfjit_func_t fn;
86	bpf_args_t args;
87	unsigned int res;
88
89	args.pkt = (const uint8_t *)pkt;
90	args.buflen = pktsize;
91	args.wirelen = pktsize;
92
93	rump_schedule();
94	fn = rumpns_bpfjit_generate_code(NULL, insns, insn_count);
95	rump_unschedule();
96
97	res = fn(NULL, &args);
98
99	rump_schedule();
100	rumpns_bpfjit_free_code(fn);
101	rump_unschedule();
102
103	return res;
104}
105
106/*
107 * Interpret a filter program with mbuf chain passed to bpf_filter_ext().
108 */
109static inline unsigned int
110interp_prog_mchain2(struct bpf_insn *insns,
111    unsigned char pkt[], size_t pktsize, size_t split)
112{
113	uint32_t mem[BPF_MEMWORDS];
114	struct mbuf mb1, mb2;
115	bpf_args_t args;
116	unsigned int res;
117
118	args.pkt = init_mchain2(&mb1, &mb2, pkt, pktsize, split);
119	args.buflen = 0;
120	args.wirelen = pktsize;
121	args.mem = mem;
122
123	rump_schedule();
124	res = rumpns_bpf_filter_ext(NULL, insns, &args);
125	rump_unschedule();
126
127	return res;
128}
129
130/*
131 * Compile and run a filter program with mbuf chain passed to compiled function.
132 */
133static inline unsigned int
134exec_prog_mchain2(struct bpf_insn *insns, size_t insn_count,
135    unsigned char pkt[], size_t pktsize, size_t split)
136{
137	bpfjit_func_t fn;
138	struct mbuf mb1, mb2;
139	bpf_args_t args;
140	unsigned int res;
141
142	args.pkt = init_mchain2(&mb1, &mb2, pkt, pktsize, split);
143	args.buflen = 0;
144	args.wirelen = pktsize;
145
146	rump_schedule();
147	fn = rumpns_bpfjit_generate_code(NULL, insns, insn_count);
148	rump_unschedule();
149
150	res = fn(NULL, &args);
151
152	rump_schedule();
153	rumpns_bpfjit_free_code(fn);
154	rump_unschedule();
155
156	return res;
157}
158
159static inline bool
160prog_validate(struct bpf_insn *insns, size_t insn_count)
161{
162	bool res;
163
164	rump_schedule();
165	res = rumpns_bpf_validate(insns, insn_count);
166	rump_unschedule();
167
168	return res;
169}
170
171#endif /* _TESTS_NET_BPF_H_BPF_H_ */
172