svn commit: r260700 - in head: sys/dev/netmap tools/tools/netmap

Luigi Rizzo luigi at FreeBSD.org
Thu Jan 16 00:20:44 UTC 2014


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 ***


More information about the svn-src-all mailing list