if_shmem.c revision 1.73 1 /* $NetBSD: if_shmem.c,v 1.73 2017/10/23 09:31:18 msaitoh Exp $ */
2
3 /*
4 * Copyright (c) 2009, 2010 Antti Kantee. All Rights Reserved.
5 *
6 * Development of this software was supported by The Nokia Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.73 2017/10/23 09:31:18 msaitoh Exp $");
32
33 #include <sys/param.h>
34 #include <sys/atomic.h>
35 #include <sys/fcntl.h>
36 #include <sys/kmem.h>
37 #include <sys/kthread.h>
38 #include <sys/lock.h>
39 #include <sys/vmem.h>
40 #include <sys/cprng.h>
41
42 #include <net/bpf.h>
43 #include <net/if.h>
44 #include <net/if_dl.h>
45 #include <net/if_ether.h>
46
47 #include <netinet/in.h>
48 #include <netinet/in_var.h>
49
50 #include <rump-sys/kern.h>
51 #include <rump-sys/net.h>
52
53 #include <rump/rump.h>
54 #include <rump/rumpuser.h>
55
56 #include "shmif_user.h"
57
58 static int shmif_clone(struct if_clone *, int);
59 static int shmif_unclone(struct ifnet *);
60
61 struct if_clone shmif_cloner =
62 IF_CLONE_INITIALIZER("shmif", shmif_clone, shmif_unclone);
63
64 /*
65 * Do r/w prefault for backend pages when attaching the interface.
66 * At least logically thinking improves performance (although no
67 * mlocking is done, so they might go away).
68 */
69 #define PREFAULT_RW
70
71 /*
72 * A virtual ethernet interface which uses shared memory from a
73 * memory mapped file as the bus.
74 */
75
76 static int shmif_init(struct ifnet *);
77 static int shmif_ioctl(struct ifnet *, u_long, void *);
78 static void shmif_start(struct ifnet *);
79 static void shmif_stop(struct ifnet *, int);
80
81 #include "shmifvar.h"
82
83 struct shmif_sc {
84 struct ethercom sc_ec;
85 struct shmif_mem *sc_busmem;
86 int sc_memfd;
87 int sc_kq;
88 int sc_unit;
89
90 char *sc_backfile;
91 size_t sc_backfilelen;
92
93 uint64_t sc_devgen;
94 uint32_t sc_nextpacket;
95
96 kmutex_t sc_mtx;
97 kcondvar_t sc_cv;
98
99 struct lwp *sc_rcvl;
100 bool sc_dying;
101
102 uint64_t sc_uuid;
103 };
104
105 static void shmif_rcv(void *);
106
107 #define LOCK_UNLOCKED 0
108 #define LOCK_LOCKED 1
109 #define LOCK_COOLDOWN 1001
110
111 vmem_t *shmif_units;
112
113 static void
114 dowakeup(struct shmif_sc *sc)
115 {
116 struct rumpuser_iovec iov;
117 uint32_t ver = SHMIF_VERSION;
118 size_t n;
119
120 iov.iov_base = &ver;
121 iov.iov_len = sizeof(ver);
122 rumpuser_iovwrite(sc->sc_memfd, &iov, 1, IFMEM_WAKEUP, &n);
123 }
124
125 /*
126 * This locking needs work and will misbehave severely if:
127 * 1) the backing memory has to be paged in
128 * 2) some lockholder exits while holding the lock
129 */
130 static void
131 shmif_lockbus(struct shmif_mem *busmem)
132 {
133 int i = 0;
134
135 while (__predict_false(atomic_cas_32(&busmem->shm_lock,
136 LOCK_UNLOCKED, LOCK_LOCKED) == LOCK_LOCKED)) {
137 if (__predict_false(++i > LOCK_COOLDOWN)) {
138 /* wait 1ms */
139 rumpuser_clock_sleep(RUMPUSER_CLOCK_RELWALL,
140 0, 1000*1000);
141 i = 0;
142 }
143 continue;
144 }
145 membar_enter();
146 }
147
148 static void
149 shmif_unlockbus(struct shmif_mem *busmem)
150 {
151 unsigned int old __diagused;
152
153 membar_exit();
154 old = atomic_swap_32(&busmem->shm_lock, LOCK_UNLOCKED);
155 KASSERT(old == LOCK_LOCKED);
156 }
157
158 static int
159 allocif(int unit, struct shmif_sc **scp)
160 {
161 uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0xa0, 0x00, 0x00, 0x00, 0x00 };
162 struct shmif_sc *sc;
163 struct ifnet *ifp;
164 uint32_t randnum;
165 int error;
166
167 randnum = cprng_fast32();
168 memcpy(&enaddr[2], &randnum, sizeof(randnum));
169
170 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
171 sc->sc_memfd = -1;
172 sc->sc_unit = unit;
173 sc->sc_uuid = cprng_fast64();
174
175 ifp = &sc->sc_ec.ec_if;
176
177 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "shmif%d", unit);
178 ifp->if_softc = sc;
179 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
180 ifp->if_init = shmif_init;
181 ifp->if_ioctl = shmif_ioctl;
182 ifp->if_start = shmif_start;
183 ifp->if_stop = shmif_stop;
184 ifp->if_mtu = ETHERMTU;
185 ifp->if_dlt = DLT_EN10MB;
186
187 mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
188 cv_init(&sc->sc_cv, "shmifcv");
189
190 error = if_initialize(ifp);
191 if (error != 0) {
192 aprint_error("shmif%d: if_initialize failed(%d)\n", unit, rv);
193 cv_destroy(&sc->sc_cv);
194 mutex_destroy(&sc->sc_mtx);
195 kmem_free(sc, sizeof(*sc));
196
197 return error;
198 }
199 ether_ifattach(ifp, enaddr);
200 if_register(ifp);
201
202 aprint_verbose("shmif%d: Ethernet address %s\n",
203 unit, ether_sprintf(enaddr));
204
205 if (scp)
206 *scp = sc;
207
208 error = 0;
209 if (rump_threads) {
210 error = kthread_create(PRI_NONE,
211 KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL,
212 shmif_rcv, ifp, &sc->sc_rcvl, "shmif");
213 } else {
214 printf("WARNING: threads not enabled, shmif NOT working\n");
215 }
216
217 if (error) {
218 shmif_unclone(ifp);
219 }
220
221 return error;
222 }
223
224 static int
225 initbackend(struct shmif_sc *sc, int memfd)
226 {
227 volatile uint8_t v;
228 volatile uint8_t *p;
229 void *mem;
230 int error;
231
232 error = rumpcomp_shmif_mmap(memfd, BUSMEM_SIZE, &mem);
233 if (error)
234 return error;
235 sc->sc_busmem = mem;
236
237 if (sc->sc_busmem->shm_magic
238 && sc->sc_busmem->shm_magic != SHMIF_MAGIC) {
239 printf("bus is not magical");
240 rumpuser_unmap(sc->sc_busmem, BUSMEM_SIZE);
241 return ENOEXEC;
242 }
243
244 /*
245 * Prefault in pages to minimize runtime penalty with buslock.
246 * Use 512 instead of PAGE_SIZE to make sure we catch cases where
247 * rump kernel PAGE_SIZE > host page size.
248 */
249 for (p = (uint8_t *)sc->sc_busmem;
250 p < (uint8_t *)sc->sc_busmem + BUSMEM_SIZE;
251 p += 512)
252 v = *p;
253
254 shmif_lockbus(sc->sc_busmem);
255 /* we're first? initialize bus */
256 if (sc->sc_busmem->shm_magic == 0) {
257 sc->sc_busmem->shm_magic = SHMIF_MAGIC;
258 sc->sc_busmem->shm_first = BUSMEM_DATASIZE;
259 }
260
261 sc->sc_nextpacket = sc->sc_busmem->shm_last;
262 sc->sc_devgen = sc->sc_busmem->shm_gen;
263
264 #ifdef PREFAULT_RW
265 for (p = (uint8_t *)sc->sc_busmem;
266 p < (uint8_t *)sc->sc_busmem + BUSMEM_SIZE;
267 p += PAGE_SIZE) {
268 v = *p;
269 *p = v;
270 }
271 #endif
272 shmif_unlockbus(sc->sc_busmem);
273
274 sc->sc_kq = -1;
275 error = rumpcomp_shmif_watchsetup(&sc->sc_kq, memfd);
276 if (error) {
277 rumpuser_unmap(sc->sc_busmem, BUSMEM_SIZE);
278 return error;
279 }
280
281 sc->sc_memfd = memfd;
282
283 return error;
284 }
285
286 static void
287 finibackend(struct shmif_sc *sc)
288 {
289
290 if (sc->sc_backfile == NULL)
291 return;
292
293 if (sc->sc_backfile) {
294 kmem_free(sc->sc_backfile, sc->sc_backfilelen);
295 sc->sc_backfile = NULL;
296 sc->sc_backfilelen = 0;
297 }
298
299 rumpuser_unmap(sc->sc_busmem, BUSMEM_SIZE);
300 rumpuser_close(sc->sc_memfd);
301 rumpuser_close(sc->sc_kq);
302
303 sc->sc_memfd = -1;
304 }
305
306 int
307 rump_shmif_create(const char *path, int *ifnum)
308 {
309 struct shmif_sc *sc;
310 vmem_addr_t t;
311 int unit, error;
312 int memfd = -1; /* XXXgcc */
313
314 if (path) {
315 error = rumpuser_open(path,
316 RUMPUSER_OPEN_RDWR | RUMPUSER_OPEN_CREATE, &memfd);
317 if (error)
318 return error;
319 }
320
321 error = vmem_xalloc(shmif_units, 1, 0, 0, 0,
322 VMEM_ADDR_MIN, VMEM_ADDR_MAX, VM_INSTANTFIT | VM_SLEEP, &t);
323
324 if (error != 0) {
325 if (path)
326 rumpuser_close(memfd);
327 return error;
328 }
329
330 unit = t - 1;
331
332 if ((error = allocif(unit, &sc)) != 0) {
333 if (path)
334 rumpuser_close(memfd);
335 return error;
336 }
337
338 if (!path)
339 goto out;
340
341 error = initbackend(sc, memfd);
342 if (error) {
343 shmif_unclone(&sc->sc_ec.ec_if);
344 return error;
345 }
346
347 sc->sc_backfilelen = strlen(path)+1;
348 sc->sc_backfile = kmem_alloc(sc->sc_backfilelen, KM_SLEEP);
349 strcpy(sc->sc_backfile, path);
350
351 out:
352 if (ifnum)
353 *ifnum = unit;
354
355 return 0;
356 }
357
358 static int
359 shmif_clone(struct if_clone *ifc, int unit)
360 {
361 int rc __diagused;
362 vmem_addr_t unit2;
363
364 /*
365 * Ok, we know the unit number, but we must still reserve it.
366 * Otherwise the wildcard-side of things might get the same one.
367 * This is slightly offset-happy due to vmem. First, we offset
368 * the range of unit numbers by +1 since vmem cannot deal with
369 * ranges starting from 0. Talk about uuuh.
370 */
371 rc = vmem_xalloc(shmif_units, 1, 0, 0, 0, unit+1, unit+1,
372 VM_SLEEP | VM_INSTANTFIT, &unit2);
373 KASSERT(rc == 0 && unit2-1 == unit);
374
375 return allocif(unit, NULL);
376 }
377
378 static int
379 shmif_unclone(struct ifnet *ifp)
380 {
381 struct shmif_sc *sc = ifp->if_softc;
382
383 shmif_stop(ifp, 1);
384 if_down(ifp);
385
386 mutex_enter(&sc->sc_mtx);
387 sc->sc_dying = true;
388 cv_broadcast(&sc->sc_cv);
389 mutex_exit(&sc->sc_mtx);
390
391 if (sc->sc_rcvl)
392 kthread_join(sc->sc_rcvl);
393 sc->sc_rcvl = NULL;
394
395 /*
396 * Need to be called after the kthread left, otherwise closing kqueue
397 * (sc_kq) hangs sometimes perhaps because of a race condition between
398 * close and kevent in the kthread on the kqueue.
399 */
400 finibackend(sc);
401
402 vmem_xfree(shmif_units, sc->sc_unit+1, 1);
403
404 ether_ifdetach(ifp);
405 if_detach(ifp);
406
407 cv_destroy(&sc->sc_cv);
408 mutex_destroy(&sc->sc_mtx);
409
410 kmem_free(sc, sizeof(*sc));
411
412 return 0;
413 }
414
415 static int
416 shmif_init(struct ifnet *ifp)
417 {
418 struct shmif_sc *sc = ifp->if_softc;
419 int error = 0;
420
421 if (sc->sc_memfd == -1)
422 return ENXIO;
423 KASSERT(sc->sc_busmem);
424
425 ifp->if_flags |= IFF_RUNNING;
426
427 mutex_enter(&sc->sc_mtx);
428 sc->sc_nextpacket = sc->sc_busmem->shm_last;
429 sc->sc_devgen = sc->sc_busmem->shm_gen;
430
431 cv_broadcast(&sc->sc_cv);
432 mutex_exit(&sc->sc_mtx);
433
434 return error;
435 }
436
437 static int
438 shmif_ioctl(struct ifnet *ifp, u_long cmd, void *data)
439 {
440 struct shmif_sc *sc = ifp->if_softc;
441 struct ifdrv *ifd;
442 char *path;
443 int s, rv, memfd;
444
445 s = splnet();
446 switch (cmd) {
447 case SIOCGLINKSTR:
448 ifd = data;
449
450 if (sc->sc_backfilelen == 0) {
451 rv = ENOENT;
452 break;
453 }
454
455 ifd->ifd_len = sc->sc_backfilelen;
456 if (ifd->ifd_cmd == IFLINKSTR_QUERYLEN) {
457 rv = 0;
458 break;
459 }
460
461 if (ifd->ifd_cmd != 0) {
462 rv = EINVAL;
463 break;
464 }
465
466 rv = copyoutstr(sc->sc_backfile, ifd->ifd_data,
467 MIN(sc->sc_backfilelen, ifd->ifd_len), NULL);
468 break;
469 case SIOCSLINKSTR:
470 if (ifp->if_flags & IFF_UP) {
471 rv = EBUSY;
472 break;
473 }
474
475 ifd = data;
476 if (ifd->ifd_cmd == IFLINKSTR_UNSET) {
477 finibackend(sc);
478 rv = 0;
479 break;
480 } else if (ifd->ifd_cmd != 0) {
481 rv = EINVAL;
482 break;
483 } else if (sc->sc_backfile) {
484 rv = EBUSY;
485 break;
486 }
487
488 if (ifd->ifd_len > MAXPATHLEN) {
489 rv = E2BIG;
490 break;
491 } else if (ifd->ifd_len < 1) {
492 rv = EINVAL;
493 break;
494 }
495
496 path = kmem_alloc(ifd->ifd_len, KM_SLEEP);
497 rv = copyinstr(ifd->ifd_data, path, ifd->ifd_len, NULL);
498 if (rv) {
499 kmem_free(path, ifd->ifd_len);
500 break;
501 }
502 rv = rumpuser_open(path,
503 RUMPUSER_OPEN_RDWR | RUMPUSER_OPEN_CREATE, &memfd);
504 if (rv) {
505 kmem_free(path, ifd->ifd_len);
506 break;
507 }
508 rv = initbackend(sc, memfd);
509 if (rv) {
510 kmem_free(path, ifd->ifd_len);
511 rumpuser_close(memfd);
512 break;
513 }
514 sc->sc_backfile = path;
515 sc->sc_backfilelen = ifd->ifd_len;
516
517 break;
518 default:
519 rv = ether_ioctl(ifp, cmd, data);
520 if (rv == ENETRESET)
521 rv = 0;
522 break;
523 }
524 splx(s);
525
526 return rv;
527 }
528
529 /* send everything in-context since it's just a matter of mem-to-mem copy */
530 static void
531 shmif_start(struct ifnet *ifp)
532 {
533 struct shmif_sc *sc = ifp->if_softc;
534 struct shmif_mem *busmem = sc->sc_busmem;
535 struct mbuf *m, *m0;
536 uint32_t dataoff;
537 uint32_t pktsize, pktwrote;
538 bool wrote = false;
539 bool wrap;
540
541 ifp->if_flags |= IFF_OACTIVE;
542
543 for (;;) {
544 struct shmif_pkthdr sp;
545 struct timeval tv;
546
547 IF_DEQUEUE(&ifp->if_snd, m0);
548 if (m0 == NULL) {
549 break;
550 }
551
552 pktsize = 0;
553 for (m = m0; m != NULL; m = m->m_next) {
554 pktsize += m->m_len;
555 }
556 KASSERT(pktsize <= ETHERMTU + ETHER_HDR_LEN);
557
558 getmicrouptime(&tv);
559 sp.sp_len = pktsize;
560 sp.sp_sec = tv.tv_sec;
561 sp.sp_usec = tv.tv_usec;
562 sp.sp_sender = sc->sc_uuid;
563
564 bpf_mtap(ifp, m0);
565
566 shmif_lockbus(busmem);
567 KASSERT(busmem->shm_magic == SHMIF_MAGIC);
568 busmem->shm_last = shmif_nextpktoff(busmem, busmem->shm_last);
569
570 wrap = false;
571 dataoff = shmif_buswrite(busmem,
572 busmem->shm_last, &sp, sizeof(sp), &wrap);
573 pktwrote = 0;
574 for (m = m0; m != NULL; m = m->m_next) {
575 pktwrote += m->m_len;
576 dataoff = shmif_buswrite(busmem, dataoff,
577 mtod(m, void *), m->m_len, &wrap);
578 }
579 KASSERT(pktwrote == pktsize);
580 if (wrap) {
581 busmem->shm_gen++;
582 DPRINTF(("bus generation now %" PRIu64 "\n",
583 busmem->shm_gen));
584 }
585 shmif_unlockbus(busmem);
586
587 m_freem(m0);
588 wrote = true;
589 ifp->if_opackets++;
590
591 DPRINTF(("shmif_start: send %d bytes at off %d\n",
592 pktsize, busmem->shm_last));
593 }
594
595 ifp->if_flags &= ~IFF_OACTIVE;
596
597 /* wakeup? */
598 if (wrote) {
599 dowakeup(sc);
600 }
601 }
602
603 static void
604 shmif_stop(struct ifnet *ifp, int disable)
605 {
606 struct shmif_sc *sc = ifp->if_softc;
607
608 ifp->if_flags &= ~IFF_RUNNING;
609 membar_producer();
610
611 /*
612 * wakeup thread. this will of course wake up all bus
613 * listeners, but that's life.
614 */
615 if (sc->sc_memfd != -1) {
616 dowakeup(sc);
617 }
618 }
619
620
621 /*
622 * Check if we have been sleeping too long. Basically,
623 * our in-sc nextpkt must by first <= nextpkt <= last"+1".
624 * We use the fact that first is guaranteed to never overlap
625 * with the last frame in the ring.
626 */
627 static __inline bool
628 stillvalid_p(struct shmif_sc *sc)
629 {
630 struct shmif_mem *busmem = sc->sc_busmem;
631 unsigned gendiff = busmem->shm_gen - sc->sc_devgen;
632 uint32_t lastoff, devoff;
633
634 KASSERT(busmem->shm_first != busmem->shm_last);
635
636 /* normalize onto a 2x busmem chunk */
637 devoff = sc->sc_nextpacket;
638 lastoff = shmif_nextpktoff(busmem, busmem->shm_last);
639
640 /* trivial case */
641 if (gendiff > 1)
642 return false;
643 KASSERT(gendiff <= 1);
644
645 /* Normalize onto 2x busmem chunk */
646 if (busmem->shm_first >= lastoff) {
647 lastoff += BUSMEM_DATASIZE;
648 if (gendiff == 0)
649 devoff += BUSMEM_DATASIZE;
650 } else {
651 if (gendiff)
652 return false;
653 }
654
655 return devoff >= busmem->shm_first && devoff <= lastoff;
656 }
657
658 static void
659 shmif_rcv(void *arg)
660 {
661 struct ifnet *ifp = arg;
662 struct shmif_sc *sc = ifp->if_softc;
663 struct shmif_mem *busmem;
664 struct mbuf *m = NULL;
665 struct ether_header *eth;
666 uint32_t nextpkt;
667 bool wrap, passup;
668 int error;
669 const int align
670 = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
671
672 reup:
673 mutex_enter(&sc->sc_mtx);
674 while ((ifp->if_flags & IFF_RUNNING) == 0 && !sc->sc_dying)
675 cv_wait(&sc->sc_cv, &sc->sc_mtx);
676 mutex_exit(&sc->sc_mtx);
677
678 busmem = sc->sc_busmem;
679
680 while (ifp->if_flags & IFF_RUNNING) {
681 struct shmif_pkthdr sp;
682
683 if (m == NULL) {
684 m = m_gethdr(M_WAIT, MT_DATA);
685 MCLGET(m, M_WAIT);
686 m->m_data += align;
687 }
688
689 DPRINTF(("waiting %d/%" PRIu64 "\n",
690 sc->sc_nextpacket, sc->sc_devgen));
691 KASSERT(m->m_flags & M_EXT);
692
693 shmif_lockbus(busmem);
694 KASSERT(busmem->shm_magic == SHMIF_MAGIC);
695 KASSERT(busmem->shm_gen >= sc->sc_devgen);
696
697 /* need more data? */
698 if (sc->sc_devgen == busmem->shm_gen &&
699 shmif_nextpktoff(busmem, busmem->shm_last)
700 == sc->sc_nextpacket) {
701 shmif_unlockbus(busmem);
702 error = rumpcomp_shmif_watchwait(sc->sc_kq);
703 if (__predict_false(error))
704 printf("shmif_rcv: wait failed %d\n", error);
705 membar_consumer();
706 continue;
707 }
708
709 if (stillvalid_p(sc)) {
710 nextpkt = sc->sc_nextpacket;
711 } else {
712 KASSERT(busmem->shm_gen > 0);
713 nextpkt = busmem->shm_first;
714 if (busmem->shm_first > busmem->shm_last)
715 sc->sc_devgen = busmem->shm_gen - 1;
716 else
717 sc->sc_devgen = busmem->shm_gen;
718 DPRINTF(("dev %p overrun, new data: %d/%" PRIu64 "\n",
719 sc, nextpkt, sc->sc_devgen));
720 }
721
722 /*
723 * If our read pointer is ahead the bus last write, our
724 * generation must be one behind.
725 */
726 KASSERT(!(nextpkt > busmem->shm_last
727 && sc->sc_devgen == busmem->shm_gen));
728
729 wrap = false;
730 nextpkt = shmif_busread(busmem, &sp,
731 nextpkt, sizeof(sp), &wrap);
732 KASSERT(sp.sp_len <= ETHERMTU + ETHER_HDR_LEN);
733 nextpkt = shmif_busread(busmem, mtod(m, void *),
734 nextpkt, sp.sp_len, &wrap);
735
736 DPRINTF(("shmif_rcv: read packet of length %d at %d\n",
737 sp.sp_len, nextpkt));
738
739 sc->sc_nextpacket = nextpkt;
740 shmif_unlockbus(sc->sc_busmem);
741
742 if (wrap) {
743 sc->sc_devgen++;
744 DPRINTF(("dev %p generation now %" PRIu64 "\n",
745 sc, sc->sc_devgen));
746 }
747
748 /*
749 * Ignore packets too short to possibly be valid.
750 * This is hit at least for the first frame on a new bus.
751 */
752 if (__predict_false(sp.sp_len < ETHER_HDR_LEN)) {
753 DPRINTF(("shmif read packet len %d < ETHER_HDR_LEN\n",
754 sp.sp_len));
755 continue;
756 }
757
758 m->m_len = m->m_pkthdr.len = sp.sp_len;
759 m_set_rcvif(m, ifp);
760
761 /*
762 * Test if we want to pass the packet upwards
763 */
764 eth = mtod(m, struct ether_header *);
765 if (sp.sp_sender == sc->sc_uuid) {
766 passup = false;
767 } else if (memcmp(eth->ether_dhost, CLLADDR(ifp->if_sadl),
768 ETHER_ADDR_LEN) == 0) {
769 passup = true;
770 } else if (ETHER_IS_MULTICAST(eth->ether_dhost)) {
771 passup = true;
772 } else if (ifp->if_flags & IFF_PROMISC) {
773 m->m_flags |= M_PROMISC;
774 passup = true;
775 } else {
776 passup = false;
777 }
778
779 if (passup) {
780 int bound;
781 KERNEL_LOCK(1, NULL);
782 /* Prevent LWP migrations between CPUs for psref(9) */
783 bound = curlwp_bind();
784 if_input(ifp, m);
785 curlwp_bindx(bound);
786 KERNEL_UNLOCK_ONE(NULL);
787 m = NULL;
788 }
789 /* else: reuse mbuf for a future packet */
790 }
791 m_freem(m);
792 m = NULL;
793
794 if (!sc->sc_dying)
795 goto reup;
796
797 kthread_exit(0);
798 }
799