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