if_virt.c revision 1.55 1 1.55 msaitoh /* $NetBSD: if_virt.c,v 1.55 2017/10/23 09:24:34 msaitoh 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.55 msaitoh __KERNEL_RCSID(0, "$NetBSD: if_virt.c,v 1.55 2017/10/23 09:24:34 msaitoh 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.44 pooka #include <sys/module.h>
36 1.1 pooka
37 1.15 pooka #include <net/bpf.h>
38 1.1 pooka #include <net/if.h>
39 1.39 pooka #include <net/if_dl.h>
40 1.1 pooka #include <net/if_ether.h>
41 1.1 pooka
42 1.1 pooka #include <netinet/in.h>
43 1.1 pooka #include <netinet/in_var.h>
44 1.1 pooka
45 1.36 pooka #include "if_virt.h"
46 1.41 pooka #include "virtif_user.h"
47 1.30 pooka
48 1.1 pooka /*
49 1.32 pooka * Virtual interface. Uses hypercalls to shovel packets back
50 1.32 pooka * and forth. The exact method for shoveling depends on the
51 1.32 pooka * hypercall implementation.
52 1.1 pooka */
53 1.1 pooka
54 1.1 pooka static int virtif_init(struct ifnet *);
55 1.1 pooka static int virtif_ioctl(struct ifnet *, u_long, void *);
56 1.1 pooka static void virtif_start(struct ifnet *);
57 1.1 pooka static void virtif_stop(struct ifnet *, int);
58 1.1 pooka
59 1.1 pooka struct virtif_sc {
60 1.7 pooka struct ethercom sc_ec;
61 1.30 pooka struct virtif_user *sc_viu;
62 1.39 pooka
63 1.39 pooka int sc_num;
64 1.39 pooka char *sc_linkstr;
65 1.1 pooka };
66 1.1 pooka
67 1.20 pooka static int virtif_clone(struct if_clone *, int);
68 1.20 pooka static int virtif_unclone(struct ifnet *);
69 1.1 pooka
70 1.36 pooka struct if_clone VIF_CLONER =
71 1.36 pooka IF_CLONE_INITIALIZER(VIF_NAME, virtif_clone, virtif_unclone);
72 1.1 pooka
73 1.34 pooka static int
74 1.39 pooka virtif_create(struct ifnet *ifp)
75 1.1 pooka {
76 1.3 pooka uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0x0a, 0x00, 0x0b, 0x0e, 0x01 };
77 1.39 pooka char enaddrstr[3*ETHER_ADDR_LEN];
78 1.39 pooka struct virtif_sc *sc = ifp->if_softc;
79 1.39 pooka int error;
80 1.39 pooka
81 1.39 pooka if (sc->sc_viu)
82 1.39 pooka panic("%s: already created", ifp->if_xname);
83 1.21 pooka
84 1.39 pooka enaddr[2] = cprng_fast32() & 0xff;
85 1.39 pooka enaddr[5] = sc->sc_num & 0xff;
86 1.1 pooka
87 1.39 pooka if ((error = VIFHYPER_CREATE(sc->sc_linkstr,
88 1.39 pooka sc, enaddr, &sc->sc_viu)) != 0) {
89 1.39 pooka printf("VIFHYPER_CREATE failed: %d\n", error);
90 1.31 pooka return error;
91 1.39 pooka }
92 1.39 pooka
93 1.39 pooka ether_ifattach(ifp, enaddr);
94 1.39 pooka ether_snprintf(enaddrstr, sizeof(enaddrstr), enaddr);
95 1.39 pooka aprint_normal_ifnet(ifp, "Ethernet address %s\n", enaddrstr);
96 1.39 pooka
97 1.39 pooka IFQ_SET_READY(&ifp->if_snd);
98 1.30 pooka
99 1.39 pooka return 0;
100 1.39 pooka }
101 1.39 pooka
102 1.39 pooka static int
103 1.39 pooka virtif_clone(struct if_clone *ifc, int num)
104 1.39 pooka {
105 1.39 pooka struct virtif_sc *sc;
106 1.39 pooka struct ifnet *ifp;
107 1.39 pooka int error = 0;
108 1.1 pooka
109 1.1 pooka sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
110 1.39 pooka sc->sc_num = num;
111 1.7 pooka ifp = &sc->sc_ec.ec_if;
112 1.47 pooka
113 1.47 pooka if_initname(ifp, VIF_NAME, num);
114 1.1 pooka ifp->if_softc = sc;
115 1.21 pooka
116 1.1 pooka ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
117 1.1 pooka ifp->if_init = virtif_init;
118 1.1 pooka ifp->if_ioctl = virtif_ioctl;
119 1.1 pooka ifp->if_start = virtif_start;
120 1.1 pooka ifp->if_stop = virtif_stop;
121 1.39 pooka ifp->if_mtu = ETHERMTU;
122 1.39 pooka ifp->if_dlt = DLT_EN10MB;
123 1.1 pooka
124 1.55 msaitoh error = if_initialize(ifp);
125 1.55 msaitoh if (error != 0) {
126 1.55 msaitoh aprint_error("%s: if_initialize failed(%d)\n", ifp->if_xname,
127 1.55 msaitoh error);
128 1.55 msaitoh goto fail_1;
129 1.55 msaitoh }
130 1.55 msaitoh
131 1.50 ozaki if_register(ifp);
132 1.1 pooka
133 1.39 pooka #ifndef RUMP_VIF_LINKSTR
134 1.39 pooka /*
135 1.39 pooka * if the underlying interface does not expect linkstr, we can
136 1.39 pooka * create everything now. Otherwise, we need to wait for
137 1.39 pooka * SIOCSLINKSTR.
138 1.39 pooka */
139 1.39 pooka #define LINKSTRNUMLEN 16
140 1.39 pooka sc->sc_linkstr = kmem_alloc(LINKSTRNUMLEN, KM_SLEEP);
141 1.55 msaitoh if (sc->sc_linkstr == NULL) {
142 1.55 msaitoh error = ENOMEM;
143 1.55 msaitoh goto fail_2;
144 1.55 msaitoh }
145 1.39 pooka snprintf(sc->sc_linkstr, LINKSTRNUMLEN, "%d", sc->sc_num);
146 1.39 pooka #undef LINKSTRNUMLEN
147 1.39 pooka error = virtif_create(ifp);
148 1.21 pooka if (error) {
149 1.55 msaitoh fail_2:
150 1.39 pooka if_detach(ifp);
151 1.55 msaitoh if (sc->sc_linkstr != NULL)
152 1.55 msaitoh kmem_free(sc->sc_linkstr, LINKSTRNUMLEN);
153 1.55 msaitoh fail_1:
154 1.39 pooka kmem_free(sc, sizeof(*sc));
155 1.39 pooka ifp->if_softc = NULL;
156 1.21 pooka }
157 1.39 pooka #endif /* !RUMP_VIF_LINKSTR */
158 1.21 pooka
159 1.21 pooka return error;
160 1.1 pooka }
161 1.1 pooka
162 1.1 pooka static int
163 1.20 pooka virtif_unclone(struct ifnet *ifp)
164 1.20 pooka {
165 1.21 pooka struct virtif_sc *sc = ifp->if_softc;
166 1.42 pooka int rv;
167 1.20 pooka
168 1.39 pooka if (ifp->if_flags & IFF_UP)
169 1.39 pooka return EBUSY;
170 1.21 pooka
171 1.42 pooka if ((rv = VIFHYPER_DYING(sc->sc_viu)) != 0)
172 1.42 pooka return rv;
173 1.30 pooka
174 1.21 pooka virtif_stop(ifp, 1);
175 1.21 pooka if_down(ifp);
176 1.21 pooka
177 1.36 pooka VIFHYPER_DESTROY(sc->sc_viu);
178 1.21 pooka
179 1.21 pooka kmem_free(sc, sizeof(*sc));
180 1.21 pooka
181 1.21 pooka ether_ifdetach(ifp);
182 1.21 pooka if_detach(ifp);
183 1.21 pooka
184 1.21 pooka return 0;
185 1.20 pooka }
186 1.20 pooka
187 1.20 pooka static int
188 1.1 pooka virtif_init(struct ifnet *ifp)
189 1.1 pooka {
190 1.21 pooka struct virtif_sc *sc = ifp->if_softc;
191 1.1 pooka
192 1.39 pooka if (sc->sc_viu == NULL)
193 1.39 pooka return ENXIO;
194 1.39 pooka
195 1.1 pooka ifp->if_flags |= IFF_RUNNING;
196 1.1 pooka return 0;
197 1.1 pooka }
198 1.1 pooka
199 1.1 pooka static int
200 1.1 pooka virtif_ioctl(struct ifnet *ifp, u_long cmd, void *data)
201 1.1 pooka {
202 1.39 pooka struct virtif_sc *sc = ifp->if_softc;
203 1.39 pooka int rv;
204 1.1 pooka
205 1.39 pooka switch (cmd) {
206 1.39 pooka #ifdef RUMP_VIF_LINKSTR
207 1.39 pooka struct ifdrv *ifd;
208 1.39 pooka size_t linkstrlen;
209 1.39 pooka
210 1.39 pooka #ifndef RUMP_VIF_LINKSTRMAX
211 1.39 pooka #define RUMP_VIF_LINKSTRMAX 4096
212 1.39 pooka #endif
213 1.1 pooka
214 1.39 pooka case SIOCGLINKSTR:
215 1.39 pooka ifd = data;
216 1.1 pooka
217 1.39 pooka if (!sc->sc_linkstr) {
218 1.39 pooka rv = ENOENT;
219 1.39 pooka break;
220 1.39 pooka }
221 1.39 pooka linkstrlen = strlen(sc->sc_linkstr)+1;
222 1.1 pooka
223 1.39 pooka if (ifd->ifd_cmd == IFLINKSTR_QUERYLEN) {
224 1.39 pooka ifd->ifd_len = linkstrlen;
225 1.39 pooka rv = 0;
226 1.39 pooka break;
227 1.39 pooka }
228 1.39 pooka if (ifd->ifd_cmd != 0) {
229 1.39 pooka rv = ENOTTY;
230 1.39 pooka break;
231 1.39 pooka }
232 1.1 pooka
233 1.39 pooka rv = copyoutstr(sc->sc_linkstr,
234 1.39 pooka ifd->ifd_data, MIN(ifd->ifd_len,linkstrlen), NULL);
235 1.39 pooka break;
236 1.39 pooka case SIOCSLINKSTR:
237 1.39 pooka if (ifp->if_flags & IFF_UP) {
238 1.39 pooka rv = EBUSY;
239 1.39 pooka break;
240 1.39 pooka }
241 1.1 pooka
242 1.39 pooka ifd = data;
243 1.21 pooka
244 1.39 pooka if (ifd->ifd_cmd == IFLINKSTR_UNSET) {
245 1.39 pooka panic("unset linkstr not implemented");
246 1.39 pooka } else if (ifd->ifd_cmd != 0) {
247 1.39 pooka rv = ENOTTY;
248 1.39 pooka break;
249 1.39 pooka } else if (sc->sc_linkstr) {
250 1.39 pooka rv = EBUSY;
251 1.39 pooka break;
252 1.39 pooka }
253 1.1 pooka
254 1.39 pooka if (ifd->ifd_len > RUMP_VIF_LINKSTRMAX) {
255 1.39 pooka rv = E2BIG;
256 1.39 pooka break;
257 1.39 pooka } else if (ifd->ifd_len < 1) {
258 1.39 pooka rv = EINVAL;
259 1.39 pooka break;
260 1.39 pooka }
261 1.21 pooka
262 1.1 pooka
263 1.39 pooka sc->sc_linkstr = kmem_alloc(ifd->ifd_len, KM_SLEEP);
264 1.39 pooka rv = copyinstr(ifd->ifd_data, sc->sc_linkstr,
265 1.39 pooka ifd->ifd_len, NULL);
266 1.39 pooka if (rv) {
267 1.39 pooka kmem_free(sc->sc_linkstr, ifd->ifd_len);
268 1.21 pooka break;
269 1.21 pooka }
270 1.21 pooka
271 1.39 pooka rv = virtif_create(ifp);
272 1.39 pooka if (rv) {
273 1.39 pooka kmem_free(sc->sc_linkstr, ifd->ifd_len);
274 1.39 pooka }
275 1.39 pooka break;
276 1.39 pooka #endif /* RUMP_VIF_LINKSTR */
277 1.39 pooka default:
278 1.39 pooka if (!sc->sc_linkstr)
279 1.39 pooka rv = ENXIO;
280 1.39 pooka else
281 1.39 pooka rv = ether_ioctl(ifp, cmd, data);
282 1.39 pooka if (rv == ENETRESET)
283 1.39 pooka rv = 0;
284 1.39 pooka break;
285 1.1 pooka }
286 1.1 pooka
287 1.39 pooka return rv;
288 1.1 pooka }
289 1.8 pooka
290 1.39 pooka /*
291 1.39 pooka * Output packets in-context until outgoing queue is empty.
292 1.39 pooka * Leave responsibility of choosing whether or not to drop the
293 1.39 pooka * kernel lock to VIPHYPER_SEND().
294 1.39 pooka */
295 1.12 pooka #define LB_SH 32
296 1.8 pooka static void
297 1.39 pooka virtif_start(struct ifnet *ifp)
298 1.8 pooka {
299 1.8 pooka struct virtif_sc *sc = ifp->if_softc;
300 1.8 pooka struct mbuf *m, *m0;
301 1.30 pooka struct iovec io[LB_SH];
302 1.30 pooka int i;
303 1.8 pooka
304 1.39 pooka ifp->if_flags |= IFF_OACTIVE;
305 1.39 pooka
306 1.39 pooka for (;;) {
307 1.8 pooka IF_DEQUEUE(&ifp->if_snd, m0);
308 1.8 pooka if (!m0) {
309 1.39 pooka break;
310 1.8 pooka }
311 1.8 pooka
312 1.8 pooka m = m0;
313 1.40 pooka for (i = 0; i < LB_SH && m; ) {
314 1.40 pooka if (m->m_len) {
315 1.40 pooka io[i].iov_base = mtod(m, void *);
316 1.40 pooka io[i].iov_len = m->m_len;
317 1.40 pooka i++;
318 1.40 pooka }
319 1.8 pooka m = m->m_next;
320 1.8 pooka }
321 1.40 pooka if (i == LB_SH && m)
322 1.8 pooka panic("lazy bum");
323 1.17 joerg bpf_mtap(ifp, m0);
324 1.21 pooka
325 1.36 pooka VIFHYPER_SEND(sc->sc_viu, io, i);
326 1.21 pooka
327 1.8 pooka m_freem(m0);
328 1.48 ozaki ifp->if_opackets++;
329 1.8 pooka }
330 1.21 pooka
331 1.39 pooka ifp->if_flags &= ~IFF_OACTIVE;
332 1.39 pooka }
333 1.39 pooka
334 1.39 pooka static void
335 1.39 pooka virtif_stop(struct ifnet *ifp, int disable)
336 1.39 pooka {
337 1.39 pooka
338 1.39 pooka /* XXX: VIFHYPER_STOP() */
339 1.39 pooka
340 1.39 pooka ifp->if_flags &= ~IFF_RUNNING;
341 1.39 pooka }
342 1.39 pooka
343 1.39 pooka void
344 1.39 pooka VIF_DELIVERPKT(struct virtif_sc *sc, struct iovec *iov, size_t iovlen)
345 1.39 pooka {
346 1.39 pooka struct ifnet *ifp = &sc->sc_ec.ec_if;
347 1.39 pooka struct ether_header *eth;
348 1.39 pooka struct mbuf *m;
349 1.39 pooka size_t i;
350 1.39 pooka int off, olen;
351 1.39 pooka bool passup;
352 1.39 pooka const int align
353 1.39 pooka = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
354 1.39 pooka
355 1.39 pooka if ((ifp->if_flags & IFF_RUNNING) == 0)
356 1.39 pooka return;
357 1.39 pooka
358 1.39 pooka m = m_gethdr(M_NOWAIT, MT_DATA);
359 1.39 pooka if (m == NULL)
360 1.39 pooka return; /* drop packet */
361 1.39 pooka m->m_len = m->m_pkthdr.len = 0;
362 1.39 pooka
363 1.39 pooka for (i = 0, off = align; i < iovlen; i++) {
364 1.39 pooka olen = m->m_pkthdr.len;
365 1.39 pooka m_copyback(m, off, iov[i].iov_len, iov[i].iov_base);
366 1.39 pooka off += iov[i].iov_len;
367 1.39 pooka if (olen + off != m->m_pkthdr.len) {
368 1.39 pooka aprint_verbose_ifnet(ifp, "m_copyback failed\n");
369 1.39 pooka m_freem(m);
370 1.39 pooka return;
371 1.39 pooka }
372 1.39 pooka }
373 1.45 pooka m->m_data += align;
374 1.45 pooka m->m_pkthdr.len -= align;
375 1.45 pooka m->m_len -= align;
376 1.39 pooka
377 1.39 pooka eth = mtod(m, struct ether_header *);
378 1.39 pooka if (memcmp(eth->ether_dhost, CLLADDR(ifp->if_sadl),
379 1.39 pooka ETHER_ADDR_LEN) == 0) {
380 1.39 pooka passup = true;
381 1.39 pooka } else if (ETHER_IS_MULTICAST(eth->ether_dhost)) {
382 1.39 pooka passup = true;
383 1.39 pooka } else if (ifp->if_flags & IFF_PROMISC) {
384 1.39 pooka m->m_flags |= M_PROMISC;
385 1.39 pooka passup = true;
386 1.39 pooka } else {
387 1.39 pooka passup = false;
388 1.39 pooka }
389 1.8 pooka
390 1.39 pooka if (passup) {
391 1.53 ozaki int bound;
392 1.52 ozaki m_set_rcvif(m, ifp);
393 1.39 pooka KERNEL_LOCK(1, NULL);
394 1.51 ozaki /* Prevent LWP migrations between CPUs for psref(9) */
395 1.53 ozaki bound = curlwp_bind();
396 1.50 ozaki if_input(ifp, m);
397 1.53 ozaki curlwp_bindx(bound);
398 1.39 pooka KERNEL_UNLOCK_LAST(NULL);
399 1.39 pooka } else {
400 1.39 pooka m_freem(m);
401 1.39 pooka }
402 1.39 pooka m = NULL;
403 1.8 pooka }
404 1.44 pooka
405 1.49 pooka /*
406 1.49 pooka * The following ensures that no two modules using if_virt end up with
407 1.49 pooka * the same module name. MODULE() and modcmd wrapped in ... bad mojo.
408 1.49 pooka */
409 1.49 pooka #define VIF_MOJO(x) MODULE(MODULE_CLASS_DRIVER,x,NULL);
410 1.49 pooka #define VIF_MODULE() VIF_MOJO(VIF_BASENAME(if_virt_,VIRTIF_BASE))
411 1.49 pooka #define VIF_MODCMD VIF_BASENAME3(if_virt_,VIRTIF_BASE,_modcmd)
412 1.49 pooka VIF_MODULE();
413 1.44 pooka static int
414 1.49 pooka VIF_MODCMD(modcmd_t cmd, void *opaque)
415 1.44 pooka {
416 1.44 pooka int error = 0;
417 1.44 pooka
418 1.44 pooka switch (cmd) {
419 1.44 pooka case MODULE_CMD_INIT:
420 1.44 pooka if_clone_attach(&VIF_CLONER);
421 1.44 pooka break;
422 1.44 pooka case MODULE_CMD_FINI:
423 1.44 pooka /*
424 1.44 pooka * not sure if interfaces are refcounted
425 1.44 pooka * and properly protected
426 1.44 pooka */
427 1.44 pooka #if 0
428 1.44 pooka if_clone_detach(&VIF_CLONER);
429 1.44 pooka #else
430 1.44 pooka error = ENOTTY;
431 1.44 pooka #endif
432 1.44 pooka break;
433 1.44 pooka default:
434 1.44 pooka error = ENOTTY;
435 1.44 pooka }
436 1.44 pooka return error;
437 1.44 pooka }
438