Author: luigi
Date: Thu Jan 16 00:20:42 2014
New Revision: 260700
URL: http://svnweb.freebsd.org/changeset/base/260700

Log:
  netmap_user.h:
     add separate rx/tx ring indexes
     add ring specifier in nm_open device name
  
  netmap.c, netmap_vale.c
     more consistent errno numbers
  
  netmap_generic.c
     correctly handle failure in registering interfaces.
  
  tools/tools/netmap/
     massive cleanup of the example programs
     (a lot of common code is now in netmap_user.h.)
  
  nm_util.[ch] are going away soon.
  pcap.c will also go when i commit the native netmap support for libpcap.

Modified:
  head/sys/dev/netmap/netmap.c
  head/sys/dev/netmap/netmap_generic.c
  head/sys/dev/netmap/netmap_vale.c
  head/tools/tools/netmap/Makefile
  head/tools/tools/netmap/bridge.c
  head/tools/tools/netmap/nm_util.c
  head/tools/tools/netmap/nm_util.h
  head/tools/tools/netmap/pcap.c
  head/tools/tools/netmap/pkt-gen.c
  head/tools/tools/netmap/vale-ctl.c

Modified: head/sys/dev/netmap/netmap.c
==============================================================================
--- head/sys/dev/netmap/netmap.c        Wed Jan 15 22:47:53 2014        
(r260699)
+++ head/sys/dev/netmap/netmap.c        Thu Jan 16 00:20:42 2014        
(r260700)
@@ -1052,7 +1052,7 @@ netmap_get_hw_na(struct ifnet *ifp, stru
         * to use generic adapters, we cannot satisfy the request.
         */
        if (!NETMAP_CAPABLE(ifp) && i == NETMAP_ADMODE_NATIVE)
-               return EINVAL;
+               return EOPNOTSUPP;
 
        /* Otherwise, create a generic adapter and return it,
         * saving the previously used netmap adapter, if any.
@@ -1090,22 +1090,19 @@ netmap_get_hw_na(struct ifnet *ifp, stru
 /*
  * MUST BE CALLED UNDER NMG_LOCK()
  *
- * get a refcounted reference to an interface.
+ * Get a refcounted reference to a netmap adapter attached
+ * to the interface specified by nmr.
  * This is always called in the execution of an ioctl().
  *
- * Return ENXIO if the interface does not exist, EINVAL if netmap
- * is not supported by the interface.
- * If successful, hold a reference.
- *
- * When the NIC is attached to a bridge, reference is managed
- * at na->na_bdg_refcount using ADD/DROP_BDG_REF() as well as
- * virtual ports.  Hence, on the final DROP_BDG_REF(), the NIC
- * is detached from the bridge, then ifp's refcount is dropped (this
- * is equivalent to that ifp is destroyed in case of virtual ports.
- *
- * This function uses if_rele() when we want to prevent the NIC from
- * being detached from the bridge in error handling.  But once refcount
- * is acquired by this function, it must be released using nm_if_rele().
+ * Return ENXIO if the interface specified by the request does
+ * not exist, ENOTSUP if netmap is not supported by the interface,
+ * EBUSY if the interface is already attached to a bridge,
+ * EINVAL if parameters are invalid, ENOMEM if needed resources
+ * could not be allocated.
+ * If successful, hold a reference to the netmap adapter.
+ *
+ * No reference is kept on the real interface, which may then
+ * disappear at any time.
  */
 int
 netmap_get_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
@@ -1135,7 +1132,7 @@ netmap_get_na(struct nmreq *nmr, struct 
        if (ret != NULL) {
                /* Users cannot use the NIC attached to a bridge directly */
                if (NETMAP_OWNED_BY_KERN(ret)) {
-                       error = EINVAL;
+                       error = EBUSY;
                        goto out;
                }
                error = 0;

Modified: head/sys/dev/netmap/netmap_generic.c
==============================================================================
--- head/sys/dev/netmap/netmap_generic.c        Wed Jan 15 22:47:53 2014        
(r260699)
+++ head/sys/dev/netmap/netmap_generic.c        Thu Jan 16 00:20:42 2014        
(r260700)
@@ -261,7 +261,7 @@ generic_netmap_register(struct netmap_ad
                /* Prepare to intercept incoming traffic. */
                error = netmap_catch_rx(na, 1);
                if (error) {
-                       D("netdev_rx_handler_register() failed");
+                       D("netdev_rx_handler_register() failed (%d)", error);
                        goto register_handler;
                }
                ifp->if_capenable |= IFCAP_NETMAP;
@@ -283,7 +283,11 @@ generic_netmap_register(struct netmap_ad
                rate_ctx.refcount++;
 #endif /* RATE */
 
-       } else { /* Disable netmap mode. */
+       } else if (na->tx_rings[0].tx_pool) {
+               /* Disable netmap mode. We enter here only if the previous
+                  generic_netmap_register(na, 1) was successfull.
+                  If it was not, na->tx_rings[0].tx_pool was set to NULL by the
+                  error handling code below. */
                rtnl_lock();
 
                ifp->if_capenable &= ~IFCAP_NETMAP;
@@ -322,7 +326,7 @@ generic_netmap_register(struct netmap_ad
 #ifdef REG_RESET
        error = ifp->netdev_ops->ndo_open(ifp);
        if (error) {
-               goto alloc_tx_pool;
+               goto free_tx_pools;
        }
 #endif
 
@@ -338,6 +342,11 @@ free_tx_pools:
                        if (na->tx_rings[r].tx_pool[i])
                                m_freem(na->tx_rings[r].tx_pool[i]);
                free(na->tx_rings[r].tx_pool, M_DEVBUF);
+               na->tx_rings[r].tx_pool = NULL;
+       }
+       netmap_mitigation_cleanup(gna);
+       for (r=0; r<na->num_rx_rings; r++) {
+               mbq_safe_destroy(&na->rx_rings[r].rx_queue);
        }
 
        return error;

Modified: head/sys/dev/netmap/netmap_vale.c
==============================================================================
--- head/sys/dev/netmap/netmap_vale.c   Wed Jan 15 22:47:53 2014        
(r260699)
+++ head/sys/dev/netmap/netmap_vale.c   Thu Jan 16 00:20:42 2014        
(r260700)
@@ -515,7 +515,7 @@ netmap_get_bdg_na(struct nmreq *nmr, str
        b = nm_find_bridge(name, create);
        if (b == NULL) {
                D("no bridges available for '%s'", name);
-               return (ENXIO);
+               return (create ? ENOMEM : ENXIO);
        }
 
        /* Now we are sure that name starts with the bridge's name,
@@ -547,7 +547,7 @@ netmap_get_bdg_na(struct nmreq *nmr, str
        needed = 2; /* in some cases we only need 1 */
        if (b->bdg_active_ports + needed >= NM_BDG_MAXPORTS) {
                D("bridge full %d, cannot create new port", 
b->bdg_active_ports);
-               return EINVAL;
+               return ENOMEM;
        }
        /* record the next two ports available, but do not allocate yet */
        cand = b->bdg_port_index[b->bdg_active_ports];
@@ -594,7 +594,7 @@ netmap_get_bdg_na(struct nmreq *nmr, str
                if (NETMAP_OWNED_BY_ANY(ret)) {
                        D("NIC %s busy, cannot attach to bridge",
                                NM_IFPNAME(ifp));
-                       error = EINVAL;
+                       error = EBUSY;
                        goto out;
                }
                /* create a fake interface */
@@ -658,11 +658,13 @@ nm_bdg_attach(struct nmreq *nmr)
        npriv = malloc(sizeof(*npriv), M_DEVBUF, M_NOWAIT|M_ZERO);
        if (npriv == NULL)
                return ENOMEM;
+
        NMG_LOCK();
-       /* XXX probably netmap_get_bdg_na() */
+
        error = netmap_get_bdg_na(nmr, &na, 1 /* create if not exists */);
        if (error) /* no device, or another bridge or user owns the device */
                goto unlock_exit;
+
        if (na == NULL) { /* VALE prefix missing */
                error = EINVAL;
                goto unlock_exit;
@@ -707,6 +709,7 @@ nm_bdg_detach(struct nmreq *nmr)
        if (error) { /* no device, or another bridge or user owns the device */
                goto unlock_exit;
        }
+
        if (na == NULL) { /* VALE prefix missing */
                error = EINVAL;
                goto unlock_exit;
@@ -1945,7 +1948,7 @@ netmap_bwrap_notify(struct netmap_adapte
        int error = 0;
 
        if (tx == NR_TX)
-               return ENXIO;
+               return EINVAL;
 
        kring = &na->rx_rings[ring_n];
        hw_kring = &hwna->tx_rings[ring_n];
@@ -1999,7 +2002,7 @@ netmap_bwrap_host_notify(struct netmap_a
        struct netmap_bwrap_adapter *bna = na->na_private;
        struct netmap_adapter *port_na = &bna->up.up;
        if (tx == NR_TX || ring_n != 0)
-               return ENXIO;
+               return EINVAL;
        return netmap_bwrap_notify(port_na, port_na->num_rx_rings, NR_RX, 
flags);
 }
 

Modified: head/tools/tools/netmap/Makefile
==============================================================================
--- head/tools/tools/netmap/Makefile    Wed Jan 15 22:47:53 2014        
(r260699)
+++ head/tools/tools/netmap/Makefile    Thu Jan 16 00:20:42 2014        
(r260700)
@@ -10,7 +10,12 @@ NO_MAN=
 CFLAGS += -Werror -Wall -nostdinc -I/usr/include -I../../../sys
 CFLAGS += -Wextra
 
-LDFLAGS += -lpthread -lpcap
+LDFLAGS += -lpthread
+.ifdef WITHOUT_PCAP
+CFLAGS += -DNO_PCAP
+.else
+LDFLAGS += -lpcap
+.endif
 
 .include <bsd.prog.mk>
 .include <bsd.lib.mk>

Modified: head/tools/tools/netmap/bridge.c
==============================================================================
--- head/tools/tools/netmap/bridge.c    Wed Jan 15 22:47:53 2014        
(r260699)
+++ head/tools/tools/netmap/bridge.c    Thu Jan 16 00:20:42 2014        
(r260700)
@@ -96,16 +96,16 @@ process_rings(struct netmap_ring *rxring
 
 /* move packts from src to destination */
 static int
-move(struct my_ring *src, struct my_ring *dst, u_int limit)
+move(struct nm_desc_t *src, struct nm_desc_t *dst, u_int limit)
 {
        struct netmap_ring *txring, *rxring;
-       u_int m = 0, si = src->begin, di = dst->begin;
-       const char *msg = (src->queueid & NETMAP_SW_RING) ?
+       u_int m = 0, si = src->first_rx_ring, di = dst->first_tx_ring;
+       const char *msg = (src->req.nr_ringid & NETMAP_SW_RING) ?
                "host->net" : "net->host";
 
-       while (si < src->end && di < dst->end) {
-               rxring = NETMAP_RXRING(src->nifp, si);
-               txring = NETMAP_TXRING(dst->nifp, di);
+       while (si <= src->last_rx_ring && di <= dst->last_tx_ring) {
+               rxring = src->tx + si;
+               txring = dst->tx + di;
                ND("txring %p rxring %p", txring, rxring);
                if (nm_ring_empty(rxring)) {
                        si++;
@@ -121,28 +121,6 @@ move(struct my_ring *src, struct my_ring
        return (m);
 }
 
-/*
- * how many packets on this set of queues ?
- */
-static int
-pkt_queued(struct my_ring *me, int tx)
-{
-       u_int i, tot = 0;
-
-       ND("me %p begin %d end %d", me, me->begin, me->end);
-       for (i = me->begin; i < me->end; i++) {
-               struct netmap_ring *ring = tx ?
-                       NETMAP_TXRING(me->nifp, i) : NETMAP_RXRING(me->nifp, i);
-               tot += nm_ring_space(ring);
-       }
-       if (0 && verbose && tot && !tx)
-               D("ring %s %s %s has %d avail at %d",
-                       me->ifname, tx ? "tx": "rx",
-                       me->end >= me->nifp->ni_tx_rings ? // XXX who comes 
first ?
-                               "host":"net",
-                       tot, NETMAP_TXRING(me->nifp, me->begin)->cur);
-       return tot;
-}
 
 static void
 usage(void)
@@ -165,14 +143,12 @@ main(int argc, char **argv)
        struct pollfd pollfd[2];
        int i, ch;
        u_int burst = 1024, wait_link = 4;
-       struct my_ring me[2];
+       struct nm_desc_t *pa = NULL, *pb = NULL;
        char *ifa = NULL, *ifb = NULL;
 
        fprintf(stderr, "%s %s built %s %s\n",
                argv[0], version, __DATE__, __TIME__);
 
-       bzero(me, sizeof(me));
-
        while ( (ch = getopt(argc, argv, "b:i:vw:")) != -1) {
                switch (ch) {
                default:
@@ -224,9 +200,6 @@ main(int argc, char **argv)
                D("invalid wait_link %d, set to 4", wait_link);
                wait_link = 4;
        }
-       /* setup netmap interface #1. */
-       me[0].ifname = ifa;
-       me[1].ifname = ifb;
        if (!strcmp(ifa, ifb)) {
                D("same interface, endpoint 0 goes to host");
                i = NETMAP_SW_RING;
@@ -234,24 +207,26 @@ main(int argc, char **argv)
                /* two different interfaces. Take all rings on if1 */
                i = 0;  // all hw rings
        }
-       if (netmap_open(me, i, 1))
+       pa = netmap_open(ifa, i, 1);
+       if (pa == NULL)
                return (1);
-       me[1].mem = me[0].mem; /* copy the pointer, so only one mmap */
-       if (netmap_open(me+1, 0, 1))
+       // XXX use a single mmap ?
+       pb = netmap_open(ifb, 0, 1);
+       if (pb == NULL) {
+               nm_close(pa);
                return (1);
+       }
 
        /* setup poll(2) variables. */
        memset(pollfd, 0, sizeof(pollfd));
-       for (i = 0; i < 2; i++) {
-               pollfd[i].fd = me[i].fd;
-               pollfd[i].events = (POLLIN);
-       }
+       pollfd[0].fd = pa->fd;
+       pollfd[1].fd = pb->fd;
 
        D("Wait %d secs for link to come up...", wait_link);
        sleep(wait_link);
        D("Ready to go, %s 0x%x/%d <-> %s 0x%x/%d.",
-               me[0].ifname, me[0].queueid, me[0].nifp->ni_rx_rings,
-               me[1].ifname, me[1].queueid, me[1].nifp->ni_rx_rings);
+               pa->req.nr_name, pa->first_rx_ring, pa->req.nr_rx_rings,
+               pb->req.nr_name, pb->first_rx_ring, pb->req.nr_rx_rings);
 
        /* main loop */
        signal(SIGINT, sigint_h);
@@ -259,8 +234,8 @@ main(int argc, char **argv)
                int n0, n1, ret;
                pollfd[0].events = pollfd[1].events = 0;
                pollfd[0].revents = pollfd[1].revents = 0;
-               n0 = pkt_queued(me, 0);
-               n1 = pkt_queued(me + 1, 0);
+               n0 = pkt_queued(pa, 0);
+               n1 = pkt_queued(pb, 0);
                if (n0)
                        pollfd[1].events |= POLLOUT;
                else
@@ -276,39 +251,39 @@ main(int argc, char **argv)
                                ret <= 0 ? "timeout" : "ok",
                                pollfd[0].events,
                                pollfd[0].revents,
-                               pkt_queued(me, 0),
-                               me[0].rx->cur,
-                               pkt_queued(me, 1),
+                               pkt_queued(pa, 0),
+                               pa->rx->cur,
+                               pkt_queued(pa, 1),
                                pollfd[1].events,
                                pollfd[1].revents,
-                               pkt_queued(me+1, 0),
-                               me[1].rx->cur,
-                               pkt_queued(me+1, 1)
+                               pkt_queued(pb, 0),
+                               pb->rx->cur,
+                               pkt_queued(pb, 1)
                        );
                if (ret < 0)
                        continue;
                if (pollfd[0].revents & POLLERR) {
                        D("error on fd0, rx [%d,%d)",
-                               me[0].rx->cur, me[0].rx->tail);
+                               pa->rx->cur, pa->rx->tail);
                }
                if (pollfd[1].revents & POLLERR) {
                        D("error on fd1, rx [%d,%d)",
-                               me[1].rx->cur, me[1].rx->tail);
+                               pb->rx->cur, pb->rx->tail);
                }
                if (pollfd[0].revents & POLLOUT) {
-                       move(me + 1, me, burst);
+                       move(pb, pa, burst);
                        // XXX we don't need the ioctl */
                        // ioctl(me[0].fd, NIOCTXSYNC, NULL);
                }
                if (pollfd[1].revents & POLLOUT) {
-                       move(me, me + 1, burst);
+                       move(pa, pb, burst);
                        // XXX we don't need the ioctl */
                        // ioctl(me[1].fd, NIOCTXSYNC, NULL);
                }
        }
        D("exiting");
-       netmap_close(me + 1);
-       netmap_close(me + 0);
+       nm_close(pb);
+       nm_close(pa);
 
        return (0);
 }

Modified: head/tools/tools/netmap/nm_util.c
==============================================================================
--- head/tools/tools/netmap/nm_util.c   Wed Jan 15 22:47:53 2014        
(r260699)
+++ head/tools/tools/netmap/nm_util.c   Thu Jan 16 00:20:42 2014        
(r260700)
@@ -37,16 +37,21 @@
 extern int verbose;
 
 int
-nm_do_ioctl(struct my_ring *me, u_long what, int subcmd)
+nm_do_ioctl(struct nm_desc_t *me, u_long what, int subcmd)
 {
        struct ifreq ifr;
        int error;
+       int fd;
+
 #if defined( __FreeBSD__ ) || defined (__APPLE__)
-       int fd = me->fd;
+       (void)subcmd;   // only used on Linux
+       fd = me->fd;
 #endif
+
 #ifdef linux 
        struct ethtool_value eval;
-       int fd;
+
+       bzero(&eval, sizeof(eval));
        fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (fd < 0) {
                printf("Error: cannot get device control socket.\n");
@@ -54,9 +59,8 @@ nm_do_ioctl(struct my_ring *me, u_long w
        }
 #endif /* linux */
 
-       (void)subcmd;   // unused
        bzero(&ifr, sizeof(ifr));
-       strncpy(ifr.ifr_name, me->ifname, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, me->req.nr_name, sizeof(ifr.ifr_name));
        switch (what) {
        case SIOCSIFFLAGS:
 #ifndef __APPLE__
@@ -71,6 +75,7 @@ nm_do_ioctl(struct my_ring *me, u_long w
                ifr.ifr_curcap = me->if_curcap;
                break;
 #endif
+
 #ifdef linux
        case SIOCETHTOOL:
                eval.cmd = subcmd;
@@ -115,108 +120,47 @@ done:
  * Returns the file descriptor.
  * The extra flag checks configures promisc mode.
  */
-int
-netmap_open(struct my_ring *me, int ringid, int promisc)
+struct nm_desc_t *
+netmap_open(const char *name, int ringid, int promisc)
 {
-       int fd, err, l;
-       struct nmreq req;
+       struct nm_desc_t *d = nm_open(name, NULL, ringid, 0);
 
-       me->fd = fd = open("/dev/netmap", O_RDWR);
-       if (fd < 0) {
-               D("Unable to open /dev/netmap");
-               return (-1);
-       }
-       bzero(&req, sizeof(req));
-       req.nr_version = NETMAP_API;
-       strncpy(req.nr_name, me->ifname, sizeof(req.nr_name));
-       req.nr_ringid = ringid;
-       err = ioctl(fd, NIOCREGIF, &req);
-       if (err) {
-               D("Unable to register %s", me->ifname);
-               goto error;
-       }
-       me->memsize = l = req.nr_memsize;
-       if (verbose)
-               D("memsize is %d MB", l>>20);
-
-       if (me->mem == NULL) {
-               me->mem = mmap(0, l, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
-               if (me->mem == MAP_FAILED) {
-                       D("Unable to mmap");
-                       me->mem = NULL;
-                       goto error;
-               }
-       }
+       if (d == NULL)
+               return d;
 
+       if (verbose)
+               D("memsize is %d MB", d->req.nr_memsize>>20);
 
        /* Set the operating mode. */
        if (ringid != NETMAP_SW_RING) {
-               nm_do_ioctl(me, SIOCGIFFLAGS, 0);
-               if ((me[0].if_flags & IFF_UP) == 0) {
-                       D("%s is down, bringing up...", me[0].ifname);
-                       me[0].if_flags |= IFF_UP;
+               nm_do_ioctl(d, SIOCGIFFLAGS, 0);
+               if ((d->if_flags & IFF_UP) == 0) {
+                       D("%s is down, bringing up...", name);
+                       d->if_flags |= IFF_UP;
                }
                if (promisc) {
-                       me[0].if_flags |= IFF_PPROMISC;
-                       nm_do_ioctl(me, SIOCSIFFLAGS, 0);
+                       d->if_flags |= IFF_PPROMISC;
+                       nm_do_ioctl(d, SIOCSIFFLAGS, 0);
                }
 
+               /* disable GSO, TSO, RXCSUM, TXCSUM...
+                * TODO: set them back when done.
+                */
 #ifdef __FreeBSD__
-               /* also disable checksums etc. */
-               nm_do_ioctl(me, SIOCGIFCAP, 0);
-               me[0].if_reqcap = me[0].if_curcap;
-               me[0].if_reqcap &= ~(IFCAP_HWCSUM | IFCAP_TSO | IFCAP_TOE);
-               nm_do_ioctl(me+0, SIOCSIFCAP, 0);
+               nm_do_ioctl(d, SIOCGIFCAP, 0);
+               d->if_reqcap = d->if_curcap;
+               d->if_reqcap &= ~(IFCAP_HWCSUM | IFCAP_TSO | IFCAP_TOE);
+               nm_do_ioctl(d, SIOCSIFCAP, 0);
 #endif
 #ifdef linux
-               /* disable:
-                * - generic-segmentation-offload
-                * - tcp-segmentation-offload
-                * - rx-checksumming
-                * - tx-checksumming
-                * XXX check how to set back the caps.
-                */
-               nm_do_ioctl(me, SIOCETHTOOL, ETHTOOL_SGSO);
-               nm_do_ioctl(me, SIOCETHTOOL, ETHTOOL_STSO);
-               nm_do_ioctl(me, SIOCETHTOOL, ETHTOOL_SRXCSUM);
-               nm_do_ioctl(me, SIOCETHTOOL, ETHTOOL_STXCSUM);
+               nm_do_ioctl(d, SIOCETHTOOL, ETHTOOL_SGSO);
+               nm_do_ioctl(d, SIOCETHTOOL, ETHTOOL_STSO);
+               nm_do_ioctl(d, SIOCETHTOOL, ETHTOOL_SRXCSUM);
+               nm_do_ioctl(d, SIOCETHTOOL, ETHTOOL_STXCSUM);
 #endif /* linux */
        }
 
-       me->nifp = NETMAP_IF(me->mem, req.nr_offset);
-       me->queueid = ringid;
-       if (ringid & NETMAP_SW_RING) {
-               me->begin = req.nr_rx_rings;
-               me->end = me->begin + 1;
-               me->tx = NETMAP_TXRING(me->nifp, req.nr_tx_rings);
-               me->rx = NETMAP_RXRING(me->nifp, req.nr_rx_rings);
-       } else if (ringid & NETMAP_HW_RING) {
-               D("XXX check multiple threads");
-               me->begin = ringid & NETMAP_RING_MASK;
-               me->end = me->begin + 1;
-               me->tx = NETMAP_TXRING(me->nifp, me->begin);
-               me->rx = NETMAP_RXRING(me->nifp, me->begin);
-       } else {
-               me->begin = 0;
-               me->end = req.nr_rx_rings; // XXX max of the two
-               me->tx = NETMAP_TXRING(me->nifp, 0);
-               me->rx = NETMAP_RXRING(me->nifp, 0);
-       }
-       return (0);
-error:
-       close(me->fd);
-       return -1;
-}
-
-
-int
-netmap_close(struct my_ring *me)
-{
-       D("");
-       if (me->mem)
-               munmap(me->mem, me->memsize);
-       close(me->fd);
-       return (0);
+       return d;
 }
 
 
@@ -224,22 +168,18 @@ netmap_close(struct my_ring *me)
  * how many packets on this set of queues ?
  */
 int
-pkt_queued(struct my_ring *me, int tx)
+pkt_queued(struct nm_desc_t *d, int tx)
 {
        u_int i, tot = 0;
 
        ND("me %p begin %d end %d", me, me->begin, me->end);
-       for (i = me->begin; i < me->end; i++) {
-               struct netmap_ring *ring = tx ?
-                       NETMAP_TXRING(me->nifp, i) : NETMAP_RXRING(me->nifp, i);
-               tot += nm_ring_space(ring);
+       if (tx) {
+               for (i = d->first_tx_ring; i <= d->last_tx_ring; i++)
+                       tot += nm_ring_space(d->tx + i);
+       } else {
+               for (i = d->first_rx_ring; i <= d->last_rx_ring; i++)
+                       tot += nm_ring_space(d->rx + i);
        }
-       if (0 && verbose && tot && !tx)
-               D("ring %s %s %s has %d avail at %d",
-                       me->ifname, tx ? "tx": "rx",
-                       me->end >= me->nifp->ni_tx_rings ? // XXX who comes 
first ?
-                               "host":"net",
-                       tot, NETMAP_TXRING(me->nifp, me->begin)->cur);
        return tot;
 }
 
@@ -258,7 +198,7 @@ Helper routines for multiple readers fro
   In particular we have a shared head+tail pointers that work
   together with cur and available
   ON RETURN FROM THE SYSCALL:
-  shadow->head = ring->cur
+  shadow->cur = ring->cur
   shadow->tail = ring->tail
   shadow->link[i] = i for all slots // mark invalid
  
@@ -267,7 +207,7 @@ Helper routines for multiple readers fro
 struct nm_q_arg {
        u_int want;     /* Input */
        u_int have;     /* Output, 0 on error */
-       u_int head;
+       u_int cur;
        u_int tail;
        struct netmap_ring *ring;
 };
@@ -280,24 +220,26 @@ my_grab(struct nm_q_arg q)
 {
        const u_int ns = q.ring->num_slots;
 
+       // lock(ring);
        for (;;) {
 
-               q.head = (volatile u_int)q.ring->head;
+               q.cur = (volatile u_int)q.ring->head;
                q.have = ns + q.head - (volatile u_int)q.ring->tail;
                if (q.have >= ns)
                        q.have -= ns;
-               if (q.have == 0) /* no space */
+               if (q.have == 0) /* no space; caller may ioctl/retry */
                        break;
                if (q.want < q.have)
                        q.have = q.want;
-               q.tail = q.head + q.have;
+               q.tail = q.cur + q.have;
                if (q.tail >= ns)
                        q.tail -= ns;
-               if (atomic_cmpset_int(&q.ring->head, q.head, q.tail)
+               if (atomic_cmpset_int(&q.ring->cur, q.cur, q.tail)
                        break; /* success */
        }
+       // unlock(ring);
        D("returns %d out of %d at %d,%d",
-               q.have, q.want, q.head, q.tail);
+               q.have, q.want, q.cur, q.tail);
        /* the last one can clear avail ? */
        return q;
 }
@@ -306,16 +248,18 @@ my_grab(struct nm_q_arg q)
 int
 my_release(struct nm_q_arg q)
 {
-       u_int head = q.head, tail = q.tail, i;
+       u_int cur = q.cur, tail = q.tail, i;
        struct netmap_ring *r = q.ring;
 
        /* link the block to the next one.
         * there is no race here because the location is mine.
         */
-       r->slot[head].ptr = tail; /* this is mine */
+       r->slot[cur].ptr = tail; /* this is mine */
+       r->slot[cur].flags |= NM_SLOT_PTR;      // points to next block
        // memory barrier
-       if (r->head != head)
-               return; /* not my turn to release */
+       // lock(ring);
+       if (r->head != cur)
+               goto done;
        for (;;) {
                // advance head
                r->head = head = r->slot[head].ptr;
@@ -327,5 +271,8 @@ my_release(struct nm_q_arg q)
         * further down.
         */
        // do an ioctl/poll to flush.
+done:
+       // unlock(ring);
+       return; /* not my turn to release */
 }
 #endif /* unused */

Modified: head/tools/tools/netmap/nm_util.h
==============================================================================
--- head/tools/tools/netmap/nm_util.h   Wed Jan 15 22:47:53 2014        
(r260699)
+++ head/tools/tools/netmap/nm_util.h   Thu Jan 16 00:20:42 2014        
(r260700)
@@ -35,60 +35,31 @@
 
 #define _GNU_SOURCE    /* for CPU_SET() */
 
-#include <errno.h>
-#include <signal.h>    /* signal */
-#include <stdlib.h>
-#include <stdio.h>
+#include <stdio.h>     /* fprintf */
+#include <sys/poll.h>  /* POLLIN */
 #include <inttypes.h>  /* PRI* macros */
-#include <string.h>    /* strcmp */
-#include <fcntl.h>     /* open */
-#include <unistd.h>    /* close */
-#include <ifaddrs.h>   /* getifaddrs */
+#include <sys/types.h> /* u_char */
 
-#include <sys/mman.h>  /* PROT_* */
-#include <sys/ioctl.h> /* ioctl */
-#include <sys/poll.h>
-#include <sys/socket.h>        /* sockaddr.. */
 #include <arpa/inet.h> /* ntohs */
-#include <sys/param.h>
 #include <sys/sysctl.h>        /* sysctl */
-#include <sys/time.h>  /* timersub */
-
-#include <net/ethernet.h>
-#include <net/if.h>    /* ifreq */
+#include <ifaddrs.h>   /* getifaddrs */
+#include <net/ethernet.h>      /* ETHERTYPE_IP */
+#include <netinet/in.h>        /* IPPROTO_* */
+#include <netinet/ip.h>        /* struct ip */
+#include <netinet/udp.h>       /* struct udp */
 
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
 
-#include <net/netmap.h>
+#define NETMAP_WITH_LIBS
 #include <net/netmap_user.h>
 
-#ifndef MY_PCAP                /* use the system's pcap if available */
-
-#ifdef NO_PCAP
-#define        PCAP_ERRBUF_SIZE        512
-typedef void pcap_t;
-struct pcap_pkthdr;
-#define        pcap_inject(a,b,c)      ((void)a, (void)b, (void)c, -1)
-#define        pcap_dispatch(a, b, c, d)       (void)c
-#define        pcap_open_live(a, b, c, d, e)   ((void)e, NULL)
-#else /* !NO_PCAP */
-#include <pcap/pcap.h> // XXX do we need it ?
-#endif /* !NO_PCAP */
-
-#endif // XXX hack
-
 #include <pthread.h>   /* pthread_* */
 
 #ifdef linux
 
 #define cpuset_t       cpu_set_t
 
-#define ifr_flagshigh  ifr_flags
-#define ifr_curcap     ifr_flags
-#define ifr_reqcap     ifr_flags
-#define IFF_PPROMISC   IFF_PROMISC
+#define ifr_flagshigh  ifr_flags       /* only the low 16 bits here */
+#define IFF_PPROMISC   IFF_PROMISC     /* IFF_PPROMISC does not exist */
 #include <linux/ethtool.h>
 #include <linux/sockios.h>
 
@@ -107,6 +78,20 @@ struct pcap_pkthdr;
 #endif /* __FreeBSD__ */
 
 #ifdef __APPLE__
+
+#define cpuset_t       uint64_t        // XXX
+static inline void CPU_ZERO(cpuset_t *p)
+{
+       *p = 0;
+}
+
+static inline void CPU_SET(uint32_t i, cpuset_t *p)
+{
+       *p |= 1<< (i & 0x3f);
+}
+
+#define pthread_setaffinity_np(a, b, c)        ((void)a, 0)
+
 #define ifr_flagshigh  ifr_flags       // XXX
 #define IFF_PPROMISC   IFF_PROMISC
 #include <net/if_dl.h>  /* LLADDR */
@@ -136,54 +121,7 @@ extern int time_second;
 
 
 
-// XXX does it work on 32-bit machines ?
-static inline void prefetch (const void *x)
-{
-       __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x));
-}
-
-// XXX only for multiples of 64 bytes, non overlapped.
-static inline void
-pkt_copy(const void *_src, void *_dst, int l)
-{
-       const uint64_t *src = _src;
-       uint64_t *dst = _dst;
-#define likely(x)       __builtin_expect(!!(x), 1)
-#define unlikely(x)       __builtin_expect(!!(x), 0)
-       if (unlikely(l >= 1024)) {
-               bcopy(src, dst, l);
-               return;
-       }
-       for (; l > 0; l-=64) {
-               *dst++ = *src++;
-               *dst++ = *src++;
-               *dst++ = *src++;
-               *dst++ = *src++;
-               *dst++ = *src++;
-               *dst++ = *src++;
-               *dst++ = *src++;
-               *dst++ = *src++;
-       }
-}
-
-/*
- * info on a ring we handle
- */
-struct my_ring {
-       const char *ifname;
-       int fd;
-       char *mem;                      /* userspace mmap address */
-       u_int memsize;
-       u_int queueid;
-       u_int begin, end;               /* first..last+1 rings to check */
-       struct netmap_if *nifp;
-       struct netmap_ring *tx, *rx;    /* shortcuts */
-
-       uint32_t if_flags;
-       uint32_t if_reqcap;
-       uint32_t if_curcap;
-};
-int netmap_open(struct my_ring *me, int ringid, int promisc);
-int netmap_close(struct my_ring *me);
-int nm_do_ioctl(struct my_ring *me, u_long what, int subcmd);
+struct nm_desc_t * netmap_open(const char *name, int ringid, int promisc);
+int nm_do_ioctl(struct nm_desc_t *me, u_long what, int subcmd);
+int pkt_queued(struct nm_desc_t *d, int tx);
 #endif /* _NM_UTIL_H */

Modified: head/tools/tools/netmap/pcap.c
==============================================================================
--- head/tools/tools/netmap/pcap.c      Wed Jan 15 22:47:53 2014        
(r260699)
+++ head/tools/tools/netmap/pcap.c      Thu Jan 16 00:20:42 2014        
(r260700)
@@ -65,7 +65,7 @@ struct pcap_stat {
 #endif /* WIN32 */
 };
 
-typedef void   pcap_t;
+typedef struct nm_desc_t       pcap_t;
 typedef enum {
        PCAP_D_INOUT = 0,
        PCAP_D_IN,
@@ -107,41 +107,6 @@ struct eproto {
 
 char pcap_version[] = "libnetmap version 0.3";
 
-/*
- * Our equivalent of pcap_t
- */
-struct pcap_ring {
-       struct my_ring me;
-#if 0
-       const char *ifname;
-
-       //struct nmreq nmr;
-
-       int fd;
-       char *mem;                      /* userspace mmap address */
-       u_int memsize;
-       u_int queueid;
-       u_int begin, end;               /* first..last+1 rings to check */
-       struct netmap_if *nifp;
-
-       uint32_t if_flags;
-       uint32_t if_reqcap;
-       uint32_t if_curcap;
-#endif
-       int snaplen;
-       char *errbuf;
-       int promisc;
-       int to_ms;
-
-       struct pcap_pkthdr hdr;
-
-
-       struct pcap_stat st;
-
-       char msg[PCAP_ERRBUF_SIZE];
-};
-
-
 
 /*
  * There is a set of functions that tcpdump expects even if probably
@@ -279,7 +244,7 @@ pcap_can_set_rfmon(pcap_t *p)
 int
 pcap_set_snaplen(pcap_t *p, int snaplen)
 {
-       struct pcap_ring *me = p;
+       struct nm_desc_t *me = p;
 
        D("len %d", snaplen);
        me->snaplen = snaplen;
@@ -289,7 +254,7 @@ pcap_set_snaplen(pcap_t *p, int snaplen)
 int
 pcap_snapshot(pcap_t *p)
 {
-       struct pcap_ring *me = p;
+       struct nm_desc_t *me = p;
 
        D("len %d", me->snaplen);
        return me->snaplen;
@@ -310,17 +275,15 @@ pcap_lookupnet(const char *device, uint3
 int
 pcap_set_promisc(pcap_t *p, int promisc)
 {
-       struct pcap_ring *me = p;
-
        D("promisc %d", promisc);
-        if (nm_do_ioctl(&me->me, SIOCGIFFLAGS, 0))
+        if (nm_do_ioctl(p, SIOCGIFFLAGS, 0))
                D("SIOCGIFFLAGS failed");
        if (promisc) {
-               me->me.if_flags |= IFF_PPROMISC;
+               p->if_flags |= IFF_PPROMISC;
        } else {
-               me->me.if_flags &= ~IFF_PPROMISC;
+               p->if_flags &= ~IFF_PPROMISC;
        }
-       if (nm_do_ioctl(&me->me, SIOCSIFFLAGS, 0))
+       if (nm_do_ioctl(p, SIOCSIFFLAGS, 0))
                D("SIOCSIFFLAGS failed");
        return 0;
 }
@@ -328,10 +291,8 @@ pcap_set_promisc(pcap_t *p, int promisc)
 int
 pcap_set_timeout(pcap_t *p, int to_ms)
 {
-       struct pcap_ring *me = p;
-
        D("%d ms", to_ms);
-       me->to_ms = to_ms;
+       p->to_ms = to_ms;
        return 0;
 }
 
@@ -384,31 +345,24 @@ struct pcap_stat;
 int
 pcap_stats(pcap_t *p, struct pcap_stat *ps)
 {
-       struct pcap_ring *me = p;
-       ND("");
-
-       *ps = me->st;
+       *ps = *(struct pcap_stat *)(void *)&(p->st);
        return 0;       /* accumulate from pcap_dispatch() */
 };
 
 char *
 pcap_geterr(pcap_t *p)
 {
-       struct pcap_ring *me = p;
-
        D("");
-       return me->msg;
+       return p->msg;
 }
 
 pcap_t *
 pcap_open_live(const char *device, int snaplen,
                int promisc, int to_ms, char *errbuf)
 {
-       struct pcap_ring *me;
+       struct nm_desc_t *d;
        int l;
 
-       (void)snaplen;  /* UNUSED */
-       (void)errbuf;   /* UNUSED */
        if (!device) {
                D("missing device name");
                return NULL;
@@ -417,54 +371,40 @@ pcap_open_live(const char *device, int s
        l = strlen(device) + 1;
        D("request to open %s snaplen %d promisc %d timeout %dms",
                device, snaplen, promisc, to_ms);
-       me = calloc(1, sizeof(*me) + l);
-       if (me == NULL) {
-               D("failed to allocate struct for %s", device);
-               return NULL;
-       }
-       me->me.ifname = (char *)(me + 1);
-       strcpy((char *)me->me.ifname, device);
-       if (netmap_open(&me->me, 0, promisc)) {
+       d = nm_open(device, NULL,  0, 0);
+       if (d == NULL) {
                D("error opening %s", device);
-               free(me);
                return NULL;
        }
-       me->to_ms = to_ms;
+       d->to_ms = to_ms;
+       d->snaplen = snaplen;
+       d->errbuf = errbuf;
+       d->promisc = promisc;
 
-       return (pcap_t *)me;
+       return d;
 }
 
 void
 pcap_close(pcap_t *p)
 {
-       struct my_ring *me = p;
-
-       D("");
-       if (!me)
-               return;
-       if (me->mem)
-               munmap(me->mem, me->memsize);
+       nm_close(p);
        /* restore original flags ? */
-       close(me->fd);
-       bzero(me, sizeof(*me));
-       free(me);
 }
 
 int
 pcap_fileno(pcap_t *p)
 {
-       struct my_ring *me = p;
-       D("returns %d", me->fd);
-       return me->fd;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to