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;

Reply via email to