svn commit: r246896 - head/tools/tools/netmap

Luigi Rizzo luigi at FreeBSD.org
Sun Feb 17 04:43:24 UTC 2013


Author: luigi
Date: Sun Feb 17 04:43:22 2013
New Revision: 246896
URL: http://svnweb.freebsd.org/changeset/base/246896

Log:
  update the netmap example programs merging some common code in nm_util.c
  
  pkt-gen now implements several functions (unlimited transmit, receive,
  ping-pong) and can operate on a 'tap' device.

Added:
  head/tools/tools/netmap/nm_util.c   (contents, props changed)
  head/tools/tools/netmap/nm_util.h   (contents, props changed)
Modified:
  head/tools/tools/netmap/Makefile
  head/tools/tools/netmap/bridge.c
  head/tools/tools/netmap/pcap.c
  head/tools/tools/netmap/pkt-gen.c

Modified: head/tools/tools/netmap/Makefile
==============================================================================
--- head/tools/tools/netmap/Makefile	Sun Feb 17 03:33:13 2013	(r246895)
+++ head/tools/tools/netmap/Makefile	Sun Feb 17 04:43:22 2013	(r246896)
@@ -5,7 +5,7 @@
 # we can just define 'progs' and create custom targets.
 PROGS	=	pkt-gen bridge testpcap libnetmap.so
 
-CLEANFILES = $(PROGS) pcap.o
+CLEANFILES = $(PROGS) pcap.o nm_util.o
 NO_MAN=
 CFLAGS += -Werror -Wall -nostdinc -I/usr/include -I../../../sys
 CFLAGS += -Wextra
@@ -17,9 +17,12 @@ LDFLAGS += -lpthread -lpcap
 
 all: $(PROGS)
 
+pkt-gen bridge: nm_util.o
+	$(CC) $(CFLAGS) -o ${.TARGET} ${.TARGET:=.c} nm_util.o $(LDFLAGS)
+
 testpcap: pcap.c libnetmap.so
-	$(CC) $(CFLAGS) -L. -lnetmap -o ${.TARGET} pcap.c
+	$(CC) $(CFLAGS) -DTEST -L. -lnetmap -o ${.TARGET} pcap.c
 	
-libnetmap.so:	pcap.c
+libnetmap.so:	pcap.c nm_util.c
 	$(CC) $(CFLAGS) -fpic -c ${.ALLSRC}
 	$(CC) -shared -o ${.TARGET} ${.ALLSRC:.c=.o}

Modified: head/tools/tools/netmap/bridge.c
==============================================================================
--- head/tools/tools/netmap/bridge.c	Sun Feb 17 03:33:13 2013	(r246895)
+++ head/tools/tools/netmap/bridge.c	Sun Feb 17 04:43:22 2013	(r246896)
@@ -9,195 +9,24 @@
  * $FreeBSD$
  */
 
-#include <errno.h>
-#include <signal.h> /* signal */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h> /* strcmp */
-#include <fcntl.h> /* open */
-#include <unistd.h> /* close */
-
-#include <sys/endian.h> /* le64toh */
-#include <sys/mman.h> /* PROT_* */
-#include <sys/ioctl.h> /* ioctl */
-#include <machine/param.h>
-#include <sys/poll.h>
-#include <sys/socket.h> /* sockaddr.. */
-#include <arpa/inet.h> /* ntohs */
-
-#include <net/if.h>	/* ifreq */
-#include <net/ethernet.h>
-#include <net/netmap.h>
-#include <net/netmap_user.h>
+#include "nm_util.h"
 
-#include <netinet/in.h> /* sockaddr_in */
-
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
 
 int verbose = 0;
 
-/* debug support */
-#define ND(format, ...) {}
-#define D(format, ...) do {					\
-	if (!verbose) break;					\
-	struct timeval _xxts;					\
-	gettimeofday(&_xxts, NULL);				\
-        fprintf(stderr, "%03d.%06d %s [%d] " format "\n",	\
-	(int)_xxts.tv_sec %1000, (int)_xxts.tv_usec,		\
-        __FUNCTION__, __LINE__, ##__VA_ARGS__);			\
-	} while (0)
-
-
-char *version = "$Id: bridge.c 10857 2012-04-06 12:18:22Z luigi $";
+char *version = "$Id: bridge.c 12016 2013-01-23 17:24:22Z luigi $";
 
 static int do_abort = 0;
 
-/*
- * 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;
-};
-
 static void
-sigint_h(__unused int sig)
+sigint_h(int sig)
 {
+	(void)sig;	/* UNUSED */
 	do_abort = 1;
 	signal(SIGINT, SIG_DFL);
 }
 
 
-static int
-do_ioctl(struct my_ring *me, unsigned long what)
-{
-	struct ifreq ifr;
-	int error;
-
-	bzero(&ifr, sizeof(ifr));
-	strncpy(ifr.ifr_name, me->ifname, sizeof(ifr.ifr_name));
-	switch (what) {
-	case SIOCSIFFLAGS:
-		ifr.ifr_flagshigh = me->if_flags >> 16;
-		ifr.ifr_flags = me->if_flags & 0xffff;
-		break;
-	case SIOCSIFCAP:
-		ifr.ifr_reqcap = me->if_reqcap;
-		ifr.ifr_curcap = me->if_curcap;
-		break;
-	}
-	error = ioctl(me->fd, what, &ifr);
-	if (error) {
-		D("ioctl error 0x%lx", what);
-		return error;
-	}
-	switch (what) {
-	case SIOCGIFFLAGS:
-		me->if_flags = (ifr.ifr_flagshigh << 16) |
-			(0xffff & ifr.ifr_flags);
-		if (verbose)
-			D("flags are 0x%x", me->if_flags);
-		break;
-
-	case SIOCGIFCAP:
-		me->if_reqcap = ifr.ifr_reqcap;
-		me->if_curcap = ifr.ifr_curcap;
-		if (verbose)
-			D("curcap are 0x%x", me->if_curcap);
-		break;
-	}
-	return 0;
-}
-
-/*
- * open a device. if me->mem is null then do an mmap.
- */
-static int
-netmap_open(struct my_ring *me, int ringid)
-{
-	int fd, err, l;
-	struct nmreq req;
-
-	me->fd = fd = open("/dev/netmap", O_RDWR);
-	if (fd < 0) {
-		D("Unable to open /dev/netmap");
-		return (-1);
-	}
-	bzero(&req, sizeof(req));
-	strncpy(req.nr_name, me->ifname, sizeof(req.nr_name));
-	req.nr_ringid = ringid;
-	req.nr_version = NETMAP_API;
-	err = ioctl(fd, NIOCGINFO, &req);
-	if (err) {
-		D("cannot get info on %s", me->ifname);
-		goto error;
-	}
-	me->memsize = l = req.nr_memsize;
-	if (verbose)
-		D("memsize is %d MB", l>>20);
-	err = ioctl(fd, NIOCREGIF, &req);
-	if (err) {
-		D("Unable to register %s", me->ifname);
-		goto error;
-	}
-
-	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;
-		}
-	}
-
-	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;
-}
-
-
-static int
-netmap_close(struct my_ring *me)
-{
-	D("");
-	if (me->mem)
-		munmap(me->mem, me->memsize);
-	ioctl(me->fd, NIOCUNREGIF, NULL);
-	close(me->fd);
-	return (0);
-}
-
-
 /*
  * move up to 'limit' pkts from rxring to txring swapping buffers.
  */
@@ -237,7 +66,7 @@ process_rings(struct netmap_ring *rxring
 		if (rs->len < 14 || rs->len > 2048)
 			D("wrong len %d rx[%d] -> tx[%d]", rs->len, j, k);
 		else if (verbose > 1)
-			D("send len %d rx[%d] -> tx[%d]", rs->len, j, k);
+			D("%s send len %d rx[%d] -> tx[%d]", msg, rs->len, j, k);
 		ts->len = rs->len;
 
 		/* report the buffer change. */
@@ -251,7 +80,7 @@ process_rings(struct netmap_ring *rxring
 	rxring->cur = j;
 	txring->cur = k;
 	if (verbose && m > 0)
-		D("sent %d packets to %p", m, txring);
+		D("%s sent %d packets to %p", msg, m, txring);
 
 	return (m);
 }
@@ -287,7 +116,7 @@ move(struct my_ring *src, struct my_ring
  * how many packets on this set of queues ?
  */
 static int
-howmany(struct my_ring *me, int tx)
+pkt_queued(struct my_ring *me, int tx)
 {
 	u_int i, tot = 0;
 
@@ -337,6 +166,7 @@ main(int argc, char **argv)
 
 	while ( (ch = getopt(argc, argv, "b:i:vw:")) != -1) {
 		switch (ch) {
+		default:
 			D("bad option %c %s", ch, optarg);
 			usage();
 			break;
@@ -361,6 +191,7 @@ main(int argc, char **argv)
 		}
 
 	}
+
 	argc -= optind;
 	argv += optind;
 
@@ -394,44 +225,12 @@ main(int argc, char **argv)
 		/* two different interfaces. Take all rings on if1 */
 		i = 0;	// all hw rings
 	}
-	if (netmap_open(me, i))
+	if (netmap_open(me, i, 1))
 		return (1);
 	me[1].mem = me[0].mem; /* copy the pointer, so only one mmap */
-	if (netmap_open(me+1, 0))
+	if (netmap_open(me+1, 0, 1))
 		return (1);
 
-	/* if bridging two interfaces, set promisc mode */
-	if (i != NETMAP_SW_RING) {
-		do_ioctl(me, SIOCGIFFLAGS);
-		if ((me[0].if_flags & IFF_UP) == 0) {
-			D("%s is down, bringing up...", me[0].ifname);
-			me[0].if_flags |= IFF_UP;
-		}
-		me[0].if_flags |= IFF_PPROMISC;
-		do_ioctl(me, SIOCSIFFLAGS);
-
-		do_ioctl(me+1, SIOCGIFFLAGS);
-		me[1].if_flags |= IFF_PPROMISC;
-		do_ioctl(me+1, SIOCSIFFLAGS);
-
-		/* also disable checksums etc. */
-		do_ioctl(me, SIOCGIFCAP);
-		me[0].if_reqcap = me[0].if_curcap;
-		me[0].if_reqcap &= ~(IFCAP_HWCSUM | IFCAP_TSO | IFCAP_TOE);
-		do_ioctl(me+0, SIOCSIFCAP);
-	}
-	do_ioctl(me+1, SIOCGIFFLAGS);
-	if ((me[1].if_flags & IFF_UP) == 0) {
-		D("%s is down, bringing up...", me[1].ifname);
-		me[1].if_flags |= IFF_UP;
-	}
-	do_ioctl(me+1, SIOCSIFFLAGS);
-
-	do_ioctl(me+1, SIOCGIFCAP);
-	me[1].if_reqcap = me[1].if_curcap;
-	me[1].if_reqcap &= ~(IFCAP_HWCSUM | IFCAP_TSO | IFCAP_TOE);
-	do_ioctl(me+1, SIOCSIFCAP);
-
 	/* setup poll(2) variables. */
 	memset(pollfd, 0, sizeof(pollfd));
 	for (i = 0; i < 2; i++) {
@@ -451,8 +250,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 = howmany(me, 0);
-		n1 = howmany(me + 1, 0);
+		n0 = pkt_queued(me, 0);
+		n1 = pkt_queued(me + 1, 0);
 		if (n0)
 			pollfd[1].events |= POLLOUT;
 		else
@@ -468,14 +267,14 @@ main(int argc, char **argv)
 				ret <= 0 ? "timeout" : "ok",
 				pollfd[0].events,
 				pollfd[0].revents,
-				howmany(me, 0),
+				pkt_queued(me, 0),
 				me[0].rx->cur,
-				howmany(me, 1),
+				pkt_queued(me, 1),
 				pollfd[1].events,
 				pollfd[1].revents,
-				howmany(me+1, 0),
+				pkt_queued(me+1, 0),
 				me[1].rx->cur,
-				howmany(me+1, 1)
+				pkt_queued(me+1, 1)
 			);
 		if (ret < 0)
 			continue;

Added: head/tools/tools/netmap/nm_util.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/netmap/nm_util.c	Sun Feb 17 04:43:22 2013	(r246896)
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2012 Luigi Rizzo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $FreeBSD$
+ * $Id$
+ *
+ * utilities to use netmap devices.
+ * This does the basic functions of opening a device and issuing
+ * ioctls()
+ */
+
+#include "nm_util.h"
+
+extern int verbose;
+
+int
+nm_do_ioctl(struct my_ring *me, u_long what, int subcmd)
+{
+	struct ifreq ifr;
+	int error;
+#if defined( __FreeBSD__ ) || defined (__APPLE__)
+	int fd = me->fd;
+#endif
+#ifdef linux 
+	struct ethtool_value eval;
+	int fd;
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd < 0) {
+		printf("Error: cannot get device control socket.\n");
+		return -1;
+	}
+#endif /* linux */
+
+	(void)subcmd;	// unused
+	bzero(&ifr, sizeof(ifr));
+	strncpy(ifr.ifr_name, me->ifname, sizeof(ifr.ifr_name));
+	switch (what) {
+	case SIOCSIFFLAGS:
+#ifndef __APPLE__
+		ifr.ifr_flagshigh = me->if_flags >> 16;
+#endif
+		ifr.ifr_flags = me->if_flags & 0xffff;
+		break;
+
+#if defined( __FreeBSD__ )
+	case SIOCSIFCAP:
+		ifr.ifr_reqcap = me->if_reqcap;
+		ifr.ifr_curcap = me->if_curcap;
+		break;
+#endif
+#ifdef linux
+	case SIOCETHTOOL:
+		eval.cmd = subcmd;
+		eval.data = 0;
+		ifr.ifr_data = (caddr_t)&eval;
+		break;
+#endif /* linux */
+	}
+	error = ioctl(fd, what, &ifr);
+	if (error)
+		goto done;
+	switch (what) {
+	case SIOCGIFFLAGS:
+#ifndef __APPLE__
+		me->if_flags = (ifr.ifr_flagshigh << 16) |
+			(0xffff & ifr.ifr_flags);
+#endif
+		if (verbose)
+			D("flags are 0x%x", me->if_flags);
+		break;
+
+#if defined( __FreeBSD__ )
+	case SIOCGIFCAP:
+		me->if_reqcap = ifr.ifr_reqcap;
+		me->if_curcap = ifr.ifr_curcap;
+		if (verbose)
+			D("curcap are 0x%x", me->if_curcap);
+		break;
+#endif /* __FreeBSD__ */
+	}
+done:
+#ifdef linux
+	close(fd);
+#endif
+	if (error)
+		D("ioctl error %d %lu", error, what);
+	return error;
+}
+
+/*
+ * open a device. if me->mem is null then do an mmap.
+ * Returns the file descriptor.
+ * The extra flag checks configures promisc mode.
+ */
+int
+netmap_open(struct my_ring *me, int ringid, int promisc)
+{
+	int fd, err, l;
+	struct nmreq req;
+
+	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, NIOCGINFO, &req);
+	if (err) {
+		D("cannot get info on %s, errno %d ver %d",
+			me->ifname, errno, req.nr_version);
+		goto error;
+	}
+	me->memsize = l = req.nr_memsize;
+	if (verbose)
+		D("memsize is %d MB", l>>20);
+	err = ioctl(fd, NIOCREGIF, &req);
+	if (err) {
+		D("Unable to register %s", me->ifname);
+		goto error;
+	}
+
+	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;
+		}
+	}
+
+
+	/* 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;
+		}
+		if (promisc) {
+			me[0].if_flags |= IFF_PPROMISC;
+			nm_do_ioctl(me, SIOCSIFFLAGS, 0);
+		}
+
+#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);
+#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);
+#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);
+	ioctl(me->fd, NIOCUNREGIF, NULL);
+	close(me->fd);
+	return (0);
+}
+
+
+/*
+ * how many packets on this set of queues ?
+ */
+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 += ring->avail;
+	}
+	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;
+}

Added: head/tools/tools/netmap/nm_util.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/netmap/nm_util.h	Sun Feb 17 04:43:22 2013	(r246896)
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2012 Luigi Rizzo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $FreeBSD$
+ * $Id$
+ *
+ * Some utilities to build netmap-based programs.
+ */
+
+#ifndef _NM_UTIL_H
+#define _NM_UTIL_H
+#include <errno.h>
+#include <signal.h>	/* signal */
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>	/* PRI* macros */
+#include <string.h>	/* strcmp */
+#include <fcntl.h>	/* open */
+#include <unistd.h>	/* close */
+#include <ifaddrs.h>	/* getifaddrs */
+
+#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 <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+
+#include <net/netmap.h>
+#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 ifr_flagshigh  ifr_flags
+#define ifr_curcap     ifr_flags
+#define ifr_reqcap     ifr_flags
+#define IFF_PPROMISC   IFF_PROMISC
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+
+#define CLOCK_REALTIME_PRECISE CLOCK_REALTIME
+#include <netinet/ether.h>      /* ether_aton */
+#include <linux/if_packet.h>    /* sockaddr_ll */
+#endif	/* linux */
+
+#ifdef __FreeBSD__
+#include <sys/endian.h> /* le64toh */
+#include <machine/param.h>
+
+#include <pthread_np.h> /* pthread w/ affinity */
+#include <sys/cpuset.h> /* cpu_set */
+#include <net/if_dl.h>  /* LLADDR */
+#endif	/* __FreeBSD__ */
+
+#ifdef __APPLE__
+#define ifr_flagshigh  ifr_flags	// XXX
+#define IFF_PPROMISC   IFF_PROMISC
+#include <net/if_dl.h>  /* LLADDR */
+#define clock_gettime(a,b)	\
+	do {struct timespec t0 = {0,0};	*(b) = t0; } while (0)
+#endif	/* __APPLE__ */
+
+static inline int min(int a, int b) { return a < b ? a : b; }
+extern int time_second;
+
+/* debug support */
+#define ND(format, ...)	do {} while(0)
+#define D(format, ...)					\
+	fprintf(stderr, "%s [%d] " format "\n",		\
+	__FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#define RD(lps, format, ...)				\
+	do {						\
+		static int t0, cnt;			\
+		if (t0 != time_second) {		\
+			t0 = time_second;		\
+			cnt = 0;			\
+		}					\
+		if (cnt++ < lps)			\
+			D(format, ##__VA_ARGS__);	\
+	} while (0)
+
+
+
+// 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);
+#endif /* _NM_UTIL_H */

Modified: head/tools/tools/netmap/pcap.c
==============================================================================
--- head/tools/tools/netmap/pcap.c	Sun Feb 17 03:33:13 2013	(r246895)
+++ head/tools/tools/netmap/pcap.c	Sun Feb 17 04:43:22 2013	(r246896)
@@ -1,5 +1,5 @@
 /*
- * (C) 2011 Luigi Rizzo
+ * (C) 2011-2012 Luigi Rizzo
  *
  * BSD license
  *
@@ -10,81 +10,18 @@
  * $FreeBSD$
  */
 
-#include <errno.h>
-#include <signal.h> /* signal */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h> /* strcmp */
-#include <fcntl.h> /* open */
-#include <unistd.h> /* close */
-
-#include <sys/endian.h> /* le64toh */
-#include <sys/mman.h> /* PROT_* */
-#include <sys/ioctl.h> /* ioctl */
-#include <machine/param.h>
-#include <sys/poll.h>
-#include <sys/socket.h> /* sockaddr.. */
-#include <arpa/inet.h> /* ntohs */
-
-#include <net/if.h>	/* ifreq */
-#include <net/ethernet.h>
-#include <net/netmap.h>
-#include <net/netmap_user.h>
+#define MY_PCAP
+#include "nm_util.h"
 
-#include <netinet/in.h> /* sockaddr_in */
-
-#include <sys/socket.h>
-#include <ifaddrs.h>
-
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-
-const char *version = "$Id$";
+char *version = "$Id: pcap.c 11463 2012-07-30 15:26:02Z luigi $";
 int verbose = 0;
 
-/* debug support */
-#define ND(format, ...) do {} while (0)
-#define D(format, ...) do {				\
-    if (verbose)					\
-        fprintf(stderr, "--- %s [%d] " format "\n",	\
-        __FUNCTION__, __LINE__, ##__VA_ARGS__);		\
-	} while (0)
-
-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++;
-        }
-}
-
 /*
  * We redefine here a number of structures that are in pcap.h
  * so we can compile this file without the system header.
  */
 #ifndef PCAP_ERRBUF_SIZE
 #define PCAP_ERRBUF_SIZE 128
-
 /*
  * Each packet is accompanied by a header including the timestamp,
  * captured size and actual size.
@@ -135,12 +72,13 @@ typedef enum {
 	PCAP_D_OUT
 } pcap_direction_t;
  
-struct bpf_program;
 
 
 typedef void (*pcap_handler)(u_char *user,
 		const struct pcap_pkthdr *h, const u_char *bytes);
 
+char errbuf[PCAP_ERRBUF_SIZE];
+
 pcap_t *pcap_open_live(const char *device, int snaplen,
                int promisc, int to_ms, char *errbuf);
 
@@ -154,24 +92,6 @@ char *pcap_lookupdev(char *errbuf);
 int pcap_inject(pcap_t *p, const void *buf, size_t size);
 int pcap_fileno(pcap_t *p);
 const char *pcap_lib_version(void);
-void	pcap_freealldevs(pcap_if_t *);
-pcap_t	*pcap_create(const char *, char *);
-int	pcap_activate(pcap_t *);
-int	pcap_can_set_rfmon(pcap_t *);
-int	pcap_set_snaplen(pcap_t *, int);
-int	pcap_snapshot(pcap_t *);
-int	pcap_lookupnet(const char *, uint32_t *, uint32_t *, char *);
-int	pcap_set_promisc(pcap_t *, int);
-int	pcap_set_timeout(pcap_t *, int);
-int	pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
-	    uint32_t);
-int	pcap_setfilter(pcap_t *, struct bpf_program *);
-int	pcap_datalink(pcap_t *);
-const char *pcap_datalink_val_to_name(int);
-const char *pcap_datalink_val_to_description(int);
-int	pcap_stats(pcap_t *, struct pcap_stat *);
-int	pcap_loop(pcap_t *, int, pcap_handler, u_char *);
-char	*pcap_geterr(pcap_t *);
 
 
 struct eproto {
@@ -180,7 +100,7 @@ struct eproto {
 };
 #endif /* !PCAP_ERRBUF_SIZE */
 
-#ifdef __PIC__
+#ifndef TEST
 /*
  * build as a shared library
  */
@@ -190,8 +110,12 @@ char pcap_version[] = "libnetmap version
 /*
  * Our equivalent of pcap_t
  */
-struct my_ring {
-	struct nmreq nmr;
+struct pcap_ring {
+	struct my_ring me;
+#if 0
+	const char *ifname;
+
+	//struct nmreq nmr;
 
 	int fd;
 	char *mem;			/* userspace mmap address */
@@ -200,6 +124,10 @@ struct my_ring {
 	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;
@@ -207,9 +135,6 @@ struct my_ring {
 
 	struct pcap_pkthdr hdr;
 
-	uint32_t if_flags;
-	uint32_t if_reqcap;
-	uint32_t if_curcap;
 
 	struct pcap_stat st;
 
@@ -217,114 +142,6 @@ struct my_ring {
 };
 
 
-static int
-do_ioctl(struct my_ring *me, unsigned long what)
-{
-	struct ifreq ifr;
-	int error;
-
-	bzero(&ifr, sizeof(ifr));
-	strncpy(ifr.ifr_name, me->nmr.nr_name, sizeof(ifr.ifr_name));
-	switch (what) {
-	case SIOCSIFFLAGS:
-		D("call SIOCSIFFLAGS 0x%x", me->if_flags);
-		ifr.ifr_flagshigh = (me->if_flags >> 16) & 0xffff;
-		ifr.ifr_flags = me->if_flags & 0xffff;
-		break;
-	case SIOCSIFCAP:
-		ifr.ifr_reqcap = me->if_reqcap;
-		ifr.ifr_curcap = me->if_curcap;
-		break;
-	}
-	error = ioctl(me->fd, what, &ifr);
-	if (error) {
-		D("ioctl 0x%lx error %d", what, error);
-		return error;
-	}
-	switch (what) {
-	case SIOCSIFFLAGS:
-	case SIOCGIFFLAGS:
-		me->if_flags = (ifr.ifr_flagshigh << 16) |
-			(0xffff & ifr.ifr_flags);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list