Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/rump/net/lib/libshmif * make interface a cloner



details:   https://anonhg.NetBSD.org/src/rev/f462198b048b
branches:  trunk
changeset: 758802:f462198b048b
user:      pooka <pooka%NetBSD.org@localhost>
date:      Mon Nov 15 22:48:06 2010 +0000

description:
* make interface a cloner
* use SIOCSLINKSTR for supplying bus filename in case of cloned if

TODO: downing interface, unclone, and some tweaks for robustness

diffstat:

 sys/rump/net/lib/libshmif/Makefile   |    3 +-
 sys/rump/net/lib/libshmif/if_shmem.c |  254 ++++++++++++++++++++++++++++------
 2 files changed, 208 insertions(+), 49 deletions(-)

diffs (truncated from 351 to 300 lines):

diff -r d9654d424df6 -r f462198b048b sys/rump/net/lib/libshmif/Makefile
--- a/sys/rump/net/lib/libshmif/Makefile        Mon Nov 15 22:45:23 2010 +0000
+++ b/sys/rump/net/lib/libshmif/Makefile        Mon Nov 15 22:48:06 2010 +0000
@@ -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
 
diff -r d9654d424df6 -r f462198b048b sys/rump/net/lib/libshmif/if_shmem.c
--- a/sys/rump/net/lib/libshmif/if_shmem.c      Mon Nov 15 22:45:23 2010 +0000
+++ b/sys/rump/net/lib/libshmif/if_shmem.c      Mon Nov 15 22:48:06 2010 +0000
@@ -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;
+       unsigned mynum = unit;
+
+       randnum = arc4random();
+       memcpy(&enaddr[2], &randnum, sizeof(randnum));
+
+       sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
+       sc->sc_memfd = -1;
+
+       ifp = &sc->sc_ec.ec_if;
+       memcpy(sc->sc_myaddr, enaddr, sizeof(enaddr));
+
+       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;
 
-       randnum = arc4random();
-       memcpy(&enaddr[2], &randnum, sizeof(randnum));
-       mynum = atomic_inc_uint_nv(&numif)-1;
-
-       sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
-       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,
+       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;
+               return error;
 
-       if (sc->sc_busmem->shm_magic && sc->sc_busmem->shm_magic != SHMIF_MAGIC)
-               panic("bus is not magical");
-
+       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;
+
+       sc->sc_memfd = memfd;
+       return 0;
+}
+
+static void
+finibackend(struct shmif_sc *sc)
+{
+       int dummy;
+
+       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);
+}
 
-       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;
+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;
 
-       if_attach(ifp);
-       ether_ifattach(ifp, enaddr);
+       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;
+       }
 
-       aprint_verbose("shmif%d: bus %s\n", mynum, path);
-       aprint_verbose("shmif%d: Ethernet address %s\n",
-           mynum, ether_sprintf(enaddr));
+       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;
+}
+
+static int
+shmif_clone(struct if_clone *ifc, int unit)
+{
+       int mynum;
 
- fail:
-       panic("rump_shmemif_create: fixme");
+       /* 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;
+               }
+



Home | Main Index | Thread Index | Old Index