if_virt.c revision 1.42 1 1.42 pooka /* $NetBSD: if_virt.c,v 1.42 2014/03/13 20:55:26 pooka Exp $ */
2 1.1 pooka
3 1.1 pooka /*
4 1.32 pooka * Copyright (c) 2008, 2013 Antti Kantee. All Rights Reserved.
5 1.1 pooka *
6 1.1 pooka * Redistribution and use in source and binary forms, with or without
7 1.1 pooka * modification, are permitted provided that the following conditions
8 1.1 pooka * are met:
9 1.1 pooka * 1. Redistributions of source code must retain the above copyright
10 1.1 pooka * notice, this list of conditions and the following disclaimer.
11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 pooka * notice, this list of conditions and the following disclaimer in the
13 1.1 pooka * documentation and/or other materials provided with the distribution.
14 1.1 pooka *
15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.1 pooka * SUCH DAMAGE.
26 1.1 pooka */
27 1.1 pooka
28 1.5 pooka #include <sys/cdefs.h>
29 1.42 pooka __KERNEL_RCSID(0, "$NetBSD: if_virt.c,v 1.42 2014/03/13 20:55:26 pooka Exp $");
30 1.5 pooka
31 1.1 pooka #include <sys/param.h>
32 1.21 pooka #include <sys/kernel.h>
33 1.1 pooka #include <sys/kmem.h>
34 1.26 tls #include <sys/cprng.h>
35 1.1 pooka
36 1.15 pooka #include <net/bpf.h>
37 1.1 pooka #include <net/if.h>
38 1.39 pooka #include <net/if_dl.h>
39 1.1 pooka #include <net/if_ether.h>
40 1.1 pooka
41 1.1 pooka #include <netinet/in.h>
42 1.1 pooka #include <netinet/in_var.h>
43 1.1 pooka
44 1.1 pooka #include <rump/rump.h>
45 1.1 pooka
46 1.1 pooka #include "rump_private.h"
47 1.10 pooka #include "rump_net_private.h"
48 1.1 pooka
49 1.36 pooka #include "if_virt.h"
50 1.41 pooka #include "virtif_user.h"
51 1.30 pooka
52 1.1 pooka /*
53 1.32 pooka * Virtual interface. Uses hypercalls to shovel packets back
54 1.32 pooka * and forth. The exact method for shoveling depends on the
55 1.32 pooka * hypercall implementation.
56 1.1 pooka */
57 1.1 pooka
58 1.1 pooka static int virtif_init(struct ifnet *);
59 1.1 pooka static int virtif_ioctl(struct ifnet *, u_long, void *);
60 1.1 pooka static void virtif_start(struct ifnet *);
61 1.1 pooka static void virtif_stop(struct ifnet *, int);
62 1.1 pooka
63 1.1 pooka struct virtif_sc {
64 1.7 pooka struct ethercom sc_ec;
65 1.30 pooka struct virtif_user *sc_viu;
66 1.39 pooka
67 1.39 pooka int sc_num;
68 1.39 pooka char *sc_linkstr;
69 1.1 pooka };
70 1.1 pooka
71 1.20 pooka static int virtif_clone(struct if_clone *, int);
72 1.20 pooka static int virtif_unclone(struct ifnet *);
73 1.1 pooka
74 1.36 pooka struct if_clone VIF_CLONER =
75 1.36 pooka IF_CLONE_INITIALIZER(VIF_NAME, virtif_clone, virtif_unclone);
76 1.1 pooka
77 1.34 pooka static int
78 1.39 pooka virtif_create(struct ifnet *ifp)
79 1.1 pooka {
80 1.3 pooka uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0x0a, 0x00, 0x0b, 0x0e, 0x01 };
81 1.39 pooka char enaddrstr[3*ETHER_ADDR_LEN];
82 1.39 pooka struct virtif_sc *sc = ifp->if_softc;
83 1.39 pooka int error;
84 1.39 pooka
85 1.39 pooka if (sc->sc_viu)
86 1.39 pooka panic("%s: already created", ifp->if_xname);
87 1.21 pooka
88 1.39 pooka enaddr[2] = cprng_fast32() & 0xff;
89 1.39 pooka enaddr[5] = sc->sc_num & 0xff;
90 1.1 pooka
91 1.39 pooka if ((error = VIFHYPER_CREATE(sc->sc_linkstr,
92 1.39 pooka sc, enaddr, &sc->sc_viu)) != 0) {
93 1.39 pooka printf("VIFHYPER_CREATE failed: %d\n", error);
94 1.31 pooka return error;
95 1.39 pooka }
96 1.39 pooka
97 1.39 pooka ether_ifattach(ifp, enaddr);
98 1.39 pooka ether_snprintf(enaddrstr, sizeof(enaddrstr), enaddr);
99 1.39 pooka aprint_normal_ifnet(ifp, "Ethernet address %s\n", enaddrstr);
100 1.39 pooka
101 1.39 pooka IFQ_SET_READY(&ifp->if_snd);
102 1.30 pooka
103 1.39 pooka return 0;
104 1.39 pooka }
105 1.39 pooka
106 1.39 pooka static int
107 1.39 pooka virtif_clone(struct if_clone *ifc, int num)
108 1.39 pooka {
109 1.39 pooka struct virtif_sc *sc;
110 1.39 pooka struct ifnet *ifp;
111 1.39 pooka int error = 0;
112 1.1 pooka
113 1.1 pooka sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
114 1.39 pooka sc->sc_num = num;
115 1.7 pooka ifp = &sc->sc_ec.ec_if;
116 1.36 pooka sprintf(ifp->if_xname, "%s%d", VIF_NAME, num);
117 1.1 pooka ifp->if_softc = sc;
118 1.21 pooka
119 1.1 pooka ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
120 1.1 pooka ifp->if_init = virtif_init;
121 1.1 pooka ifp->if_ioctl = virtif_ioctl;
122 1.1 pooka ifp->if_start = virtif_start;
123 1.1 pooka ifp->if_stop = virtif_stop;
124 1.39 pooka ifp->if_mtu = ETHERMTU;
125 1.39 pooka ifp->if_dlt = DLT_EN10MB;
126 1.1 pooka
127 1.1 pooka if_attach(ifp);
128 1.1 pooka
129 1.39 pooka #ifndef RUMP_VIF_LINKSTR
130 1.39 pooka /*
131 1.39 pooka * if the underlying interface does not expect linkstr, we can
132 1.39 pooka * create everything now. Otherwise, we need to wait for
133 1.39 pooka * SIOCSLINKSTR.
134 1.39 pooka */
135 1.39 pooka #define LINKSTRNUMLEN 16
136 1.39 pooka sc->sc_linkstr = kmem_alloc(LINKSTRNUMLEN, KM_SLEEP);
137 1.39 pooka snprintf(sc->sc_linkstr, LINKSTRNUMLEN, "%d", sc->sc_num);
138 1.39 pooka #undef LINKSTRNUMLEN
139 1.39 pooka error = virtif_create(ifp);
140 1.21 pooka if (error) {
141 1.39 pooka if_detach(ifp);
142 1.39 pooka kmem_free(sc, sizeof(*sc));
143 1.39 pooka ifp->if_softc = NULL;
144 1.21 pooka }
145 1.39 pooka #endif /* !RUMP_VIF_LINKSTR */
146 1.21 pooka
147 1.21 pooka return error;
148 1.1 pooka }
149 1.1 pooka
150 1.1 pooka static int
151 1.20 pooka virtif_unclone(struct ifnet *ifp)
152 1.20 pooka {
153 1.21 pooka struct virtif_sc *sc = ifp->if_softc;
154 1.42 pooka int rv;
155 1.20 pooka
156 1.39 pooka if (ifp->if_flags & IFF_UP)
157 1.39 pooka return EBUSY;
158 1.21 pooka
159 1.42 pooka if ((rv = VIFHYPER_DYING(sc->sc_viu)) != 0)
160 1.42 pooka return rv;
161 1.30 pooka
162 1.21 pooka virtif_stop(ifp, 1);
163 1.21 pooka if_down(ifp);
164 1.21 pooka
165 1.36 pooka VIFHYPER_DESTROY(sc->sc_viu);
166 1.21 pooka
167 1.21 pooka kmem_free(sc, sizeof(*sc));
168 1.21 pooka
169 1.21 pooka ether_ifdetach(ifp);
170 1.21 pooka if_detach(ifp);
171 1.21 pooka
172 1.21 pooka return 0;
173 1.20 pooka }
174 1.20 pooka
175 1.20 pooka static int
176 1.1 pooka virtif_init(struct ifnet *ifp)
177 1.1 pooka {
178 1.21 pooka struct virtif_sc *sc = ifp->if_softc;
179 1.1 pooka
180 1.39 pooka if (sc->sc_viu == NULL)
181 1.39 pooka return ENXIO;
182 1.39 pooka
183 1.1 pooka ifp->if_flags |= IFF_RUNNING;
184 1.1 pooka return 0;
185 1.1 pooka }
186 1.1 pooka
187 1.1 pooka static int
188 1.1 pooka virtif_ioctl(struct ifnet *ifp, u_long cmd, void *data)
189 1.1 pooka {
190 1.39 pooka struct virtif_sc *sc = ifp->if_softc;
191 1.39 pooka int rv;
192 1.1 pooka
193 1.39 pooka switch (cmd) {
194 1.39 pooka #ifdef RUMP_VIF_LINKSTR
195 1.39 pooka struct ifdrv *ifd;
196 1.39 pooka size_t linkstrlen;
197 1.39 pooka
198 1.39 pooka #ifndef RUMP_VIF_LINKSTRMAX
199 1.39 pooka #define RUMP_VIF_LINKSTRMAX 4096
200 1.39 pooka #endif
201 1.1 pooka
202 1.39 pooka case SIOCGLINKSTR:
203 1.39 pooka ifd = data;
204 1.1 pooka
205 1.39 pooka if (!sc->sc_linkstr) {
206 1.39 pooka rv = ENOENT;
207 1.39 pooka break;
208 1.39 pooka }
209 1.39 pooka linkstrlen = strlen(sc->sc_linkstr)+1;
210 1.1 pooka
211 1.39 pooka if (ifd->ifd_cmd == IFLINKSTR_QUERYLEN) {
212 1.39 pooka ifd->ifd_len = linkstrlen;
213 1.39 pooka rv = 0;
214 1.39 pooka break;
215 1.39 pooka }
216 1.39 pooka if (ifd->ifd_cmd != 0) {
217 1.39 pooka rv = ENOTTY;
218 1.39 pooka break;
219 1.39 pooka }
220 1.1 pooka
221 1.39 pooka rv = copyoutstr(sc->sc_linkstr,
222 1.39 pooka ifd->ifd_data, MIN(ifd->ifd_len,linkstrlen), NULL);
223 1.39 pooka break;
224 1.39 pooka case SIOCSLINKSTR:
225 1.39 pooka if (ifp->if_flags & IFF_UP) {
226 1.39 pooka rv = EBUSY;
227 1.39 pooka break;
228 1.39 pooka }
229 1.1 pooka
230 1.39 pooka ifd = data;
231 1.21 pooka
232 1.39 pooka if (ifd->ifd_cmd == IFLINKSTR_UNSET) {
233 1.39 pooka panic("unset linkstr not implemented");
234 1.39 pooka } else if (ifd->ifd_cmd != 0) {
235 1.39 pooka rv = ENOTTY;
236 1.39 pooka break;
237 1.39 pooka } else if (sc->sc_linkstr) {
238 1.39 pooka rv = EBUSY;
239 1.39 pooka break;
240 1.39 pooka }
241 1.1 pooka
242 1.39 pooka if (ifd->ifd_len > RUMP_VIF_LINKSTRMAX) {
243 1.39 pooka rv = E2BIG;
244 1.39 pooka break;
245 1.39 pooka } else if (ifd->ifd_len < 1) {
246 1.39 pooka rv = EINVAL;
247 1.39 pooka break;
248 1.39 pooka }
249 1.21 pooka
250 1.1 pooka
251 1.39 pooka sc->sc_linkstr = kmem_alloc(ifd->ifd_len, KM_SLEEP);
252 1.39 pooka rv = copyinstr(ifd->ifd_data, sc->sc_linkstr,
253 1.39 pooka ifd->ifd_len, NULL);
254 1.39 pooka if (rv) {
255 1.39 pooka kmem_free(sc->sc_linkstr, ifd->ifd_len);
256 1.21 pooka break;
257 1.21 pooka }
258 1.21 pooka
259 1.39 pooka rv = virtif_create(ifp);
260 1.39 pooka if (rv) {
261 1.39 pooka kmem_free(sc->sc_linkstr, ifd->ifd_len);
262 1.39 pooka }
263 1.39 pooka break;
264 1.39 pooka #endif /* RUMP_VIF_LINKSTR */
265 1.39 pooka default:
266 1.39 pooka if (!sc->sc_linkstr)
267 1.39 pooka rv = ENXIO;
268 1.39 pooka else
269 1.39 pooka rv = ether_ioctl(ifp, cmd, data);
270 1.39 pooka if (rv == ENETRESET)
271 1.39 pooka rv = 0;
272 1.39 pooka break;
273 1.1 pooka }
274 1.1 pooka
275 1.39 pooka return rv;
276 1.1 pooka }
277 1.8 pooka
278 1.39 pooka /*
279 1.39 pooka * Output packets in-context until outgoing queue is empty.
280 1.39 pooka * Leave responsibility of choosing whether or not to drop the
281 1.39 pooka * kernel lock to VIPHYPER_SEND().
282 1.39 pooka */
283 1.12 pooka #define LB_SH 32
284 1.8 pooka static void
285 1.39 pooka virtif_start(struct ifnet *ifp)
286 1.8 pooka {
287 1.8 pooka struct virtif_sc *sc = ifp->if_softc;
288 1.8 pooka struct mbuf *m, *m0;
289 1.30 pooka struct iovec io[LB_SH];
290 1.30 pooka int i;
291 1.8 pooka
292 1.39 pooka ifp->if_flags |= IFF_OACTIVE;
293 1.39 pooka
294 1.39 pooka for (;;) {
295 1.8 pooka IF_DEQUEUE(&ifp->if_snd, m0);
296 1.8 pooka if (!m0) {
297 1.39 pooka break;
298 1.8 pooka }
299 1.8 pooka
300 1.8 pooka m = m0;
301 1.40 pooka for (i = 0; i < LB_SH && m; ) {
302 1.40 pooka if (m->m_len) {
303 1.40 pooka io[i].iov_base = mtod(m, void *);
304 1.40 pooka io[i].iov_len = m->m_len;
305 1.40 pooka i++;
306 1.40 pooka }
307 1.8 pooka m = m->m_next;
308 1.8 pooka }
309 1.40 pooka if (i == LB_SH && m)
310 1.8 pooka panic("lazy bum");
311 1.17 joerg bpf_mtap(ifp, m0);
312 1.21 pooka
313 1.36 pooka VIFHYPER_SEND(sc->sc_viu, io, i);
314 1.21 pooka
315 1.8 pooka m_freem(m0);
316 1.8 pooka }
317 1.21 pooka
318 1.39 pooka ifp->if_flags &= ~IFF_OACTIVE;
319 1.39 pooka }
320 1.39 pooka
321 1.39 pooka static void
322 1.39 pooka virtif_stop(struct ifnet *ifp, int disable)
323 1.39 pooka {
324 1.39 pooka
325 1.39 pooka /* XXX: VIFHYPER_STOP() */
326 1.39 pooka
327 1.39 pooka ifp->if_flags &= ~IFF_RUNNING;
328 1.39 pooka }
329 1.39 pooka
330 1.39 pooka void
331 1.39 pooka VIF_DELIVERPKT(struct virtif_sc *sc, struct iovec *iov, size_t iovlen)
332 1.39 pooka {
333 1.39 pooka struct ifnet *ifp = &sc->sc_ec.ec_if;
334 1.39 pooka struct ether_header *eth;
335 1.39 pooka struct mbuf *m;
336 1.39 pooka size_t i;
337 1.39 pooka int off, olen;
338 1.39 pooka bool passup;
339 1.39 pooka const int align
340 1.39 pooka = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
341 1.39 pooka
342 1.39 pooka if ((ifp->if_flags & IFF_RUNNING) == 0)
343 1.39 pooka return;
344 1.39 pooka
345 1.39 pooka m = m_gethdr(M_NOWAIT, MT_DATA);
346 1.39 pooka if (m == NULL)
347 1.39 pooka return; /* drop packet */
348 1.39 pooka m->m_len = m->m_pkthdr.len = 0;
349 1.39 pooka
350 1.39 pooka for (i = 0, off = align; i < iovlen; i++) {
351 1.39 pooka olen = m->m_pkthdr.len;
352 1.39 pooka m_copyback(m, off, iov[i].iov_len, iov[i].iov_base);
353 1.39 pooka off += iov[i].iov_len;
354 1.39 pooka if (olen + off != m->m_pkthdr.len) {
355 1.39 pooka aprint_verbose_ifnet(ifp, "m_copyback failed\n");
356 1.39 pooka m_freem(m);
357 1.39 pooka return;
358 1.39 pooka }
359 1.39 pooka }
360 1.39 pooka
361 1.39 pooka m->m_data += align;
362 1.39 pooka eth = mtod(m, struct ether_header *);
363 1.39 pooka if (memcmp(eth->ether_dhost, CLLADDR(ifp->if_sadl),
364 1.39 pooka ETHER_ADDR_LEN) == 0) {
365 1.39 pooka passup = true;
366 1.39 pooka } else if (ETHER_IS_MULTICAST(eth->ether_dhost)) {
367 1.39 pooka passup = true;
368 1.39 pooka } else if (ifp->if_flags & IFF_PROMISC) {
369 1.39 pooka m->m_flags |= M_PROMISC;
370 1.39 pooka passup = true;
371 1.39 pooka } else {
372 1.39 pooka passup = false;
373 1.39 pooka }
374 1.8 pooka
375 1.39 pooka if (passup) {
376 1.39 pooka m->m_pkthdr.rcvif = ifp;
377 1.39 pooka KERNEL_LOCK(1, NULL);
378 1.39 pooka bpf_mtap(ifp, m);
379 1.39 pooka ifp->if_input(ifp, m);
380 1.39 pooka KERNEL_UNLOCK_LAST(NULL);
381 1.39 pooka } else {
382 1.39 pooka m_freem(m);
383 1.39 pooka }
384 1.39 pooka m = NULL;
385 1.8 pooka }
386