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-all
mailing list