aboutsummaryrefslogtreecommitdiff
path: root/tools/tools/netmap
diff options
context:
space:
mode:
authorLuigi Rizzo <luigi@FreeBSD.org>2014-01-16 00:20:42 +0000
committerLuigi Rizzo <luigi@FreeBSD.org>2014-01-16 00:20:42 +0000
commitf26375266853d6a1037cadc43ee75d3f71a18403 (patch)
tree688605057e1e80e90412871111aef8f69489508b /tools/tools/netmap
parent7855b0bd6821862b7f6bcc776ef2d726b907d1c3 (diff)
downloadsrc-f26375266853d6a1037cadc43ee75d3f71a18403.tar.gz
src-f26375266853d6a1037cadc43ee75d3f71a18403.zip
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.
Notes
Notes: svn path=/head/; revision=260700
Diffstat (limited to 'tools/tools/netmap')
-rw-r--r--tools/tools/netmap/Makefile7
-rw-r--r--tools/tools/netmap/bridge.c89
-rw-r--r--tools/tools/netmap/nm_util.c173
-rw-r--r--tools/tools/netmap/nm_util.h118
-rw-r--r--tools/tools/netmap/pcap.c184
-rw-r--r--tools/tools/netmap/pkt-gen.c147
-rw-r--r--tools/tools/netmap/vale-ctl.c26
7 files changed, 263 insertions, 481 deletions
diff --git a/tools/tools/netmap/Makefile b/tools/tools/netmap/Makefile
index d737bac71939..e873389c7179 100644
--- a/tools/tools/netmap/Makefile
+++ b/tools/tools/netmap/Makefile
@@ -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>
diff --git a/tools/tools/netmap/bridge.c b/tools/tools/netmap/bridge.c
index 6dc77e438273..cab545bfc919 100644
--- a/tools/tools/netmap/bridge.c
+++ b/tools/tools/netmap/bridge.c
@@ -96,16 +96,16 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring,
/* 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 *dst, u_int limit)
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);
}
diff --git a/tools/tools/netmap/nm_util.c b/tools/tools/netmap/nm_util.c
index 1268840cd868..deb52bbc87e4 100644
--- a/tools/tools/netmap/nm_util.c
+++ b/tools/tools/netmap/nm_util.c
@@ -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 what, int subcmd)
}
#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 what, int subcmd)
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 from the same queue
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 from the same queue
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 */
diff --git a/tools/tools/netmap/nm_util.h b/tools/tools/netmap/nm_util.h
index d8f8f94fd162..0ab2e2e81984 100644
--- a/tools/tools/netmap/nm_util.h
+++ b/tools/tools/netmap/nm_util.h
@@ -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 */
diff --git a/tools/tools/netmap/pcap.c b/tools/tools/netmap/pcap.c
index dd87c4a1b00e..b3c2be5d23ff 100644
--- a/tools/tools/netmap/pcap.c
+++ b/tools/tools/netmap/pcap.c
@@ -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, uint32_t *netp,
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 snaplen,
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;
+ struct nm_desc_t *d = p;
+ D("returns %d", d->fd);
+ return d->fd;
}
int
pcap_get_selectable_fd(pcap_t *p)
{
- struct my_ring *me = p;
+ struct nm_desc_t *d = p;
- ND("");
- return me->fd;
+ return d->fd;
}
int
@@ -488,94 +428,32 @@ pcap_setdirection(pcap_t *p, pcap_direction_t d)
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
- struct pcap_ring *pme = p;
- struct my_ring *me = &pme->me;
- int got = 0;
- u_int si;
-
- ND("cnt %d", cnt);
- if (cnt == 0)
- cnt = -1;
- /* scan all rings */
- for (si = me->begin; si < me->end; si++) {
- struct netmap_ring *ring = NETMAP_RXRING(me->nifp, si);
- if (nm_ring_empty(ring))
- continue;
- pme->hdr.ts = ring->ts;
- /*
- * XXX a proper prefetch should be done as
- * prefetch(i); callback(i-1); ...
- */
- while ((cnt == -1 || cnt != got) && !nm_ring_empty(ring)) {
- u_int i = ring->cur;
- u_int idx = ring->slot[i].buf_idx;
- if (idx < 2) {
- D("%s bogus RX index %d at offset %d",
- me->nifp->ni_name, idx, i);
- sleep(2);
- }
- u_char *buf = (u_char *)NETMAP_BUF(ring, idx);
- prefetch(buf);
- pme->hdr.len = pme->hdr.caplen = ring->slot[i].len;
- // D("call %p len %d", p, me->hdr.len);
- callback(user, &pme->hdr, buf);
- ring->head = ring->cur = nm_ring_next(ring, i);
- got++;
- }
- }
- pme->st.ps_recv += got;
- return got;
+ return nm_dispatch(p, cnt, (void *)callback, user);
}
int
pcap_inject(pcap_t *p, const void *buf, size_t size)
{
- struct my_ring *me = p;
- u_int si;
-
- ND("cnt %d", cnt);
- /* scan all rings */
- for (si = me->begin; si < me->end; si++) {
- struct netmap_ring *ring = NETMAP_TXRING(me->nifp, si);
-
- if (nm_ring_empty(ring))
- continue;
- u_int i = ring->cur;
- u_int idx = ring->slot[i].buf_idx;
- if (idx < 2) {
- D("%s bogus TX index %d at offset %d",
- me->nifp->ni_name, idx, i);
- sleep(2);
- }
- u_char *dst = (u_char *)NETMAP_BUF(ring, idx);
- ring->slot[i].len = size;
- pkt_copy(buf, dst, size);
- ring->head = ring->cur = nm_ring_next(ring, i);
- // if (ring->cur == ring->tail) ioctl(me->fd, NIOCTXSYNC, NULL);
- return size;
- }
- errno = ENOBUFS;
- return -1;
+ return nm_inject(p, buf, size);
}
int
pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
- struct pcap_ring *me = p;
struct pollfd fds[1];
int i;
ND("cnt %d", cnt);
memset(fds, 0, sizeof(fds));
- fds[0].fd = me->me.fd;
+ fds[0].fd = p->fd;
fds[0].events = (POLLIN);
while (cnt == -1 || cnt > 0) {
- if (poll(fds, 1, me->to_ms) <= 0) {
+ if (poll(fds, 1, p->to_ms) <= 0) {
D("poll error/timeout");
continue;
}
- i = pcap_dispatch(p, cnt, callback, user);
+ i = nm_dispatch(p, cnt, (void *)callback, user);
if (cnt > 0)
cnt -= i;
}
@@ -640,9 +518,9 @@ main(int argc, char **argv)
if (ret < 0)
continue;
if (pollfd[0].revents & POLLIN)
- pcap_dispatch(p0, burst, do_send, p1);
+ pcap_dispatch(p0, burst, do_send, (void *)p1);
if (pollfd[1].revents & POLLIN)
- pcap_dispatch(p1, burst, do_send, p0);
+ pcap_dispatch(p1, burst, do_send, (void *)p0);
}
return (0);
diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c
index c1d084028d93..3fb7702083fd 100644
--- a/tools/tools/netmap/pkt-gen.c
+++ b/tools/tools/netmap/pkt-gen.c
@@ -37,10 +37,15 @@
*
*/
+#define MY_PCAP
#include "nm_util.h"
+// #include <net/netmap_user.h>
#include <ctype.h> // isprint()
+#ifndef NO_PCAP
+#include <pcap/pcap.h>
+#endif
const char *default_payload="netmap pkt-gen DIRECT payload\n"
"http://info.iet.unipi.it/~luigi/netmap/ ";
@@ -105,14 +110,16 @@ struct glob_arg {
#define OPT_INDIRECT 32 /* use indirect buffers, tx only */
#define OPT_DUMP 64 /* dump rx/tx traffic */
int dev_type;
+#ifndef NO_PCAP
pcap_t *p;
+#endif
int tx_rate;
struct timespec tx_period;
int affinity;
int main_fd;
- int report_interval;
+ int report_interval; /* milliseconds between prints */
void *(*td_body)(void *);
void *mmap_addr;
int mmap_size;
@@ -486,17 +493,18 @@ update_addresses(struct pkt *pkt, struct glob_arg *g)
struct ip *ip = &pkt->ip;
struct udphdr *udp = &pkt->udp;
+ do {
p = ntohs(udp->uh_sport);
if (p < g->src_ip.port1) { /* just inc, no wrap */
udp->uh_sport = htons(p + 1);
- return;
+ break;
}
udp->uh_sport = htons(g->src_ip.port0);
a = ntohl(ip->ip_src.s_addr);
if (a < g->src_ip.end) { /* just inc, no wrap */
ip->ip_src.s_addr = htonl(a + 1);
- return;
+ break;
}
ip->ip_src.s_addr = htonl(g->src_ip.start);
@@ -504,17 +512,18 @@ update_addresses(struct pkt *pkt, struct glob_arg *g)
p = ntohs(udp->uh_dport);
if (p < g->dst_ip.port1) { /* just inc, no wrap */
udp->uh_dport = htons(p + 1);
- return;
+ break;
}
udp->uh_dport = htons(g->dst_ip.port0);
a = ntohl(ip->ip_dst.s_addr);
if (a < g->dst_ip.end) { /* just inc, no wrap */
ip->ip_dst.s_addr = htonl(a + 1);
- return;
+ break;
}
ip->ip_dst.s_addr = htonl(g->dst_ip.start);
-
+ } while (0);
+ // update checksum
}
/*
@@ -531,13 +540,13 @@ initialize_packet(struct targ *targ)
uint16_t paylen = targ->g->pkt_size - sizeof(*eh) - sizeof(struct ip);
const char *payload = targ->g->options & OPT_INDIRECT ?
indirect_payload : default_payload;
- int i, l, l0 = strlen(payload);
+ int i, l0 = strlen(payload);
/* create a nice NUL-terminated string */
- for (i = 0; i < paylen;) {
- l = min(l0, paylen - i);
- bcopy(payload, pkt->body + i, l);
- i += l;
+ for (i = 0; i < paylen; i += l0) {
+ if (l0 > paylen - i)
+ l0 = paylen - i; // last round
+ bcopy(payload, pkt->body + i, l0);
}
pkt->body[i-1] = '\0';
ip = &pkt->ip;
@@ -593,7 +602,7 @@ send_packets(struct netmap_ring *ring, struct pkt *pkt, void *frame,
u_int nfrags)
{
u_int n, sent, cur = ring->cur;
- int fcnt;
+ u_int fcnt;
n = nm_ring_space(ring);
if (n < count)
@@ -608,7 +617,7 @@ send_packets(struct netmap_ring *ring, struct pkt *pkt, void *frame,
struct netmap_slot *slot = &ring->slot[cur];
char *p = NETMAP_BUF(ring, slot->buf_idx);
- prefetch(p);
+ __builtin_prefetch(p);
cur = nm_ring_next(ring, cur);
}
cur = ring->cur;
@@ -624,14 +633,14 @@ send_packets(struct netmap_ring *ring, struct pkt *pkt, void *frame,
slot->ptr = (uint64_t)frame;
} else if (options & OPT_COPY) {
pkt_copy(frame, p, size);
- if (fcnt == 1)
+ if (fcnt == nfrags)
update_addresses(pkt, g);
} else if (options & OPT_MEMCPY) {
memcpy(p, frame, size);
- if (fcnt == 1)
+ if (fcnt == nfrags)
update_addresses(pkt, g);
} else if (options & OPT_PREFETCH) {
- prefetch(p);
+ __builtin_prefetch(p);
}
if (options & OPT_DUMP)
dump_payload(p, size, ring, cur);
@@ -947,11 +956,11 @@ sender_body(void *data)
wait_time(targ->tic);
nexttime = targ->tic;
}
- if (targ->g->dev_type == DEV_PCAP) {
- pcap_t *p = targ->g->p;
+ if (targ->g->dev_type == DEV_TAP) {
+ D("writing to file desc %d", targ->g->main_fd);
for (i = 0; !targ->cancel && (n == 0 || sent < n); i++) {
- if (pcap_inject(p, frame, size) != -1)
+ if (write(targ->g->main_fd, frame, size) != -1)
sent++;
update_addresses(pkt, targ->g);
if (i > 10000) {
@@ -959,11 +968,12 @@ sender_body(void *data)
i = 0;
}
}
- } else if (targ->g->dev_type == DEV_TAP) { /* tap */
- D("writing to file desc %d", targ->g->main_fd);
+#ifndef NO_PCAP
+ } else if (targ->g->dev_type == DEV_PCAP) {
+ pcap_t *p = targ->g->p;
for (i = 0; !targ->cancel && (n == 0 || sent < n); i++) {
- if (write(targ->g->main_fd, frame, size) != -1)
+ if (pcap_inject(p, frame, size) != -1)
sent++;
update_addresses(pkt, targ->g);
if (i > 10000) {
@@ -971,6 +981,7 @@ sender_body(void *data)
i = 0;
}
}
+#endif /* NO_PCAP */
} else {
int tosend = 0;
int frags = targ->g->frags;
@@ -1016,8 +1027,8 @@ sender_body(void *data)
m = send_packets(txring, pkt, frame, size, targ->g,
limit, options, frags);
- ND("limit %d avail %d frags %d m %d",
- limit, txring->avail, frags, m);
+ ND("limit %d tail %d frags %d m %d",
+ limit, txring->tail, frags, m);
sent += m;
targ->count = sent;
if (rate_limit) {
@@ -1038,7 +1049,7 @@ sender_body(void *data)
usleep(1); /* wait 1 tick */
}
}
- }
+ } /* end DEV_NETMAP */
clock_gettime(CLOCK_REALTIME_PRECISE, &targ->toc);
targ->completed = 1;
@@ -1052,6 +1063,7 @@ quit:
}
+#ifndef NO_PCAP
static void
receive_pcap(u_char *user, const struct pcap_pkthdr * h,
const u_char * bytes)
@@ -1061,6 +1073,7 @@ receive_pcap(u_char *user, const struct pcap_pkthdr * h,
(void)bytes; /* UNUSED */
(*count)++;
}
+#endif /* !NO_PCAP */
static int
receive_packets(struct netmap_ring *ring, u_int limit, int dump)
@@ -1113,12 +1126,7 @@ receiver_body(void *data)
/* main loop, exit after 1s silence */
clock_gettime(CLOCK_REALTIME_PRECISE, &targ->tic);
- if (targ->g->dev_type == DEV_PCAP) {
- while (!targ->cancel) {
- /* XXX should we poll ? */
- pcap_dispatch(targ->g->p, targ->g->burst, receive_pcap, NULL);
- }
- } else if (targ->g->dev_type == DEV_TAP) {
+ if (targ->g->dev_type == DEV_TAP) {
D("reading from %s fd %d", targ->g->ifname, targ->g->main_fd);
while (!targ->cancel) {
char buf[2048];
@@ -1126,6 +1134,13 @@ receiver_body(void *data)
if (read(targ->g->main_fd, buf, sizeof(buf)) > 0)
targ->count++;
}
+#ifndef NO_PCAP
+ } else if (targ->g->dev_type == DEV_PCAP) {
+ while (!targ->cancel) {
+ /* XXX should we poll ? */
+ pcap_dispatch(targ->g->p, targ->g->burst, receive_pcap, NULL);
+ }
+#endif /* !NO_PCAP */
} else {
int dump = targ->g->options & OPT_DUMP;
while (!targ->cancel) {
@@ -1533,7 +1548,7 @@ main(int arc, char **argv)
g.virt_header = 0;
while ( (ch = getopt(arc, argv,
- "a:f:F:n:i:It:r:l:d:s:D:S:b:c:o:p:PT:w:WvR:XC:H:h")) != -1) {
+ "a:f:F:n:i:It:r:l:d:s:D:S:b:c:o:p:T:w:WvR:XC:H:h")) != -1) {
struct sf *fn;
switch(ch) {
@@ -1575,13 +1590,28 @@ main(int arc, char **argv)
break;
case 'i': /* interface */
+ /* a prefix of tap: netmap: or pcap: forces the mode.
+ * otherwise we guess
+ */
+ D("interface is %s", optarg);
g.ifname = optarg;
- if (!strncmp(optarg, "tap", 3))
- g.dev_type = DEV_TAP;
- else
+ if (!strcmp(optarg, "null")) {
g.dev_type = DEV_NETMAP;
- if (!strcmp(g.ifname, "null"))
g.dummy_send = 1;
+ } else if (!strncmp(optarg, "tap:", 4)) {
+ g.dev_type = DEV_TAP;
+ g.ifname = optarg + 4;
+ } else if (!strncmp(optarg, "pcap:", 5)) {
+ g.dev_type = DEV_PCAP;
+ g.ifname = optarg + 5;
+ } else if (!strncmp(optarg, "netmap:", 7)) {
+ g.dev_type = DEV_NETMAP;
+ g.ifname = optarg + 7;
+ } else if (!strncmp(optarg, "tap", 3)) {
+ g.dev_type = DEV_TAP;
+ } else {
+ g.dev_type = DEV_NETMAP;
+ }
break;
case 'I':
@@ -1634,10 +1664,6 @@ main(int arc, char **argv)
g.nthreads = atoi(optarg);
break;
- case 'P':
- g.dev_type = DEV_PCAP;
- break;
-
case 'D': /* destination mac */
g.dst_mac.name = optarg;
break;
@@ -1659,8 +1685,10 @@ main(int arc, char **argv)
break;
case 'H':
g.virt_header = atoi(optarg);
+ break;
case 'h':
g.host_ring = 1;
+ break;
}
}
@@ -1697,6 +1725,12 @@ main(int arc, char **argv)
extract_mac_range(&g.src_mac);
extract_mac_range(&g.dst_mac);
+ if (g.src_ip.start != g.src_ip.end ||
+ g.src_ip.port0 != g.src_ip.port1 ||
+ g.dst_ip.start != g.dst_ip.end ||
+ g.dst_ip.port0 != g.dst_ip.port1)
+ g.options |= OPT_COPY;
+
if (g.virt_header != 0 && g.virt_header != VIRT_HDR_1
&& g.virt_header != VIRT_HDR_2) {
D("bad virtio-net-header length");
@@ -1710,7 +1744,8 @@ main(int arc, char **argv)
D("cannot open tap %s", g.ifname);
usage();
}
- } else if (g.dev_type > DEV_NETMAP) {
+#ifndef NO_PCAP
+ } else if (g.dev_type == DEV_PCAP) {
char pcap_errbuf[PCAP_ERRBUF_SIZE];
D("using pcap on %s", g.ifname);
@@ -1720,7 +1755,8 @@ main(int arc, char **argv)
D("cannot open pcap on %s", g.ifname);
usage();
}
- } else if (g.dummy_send) {
+#endif /* !NO_PCAP */
+ } else if (g.dummy_send) { /* but DEV_NETMAP */
D("using a dummy send routine");
} else {
bzero(&nmr, sizeof(nmr));
@@ -1758,9 +1794,6 @@ main(int arc, char **argv)
ND("%s: txr %d txd %d rxr %d rxd %d", g.ifname,
nmr.nr_tx_rings, nmr.nr_tx_slots,
nmr.nr_rx_rings, nmr.nr_rx_slots);
- if ((ioctl(g.main_fd, NIOCGINFO, &nmr)) == -1) {
- D("Unable to get if info for %s: %s", g.ifname, strerror(errno));
- }
devqueues = nmr.nr_rx_rings;
/* validate provided nthreads. */
@@ -1784,7 +1817,21 @@ main(int arc, char **argv)
// continue, fail later
}
+ if (verbose) {
+ struct netmap_if *nifp = NETMAP_IF(g.mmap_addr, nmr.nr_offset);
+ D("nifp at offset %d, %d tx %d rx rings %s",
+ nmr.nr_offset, nmr.nr_tx_rings, nmr.nr_rx_rings,
+ nmr.nr_ringid & NETMAP_PRIV_MEM ? "PRIVATE" : "common" );
+ for (i = 0; i <= nmr.nr_tx_rings; i++) {
+ D(" TX%d at 0x%lx", i,
+ (char *)NETMAP_TXRING(nifp, i) - (char *)nifp);
+ }
+ for (i = 0; i <= nmr.nr_rx_rings; i++) {
+ D(" RX%d at 0x%lx", i,
+ (char *)NETMAP_RXRING(nifp, i) - (char *)nifp);
+ }
+ }
/* Print some debug information. */
fprintf(stdout,
@@ -1846,16 +1893,6 @@ main(int arc, char **argv)
global_nthreads = g.nthreads;
signal(SIGINT, sigint_h);
-#if 0 // XXX this is not needed, i believe
- if (g.dev_type > DEV_NETMAP) {
- g.p = pcap_open_live(g.ifname, 0, 1, 100, NULL);
- if (g.p == NULL) {
- D("cannot open pcap on %s", g.ifname);
- usage();
- } else
- D("using pcap %p on %s", g.p, g.ifname);
- }
-#endif // XXX
start_threads(&g);
main_thread(&g);
return 0;
diff --git a/tools/tools/netmap/vale-ctl.c b/tools/tools/netmap/vale-ctl.c
index c0cf574986b6..eb6c48d15a04 100644
--- a/tools/tools/netmap/vale-ctl.c
+++ b/tools/tools/netmap/vale-ctl.c
@@ -69,20 +69,22 @@ bdg_ctl(const char *name, int nr_cmd, int nr_arg)
nr_arg = 0;
nmr.nr_arg1 = nr_arg;
error = ioctl(fd, NIOCREGIF, &nmr);
- if (error == -1)
- D("Unable to %s %s to the bridge", nr_cmd ==
+ if (error == -1) {
+ ND("Unable to %s %s to the bridge", nr_cmd ==
NETMAP_BDG_DETACH?"detach":"attach", name);
- else
- D("Success to %s %s to the bridge\n", nr_cmd ==
+ perror(name);
+ } else
+ ND("Success to %s %s to the bridge", nr_cmd ==
NETMAP_BDG_DETACH?"detach":"attach", name);
break;
case NETMAP_BDG_LIST:
if (strlen(nmr.nr_name)) { /* name to bridge/port info */
error = ioctl(fd, NIOCGINFO, &nmr);
- if (error)
- D("Unable to obtain info for %s", name);
- else
+ if (error) {
+ ND("Unable to obtain info for %s", name);
+ perror(name);
+ } else
D("%s at bridge:%d port:%d", name, nmr.nr_arg1,
nmr.nr_arg2);
break;
@@ -101,9 +103,10 @@ bdg_ctl(const char *name, int nr_cmd, int nr_arg)
default: /* GINFO */
nmr.nr_cmd = nmr.nr_arg1 = nmr.nr_arg2 = 0;
error = ioctl(fd, NIOCGINFO, &nmr);
- if (error)
- D("Unable to get if info for %s", name);
- else
+ if (error) {
+ ND("Unable to get if info for %s", name);
+ perror(name);
+ } else
D("%s: %d queues.", name, nmr.nr_rx_rings);
break;
}
@@ -164,6 +167,5 @@ usage:
}
if (argc == 1)
nr_cmd = NETMAP_BDG_LIST;
- bdg_ctl(name, nr_cmd, nr_arg);
- return 0;
+ return bdg_ctl(name, nr_cmd, nr_arg) ? 1 : 0;
}