static int allocif(int unit, struct shmif_sc **scp) { uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0xa0, 0x00, 0x00, 0x00, 0x00 }; struct shmif_sc *sc; struct ifnet *ifp; uint32_t randnum; int error; randnum = cprng_fast32(); memcpy(&enaddr[2], &randnum, sizeof(randnum)); sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); sc->sc_memfd = -1; sc->sc_unit = unit; sc->sc_uuid = cprng_fast64(); ifp = &sc->sc_ec.ec_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "shmif%d", unit); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = shmif_init; ifp->if_ioctl = shmif_ioctl; ifp->if_start = shmif_start; ifp->if_stop = shmif_stop; ifp->if_mtu = ETHERMTU; ifp->if_dlt = DLT_EN10MB; mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE); cv_init(&sc->sc_cv, "shmifcv"); if_initialize(ifp); ether_ifattach(ifp, enaddr); if_register(ifp); aprint_verbose("shmif%d: Ethernet address %s\n", unit, ether_sprintf(enaddr)); if (scp) *scp = sc; error = 0; if (rump_threads) { error = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL, shmif_rcv, ifp, &sc->sc_rcvl, "shmif"); } else { printf("WARNING: threads not enabled, shmif NOT working\n"); } if (error) { shmif_unclone(ifp); } return error; }
int rump_shmif_create(const char *path, int *ifnum) { struct shmif_sc *sc; vmem_addr_t t; int unit, error; int memfd = -1; /* XXXgcc */ if (path) { error = rumpuser_open(path, RUMPUSER_OPEN_RDWR | RUMPUSER_OPEN_CREATE, &memfd); if (error) return error; } error = vmem_xalloc(shmif_units, 1, 0, 0, 0, VMEM_ADDR_MIN, VMEM_ADDR_MAX, VM_INSTANTFIT | VM_SLEEP, &t); if (error != 0) { if (path) rumpuser_close(memfd); return error; } unit = t - 1; if ((error = allocif(unit, &sc)) != 0) { if (path) rumpuser_close(memfd); return error; } if (!path) goto out; error = initbackend(sc, memfd); if (error) { shmif_unclone(&sc->sc_ec.ec_if); return error; } sc->sc_backfilelen = strlen(path)+1; sc->sc_backfile = kmem_alloc(sc->sc_backfilelen, KM_SLEEP); strcpy(sc->sc_backfile, path); out: if (ifnum) *ifnum = unit; return 0; }