Module Name: src
Committed By: pooka
Date: Mon Nov 15 22:48:06 UTC 2010
Modified Files:
src/sys/rump/net/lib/libshmif: Makefile if_shmem.c
Log Message:
* make interface a cloner
* use SIOCSLINKSTR for supplying bus filename in case of cloned if
TODO: downing interface, unclone, and some tweaks for robustness
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/rump/net/lib/libshmif/Makefile
cvs rdiff -u -r1.28 -r1.29 src/sys/rump/net/lib/libshmif/if_shmem.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/rump/net/lib/libshmif/Makefile
diff -u src/sys/rump/net/lib/libshmif/Makefile:1.2 src/sys/rump/net/lib/libshmif/Makefile:1.3
--- src/sys/rump/net/lib/libshmif/Makefile:1.2 Thu Aug 12 21:41:47 2010
+++ src/sys/rump/net/lib/libshmif/Makefile Mon Nov 15 22:48:06 2010
@@ -1,9 +1,10 @@
-# $NetBSD: Makefile,v 1.2 2010/08/12 21:41:47 pooka Exp $
+# $NetBSD: Makefile,v 1.3 2010/11/15 22:48:06 pooka Exp $
#
LIB= rumpnet_shmif
SRCS= if_shmem.c shmif_busops.c
+SRCS+= component.c
CPPFLAGS+= -I${.CURDIR}/../../../librump/rumpkern
Index: src/sys/rump/net/lib/libshmif/if_shmem.c
diff -u src/sys/rump/net/lib/libshmif/if_shmem.c:1.28 src/sys/rump/net/lib/libshmif/if_shmem.c:1.29
--- src/sys/rump/net/lib/libshmif/if_shmem.c:1.28 Tue Aug 17 20:42:47 2010
+++ src/sys/rump/net/lib/libshmif/if_shmem.c Mon Nov 15 22:48:06 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: if_shmem.c,v 1.28 2010/08/17 20:42:47 pooka Exp $ */
+/* $NetBSD: if_shmem.c,v 1.29 2010/11/15 22:48:06 pooka Exp $ */
/*
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.28 2010/08/17 20:42:47 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.29 2010/11/15 22:48:06 pooka Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@@ -50,14 +50,17 @@
#include "rump_private.h"
#include "rump_net_private.h"
+static int shmif_clone(struct if_clone *, int);
+static int shmif_unclone(struct ifnet *);
+
+struct if_clone shmif_cloner =
+ IF_CLONE_INITIALIZER("shmif", shmif_clone, shmif_unclone);
+
/*
* Do r/w prefault for backend pages when attaching the interface.
- * This works aroud the most likely kernel/ffs/x86pmap bug described
- * in http://mail-index.netbsd.org/tech-kern/2010/08/17/msg008749.html
- *
- * NOTE: read prefaulting is not enough (that's done always)!
+ * At least logically thinking improves performance (although no
+ * mlocking is done, so they might go away).
*/
-
#define PREFAULT_RW
/*
@@ -79,6 +82,9 @@
int sc_memfd;
int sc_kq;
+ char *sc_backfile;
+ size_t sc_backfilelen;
+
uint64_t sc_devgen;
uint32_t sc_nextpacket;
};
@@ -129,38 +135,64 @@
KASSERT(old == LOCK_LOCKED);
}
-int
-rump_shmif_create(const char *path, int *ifnum)
+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;
- uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0xa0, 0x00, 0x00, 0x00, 0x00 };
uint32_t randnum;
- unsigned mynum;
- volatile uint8_t v;
- volatile uint8_t *p;
- int error;
+ unsigned mynum = unit;
randnum = arc4random();
memcpy(&enaddr[2], &randnum, sizeof(randnum));
- mynum = atomic_inc_uint_nv(&numif)-1;
sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
+ sc->sc_memfd = -1;
+
ifp = &sc->sc_ec.ec_if;
memcpy(sc->sc_myaddr, enaddr, sizeof(enaddr));
- sc->sc_memfd = rumpuser_open(path, O_RDWR | O_CREAT, &error);
- if (sc->sc_memfd == -1)
- goto fail;
- sc->sc_busmem = rumpuser_filemmap(sc->sc_memfd, 0, BUSMEM_SIZE,
+ sprintf(ifp->if_xname, "shmif%d", mynum);
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | 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;
+
+ if_attach(ifp);
+ ether_ifattach(ifp, enaddr);
+
+ aprint_verbose("shmif%d: Ethernet address %s\n",
+ mynum, ether_sprintf(enaddr));
+
+ if (scp)
+ *scp = sc;
+
+ return 0;
+}
+
+static int
+initbackend(struct shmif_sc *sc, int memfd)
+{
+ volatile uint8_t v;
+ volatile uint8_t *p;
+ int error;
+
+ sc->sc_busmem = rumpuser_filemmap(memfd, 0, BUSMEM_SIZE,
RUMPUSER_FILEMMAP_TRUNCATE | RUMPUSER_FILEMMAP_SHARED
| RUMPUSER_FILEMMAP_READ | RUMPUSER_FILEMMAP_WRITE, &error);
if (error)
- goto fail;
-
- if (sc->sc_busmem->shm_magic && sc->sc_busmem->shm_magic != SHMIF_MAGIC)
- panic("bus is not magical");
+ return error;
+ if (sc->sc_busmem->shm_magic
+ && sc->sc_busmem->shm_magic != SHMIF_MAGIC) {
+ printf("bus is not magical");
+ rumpuser_unmap(sc->sc_busmem, BUSMEM_SIZE);
+ return ENOEXEC;
+ }
/* Prefault in pages to minimize runtime penalty with buslock */
for (p = (uint8_t *)sc->sc_busmem;
@@ -188,39 +220,88 @@
#endif
shmif_unlockbus(sc->sc_busmem);
- sc->sc_kq = rumpuser_writewatchfile_setup(-1, sc->sc_memfd, 0, &error);
+ sc->sc_kq = rumpuser_writewatchfile_setup(-1, memfd, 0, &error);
if (sc->sc_kq == -1)
- goto fail;
+ return error;
- sprintf(ifp->if_xname, "shmif%d", mynum);
- ifp->if_softc = sc;
- ifp->if_flags = IFF_BROADCAST | 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;
+ sc->sc_memfd = memfd;
+ return 0;
+}
- if_attach(ifp);
- ether_ifattach(ifp, enaddr);
+static void
+finibackend(struct shmif_sc *sc)
+{
+ int dummy;
- aprint_verbose("shmif%d: bus %s\n", mynum, path);
- aprint_verbose("shmif%d: Ethernet address %s\n",
- mynum, ether_sprintf(enaddr));
+ kmem_free(sc->sc_backfile, sc->sc_backfilelen);
+ sc->sc_backfile = NULL;
+ sc->sc_backfilelen = 0;
+
+ rumpuser_unmap(sc->sc_busmem, BUSMEM_SIZE);
+ rumpuser_close(sc->sc_memfd, &dummy);
+ rumpuser_close(sc->sc_kq, &dummy);
+}
+
+int
+rump_shmif_create(const char *path, int *ifnum)
+{
+ struct shmif_sc *sc;
+ int mynum, error, memfd, dummy;
+
+ memfd = rumpuser_open(path, O_RDWR | O_CREAT, &error);
+ if (memfd == -1)
+ return error;
+
+ mynum = atomic_inc_uint_nv(&numif)-1;
+ if ((error = allocif(mynum, &sc)) != 0) {
+ rumpuser_close(memfd, &dummy);
+ return error;
+ }
+ error = initbackend(sc, memfd);
+ if (error) {
+ rumpuser_close(memfd, &dummy);
+ /* XXX: free sc */
+ return error;
+ }
+
+ sc->sc_backfilelen = strlen(path)+1;
+ sc->sc_backfile = kmem_alloc(sc->sc_backfilelen, KM_SLEEP);
+ strcpy(sc->sc_backfile, path);
if (ifnum)
*ifnum = mynum;
+
return 0;
+}
- fail:
- panic("rump_shmemif_create: fixme");
+static int
+shmif_clone(struct if_clone *ifc, int unit)
+{
+ int mynum;
+
+ /* not atomic against rump_shmif_create(). so "don't do it". */
+ if (unit >= mynum)
+ mynum = unit+1;
+
+ return allocif(unit, NULL);
+}
+
+static int
+shmif_unclone(struct ifnet *ifp)
+{
+
+ return EOPNOTSUPP;
}
static int
shmif_init(struct ifnet *ifp)
{
+ struct shmif_sc *sc = ifp->if_softc;
int error = 0;
+ if (sc->sc_memfd == -1)
+ return ENXIO;
+
if (rump_threads) {
error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
shmif_rcv, ifp, NULL, "shmif");
@@ -235,12 +316,89 @@
static int
shmif_ioctl(struct ifnet *ifp, u_long cmd, void *data)
{
- int s, rv;
+ struct shmif_sc *sc = ifp->if_softc;
+ struct ifdrv *ifd;
+ char *path;
+ int s, rv, memfd, dummy;
s = splnet();
- rv = ether_ioctl(ifp, cmd, data);
- if (rv == ENETRESET)
- rv = 0;
+ switch (cmd) {
+ case SIOCGLINKSTR:
+ ifd = data;
+
+ if (sc->sc_backfilelen == 0) {
+ rv = ENOENT;
+ break;
+ }
+
+ ifd->ifd_len = sc->sc_backfilelen;
+ if (ifd->ifd_cmd == IFLINKSTR_QUERYLEN) {
+ rv = 0;
+ break;
+ }
+
+ if (ifd->ifd_cmd != 0) {
+ rv = EINVAL;
+ break;
+ }
+
+ rv = copyoutstr(sc->sc_backfile, ifd->ifd_data,
+ MIN(sc->sc_backfilelen, ifd->ifd_len), NULL);
+ break;
+ case SIOCSLINKSTR:
+ if (ifp->if_flags & IFF_UP) {
+ rv = EBUSY;
+ break;
+ }
+
+ ifd = data;
+ if (ifd->ifd_cmd == IFLINKSTR_UNSET) {
+ finibackend(sc);
+ rv = 0;
+ break;
+ } else if (ifd->ifd_cmd != 0) {
+ rv = EINVAL;
+ break;
+ } else if (sc->sc_backfile) {
+ rv = EBUSY;
+ break;
+ }
+
+ if (ifd->ifd_len > MAXPATHLEN) {
+ rv = E2BIG;
+ break;
+ } else if (ifd->ifd_len < 1) {
+ rv = EINVAL;
+ break;
+ }
+
+ path = kmem_alloc(ifd->ifd_len, KM_SLEEP);
+ rv = copyinstr(ifd->ifd_data, path, ifd->ifd_len, NULL);
+ if (rv) {
+ kmem_free(path, ifd->ifd_len);
+ break;
+ }
+ memfd = rumpuser_open(path, O_RDWR | O_CREAT, &rv);
+ if (memfd == -1) {
+ kmem_free(path, ifd->ifd_len);
+ break;
+ }
+ rv = initbackend(sc, memfd);
+ if (rv) {
+ kmem_free(path, ifd->ifd_len);
+ rumpuser_close(memfd, &dummy);
+ break;
+ }
+ sc->sc_backfile = path;
+ sc->sc_backfilelen = ifd->ifd_len;
+
+ break;
+ default:
+ rv = ether_ioctl(ifp, cmd, data);
+ if (rv == ENETRESET)
+ rv = 0;
+ break;
+ }
splx(s);
return rv;