Commit 6c7c3f20 authored by Eddie Kohler's avatar Eddie Kohler

Netmap zero-copy (and some other improvements).

* Netmap supports zero copy packet transfer (on single threaded
  machines).
* Allow --with-netmap=NETMAPDIRECTORY.
* Improve some configury help messages.
* Fix ToDevice bug.
parent 6128b00a
......@@ -1593,7 +1593,7 @@ EOF
shortensyms)
shift 1; shortensyms "$@"; exit 0;;
--cf|--cfl|--cfla|--cflag|--cflags|--d|--de|--def|--defs)
echo @PROPER_INCLUDES@ @PCAP_INCLUDES@ -I@includedir@; exit 0;;
echo @PROPER_INCLUDES@ @PCAP_INCLUDES@ @NETMAP_INCLUDES@ -I@includedir@; exit 0;;
--o|--ot|--oth|--othe|--other|--otherl|--otherli|--otherlib|--otherlibs)
echo @PROPER_LIBS@ @PCAP_LIBS@ @DL_LIBS@ @SOCKET_LIBS@ @PTHREAD_LIBS@ @POSIX_CLOCK_LIBS@;
exit 0;;
......
......@@ -47,7 +47,7 @@ while true; do
--dr=*|--dri=*|--driv=*|--drive=*|--driver=*)
driver=`echo "$1" | sed 's/[-a-z]*=//'`; shift 1;;
--c|--cf|--cfl|--cfla|--cflag|--cflags|--de|--def|--defs)
echo @PROPER_INCLUDES@ @PCAP_INCLUDES@ -I$includedir
echo @PROPER_INCLUDES@ @PCAP_INCLUDES@ @NETMAP_INCLUDES@ -I$includedir
exit=y; shift 1;;
--l|--li|--lib|--libs)
echo -L$libdir -lclick @PROPER_LIBS@ @PCAP_LIBS@ @DL_LIBS@ @SOCKET_LIBS@ @PTHREAD_LIBS@ @POSIX_CLOCK_LIBS@
......
......@@ -640,6 +640,7 @@ EXPAT_INCLUDES
XML2CLICK
PROPER_LIBS
PROPER_INCLUDES
NETMAP_INCLUDES
PCAP_LIBS
PCAP_INCLUDES
TOOL_TARGETS
......@@ -809,6 +810,7 @@ enable_dmalloc
enable_valgrind
enable_schedule_debugging
enable_intel_cpu
with_netmap
with_proper
with_expat
'
......@@ -1442,11 +1444,13 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-userlevel disable user-level driver
--enable-user-multithread support userlevel multithreading
--enable-select=[select|poll|kqueue] set file descriptor wait mechanism
--disable-select do not use select()
--disable-poll do not use poll()
--disable-kqueue do not use kqueue()
--enable-user-multithread
support userlevel multithreading
--enable-select=[select|poll|kqueue]
set file descriptor wait mechanism
--disable-select do not use select()
--disable-poll do not use poll()
--disable-kqueue do not use kqueue()
--disable-linuxmodule disable Linux kernel driver
--disable-fixincludes do not patch Linux kernel headers for C++
--enable-multithread support kernel multithreading
......@@ -1500,6 +1504,7 @@ Optional Packages:
--with-linux-map[=FILE] filename for Linux System.map [LINUXDIR/System.map]
--with-freebsd[=SRC,INC] FreeBSD source code is in SRC [/usr/src/sys],
include directory is INC [/usr/include]
--with-netmap enable netmap [no]
--with-proper[=PREFIX] use PlanetLab Proper library (optional)
--with-expat[=PREFIX] locate expat XML library (optional)
......@@ -6194,7 +6199,7 @@ fi
if test "${enable_select+set}" = set; then :
enableval=$enable_select; :
else
enable_select='select poll kqueue'
enable_select="select poll kqueue"
fi
# Check whether --enable-poll was given.
......@@ -7361,7 +7366,7 @@ else
ac_cv_endian=0
cat > conftest.$ac_ext <<EOF
#line 7364 "configure"
#line 7369 "configure"
#include "confdefs.h"
#include <$endian_hdr>
#ifdef __BYTE_ORDER
......@@ -10162,14 +10167,31 @@ done
fi
# Check whether --with-netmap was given.
if test "${with_netmap+set}" = set; then :
withval=$with_netmap; use_netmap=$withval
else
use_netmap=no
fi
if test "$use_netmap" != "yes" -a "$use_netmap" != "no"; then
if test "${NETMAP_INCLUDES-NO}" != NO; then
:
elif test -f "$use_netmap/net/netmap.h"; then
NETMAP_INCLUDES="-I$use_netmap"
elif test -f "$use_netmap/include/net/netmap.h"; then
NETMAP_INCLUDES="-I$use_netmap/include"
fi
fi
saveflags="$CPPFLAGS"
CPPFLAGS="$saveflags $NETMAP_INCLUDES"
HAVE_NETMAP=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for net/netmap.h" >&5
$as_echo_n "checking for net/netmap.h... " >&6; }
if ${ac_cv_net_netmap_header_path+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <net/netmap.h>
_ACEOF
......@@ -10179,9 +10201,9 @@ else
ac_cv_net_netmap_header_path="not found"
fi
rm -f conftest.err conftest.i conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_net_netmap_header_path" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_net_netmap_header_path" >&5
$as_echo "$ac_cv_net_netmap_header_path" >&6; }
if test "$ac_cv_net_netmap_header_path" = "found"; then
HAVE_NETMAP=yes
fi
......@@ -10209,12 +10231,14 @@ $as_echo "$ac_cv_working_net_netmap_h" >&6; }
test "$ac_cv_working_net_netmap_h" != yes && HAVE_NETMAP=
fi
if test "$HAVE_NETMAP" = yes; then
CPPFLAGS="$saveflags"
if test "$HAVE_NETMAP" = yes -a "$use_netmap" != no; then
$as_echo "#define HAVE_NET_NETMAP_H 1" >>confdefs.h
fi
if test "$HAVE_PCAP" != yes -a "$HAVE_NETMAP" != yes -a "$ac_cv_under_linux" != yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
=========================================
......@@ -12424,6 +12448,10 @@ if test $ac_have_linux_kernel = y; then
fi
fi
if test "x$HAVE_NETMAP" = xyes; then
provisions="$provisions netmap"
fi
if test "x$HAVE_PCAP" = xyes; then
provisions="$provisions pcap"
fi
......
......@@ -65,9 +65,13 @@ dnl
dnl userlevel driver and features
AC_ARG_ENABLE(userlevel, [ --disable-userlevel disable user-level driver], :, enable_userlevel=yes)
AC_ARG_ENABLE([userlevel],
[AS_HELP_STRING([--disable-userlevel], [disable user-level driver])],
[:], [enable_userlevel=yes])
AC_ARG_ENABLE(user-multithread, [[ --enable-user-multithread support userlevel multithreading]], :, [enable_user_multithread=no])
AC_ARG_ENABLE([user-multithread],
[AS_HELP_STRING([ --enable-user-multithread], [support userlevel multithreading])],
[:], [enable_user_multithread=no])
PTHREAD_LIBS=""
AC_SUBST(PTHREAD_LIBS)
......@@ -93,10 +97,16 @@ Can't find -lpthread and/or <pthread.h>, so I can't compile with
LIBS="$SAVE_LIBS"
fi
AC_ARG_ENABLE([select], [ --enable-select=[[select|poll|kqueue]] set file descriptor wait mechanism
--disable-select do not use select()], [:], [enable_select='select poll kqueue'])
AC_ARG_ENABLE([poll], [ --disable-poll do not use poll()], [:], [enable_poll=yes])
AC_ARG_ENABLE([kqueue], [ --disable-kqueue do not use kqueue()], [:], [enable_kqueue=yes])
AC_ARG_ENABLE([select],
[AS_HELP_STRING([ --enable-select=[[select|poll|kqueue]]], [set file descriptor wait mechanism])
AS_HELP_STRING([ --disable-select], [do not use select()])],
[:], [enable_select="select poll kqueue"])
AC_ARG_ENABLE([poll],
[AS_HELP_STRING([ --disable-poll], [do not use poll()])],
[:], [enable_poll=yes])
AC_ARG_ENABLE([kqueue],
[AS_HELP_STRING([ --disable-kqueue], [do not use kqueue()])],
[:], [enable_kqueue=yes])
if test "$enable_select" = yes; then
enable_select='select poll kqueue'
......@@ -1746,6 +1756,11 @@ if test $ac_have_linux_kernel = y; then
fi
fi
dnl add 'netmap' if netmap support is available
if test "x$HAVE_NETMAP" = xyes; then
provisions="$provisions netmap"
fi
dnl add 'pcap' if libpcap is available
if test "x$HAVE_PCAP" = xyes; then
provisions="$provisions pcap"
......
......@@ -7,6 +7,7 @@
* Copyright (c) 2001 International Computer Science Institute
* Copyright (c) 2005-2007 Regents of the University of California
* Copyright (c) 2011 Meraki, Inc.
* Copyright (c) 2012 Eddie Kohler
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
......@@ -272,56 +273,6 @@ FromDevice::open_pcap(String ifname, int snaplen, bool promisc,
}
#endif
#if FROMDEVICE_ALLOW_NETMAP
int
FromDevice::netmap_type::open(const String &ifname,
bool always_error, ErrorHandler *errh)
{
ErrorHandler *initial_errh = always_error ? errh : ErrorHandler::silent_handler();
int fd = ::open("/dev/netmap", O_RDWR);
if (fd < 0) {
initial_errh->error("/dev/netmap: %s", strerror(errno));
return -1;
}
struct nmreq req;
memset(&req, 0, sizeof(req));
strncpy(req.nr_name, ifname.c_str(), sizeof(req.nr_name));
req.nr_ringid = 0;
int r;
if ((r = ioctl(fd, NIOCGINFO, &req))) {
initial_errh->error("netmap %s: %s", ifname.c_str(), strerror(errno));
error:
close(fd);
return -1;
}
memsize = req.nr_memsize;
if ((r = ioctl(fd, NIOCREGIF, &req))) {
errh->error("netmap register %s: %s", ifname.c_str(), strerror(errno));
goto error;
}
mem = (char *) mmap(0, memsize, PROT_WRITE | PROT_READ,
MAP_SHARED, fd, 0);
if (mem == MAP_FAILED) {
errh->error("netmap allocate %s: %s", ifname.c_str(), strerror(errno));
mem = 0;
goto error;
}
nifp = NETMAP_IF(mem, req.nr_offset);
ring_begin = 0;
ring_end = req.nr_numrings;
// XXX timestamp off
for (unsigned i = ring_begin; i != ring_end; ++i)
NETMAP_RXRING(nifp, i)->flags = NR_TIMESTAMP;
return fd;
}
#endif
int
FromDevice::initialize(ErrorHandler *errh)
{
......@@ -443,12 +394,8 @@ FromDevice::cleanup(CleanupStage stage)
if (stage >= CLEANUP_INITIALIZED && !_sniffer)
KernelFilter::device_filter(_ifname, false, ErrorHandler::default_handler());
#if FROMDEVICE_ALLOW_NETMAP
if (_fd >= 0 && _method == method_netmap) {
munmap(_netmap.mem, _netmap.memsize);
ioctl(_fd, NIOCUNREGIF, (struct nmreq *) 0);
close(_fd);
_netmap.mem = 0;
}
if (_fd >= 0 && _method == method_netmap)
_netmap.close(_fd);
#endif
#if FROMDEVICE_ALLOW_LINUX
if (_fd >= 0 && _method == method_linux) {
......@@ -469,11 +416,8 @@ FromDevice::cleanup(CleanupStage stage)
#if FROMDEVICE_ALLOW_PCAP || FROMDEVICE_ALLOW_NETMAP
void
FromDevice::emit_packet_data(const unsigned char *buf, int len, int fulllen,
const Timestamp &ts)
FromDevice::emit_packet(WritablePacket *p, int extra_len, const Timestamp &ts)
{
WritablePacket *p = Packet::make(_headroom, buf, len, 0);
// set packet type annotation
if (p->data()[0] & 1) {
if (EtherAddress::is_broadcast(p->data()))
......@@ -485,7 +429,7 @@ FromDevice::emit_packet_data(const unsigned char *buf, int len, int fulllen,
// set annotations
p->set_timestamp_anno(ts);
p->set_mac_header(p->data());
SET_EXTRA_LENGTH_ANNO(p, fulllen - len);
SET_EXTRA_LENGTH_ANNO(p, extra_len);
if (!_force_ip || fake_pcap_force_ip(p, _datalink))
output(0).push(p);
......@@ -503,8 +447,9 @@ FromDevice_get_packet(u_char* clientdata,
const u_char* data)
{
FromDevice *fd = (FromDevice *) clientdata;
fd->emit_packet_data(data, pkthdr->caplen, pkthdr->len,
Timestamp::make_usec(pkthdr->ts.tv_sec, pkthdr->ts.tv_usec));
WritablePacket *p = Packet::make(fd->_headroom, data, pkthdr->caplen, 0);
fd->emit_packet(p, pkthdr->len - pkthdr->caplen,
Timestamp::make_usec(pkthdr->ts.tv_sec, pkthdr->ts.tv_usec));
}
}
CLICK_DECLS
......@@ -517,18 +462,38 @@ FromDevice::netmap_dispatch()
int n = 0;
for (unsigned ri = _netmap.ring_begin; ri != _netmap.ring_end; ++ri) {
struct netmap_ring *ring = NETMAP_RXRING(_netmap.nifp, ri);
//click_chatter("netmap dispatch %s %u %u %u %u", _ifname.c_str(), ri, ring->cur, ring->reserved, ring->avail);
while (ring->reserved > 0 && NetmapInfo::refill(ring))
/* click_chatter("Refilled") */;
if (ring->avail == 0)
continue;
int nzcopy = (int) (ring->num_slots / 2) - (int) ring->reserved;
while (n != _burst && ring->avail > 0) {
unsigned i = ring->cur;
unsigned buf_idx = ring->slot[i].buf_idx;
unsigned cur = ring->cur;
unsigned buf_idx = ring->slot[cur].buf_idx;
if (buf_idx < 2)
break;
unsigned char *buf = (unsigned char *) NETMAP_BUF(ring, buf_idx);
emit_packet_data(buf, ring->slot[i].len, ring->slot[i].len, ring->ts);
ring->cur = NETMAP_RING_NEXT(ring, i);
ring->avail--;
n++;
WritablePacket *p;
if (nzcopy > 0) {
p = Packet::make(buf, ring->slot[cur].len, NetmapInfo::buffer_destructor);
++ring->reserved;
--nzcopy;
} else {
p = Packet::make(_headroom, buf, ring->slot[cur].len, 0);
unsigned res1idx = NETMAP_RING_FIRST_RESERVED(ring);
ring->slot[res1idx].buf_idx = buf_idx;
}
ring->cur = NETMAP_RING_NEXT(ring, ring->cur);
--ring->avail;
++n;
emit_packet(p, 0, ring->ts);
}
}
return n;
......@@ -671,5 +636,5 @@ FromDevice::add_handlers()
}
CLICK_ENDDECLS
ELEMENT_REQUIRES(userlevel FakePcap KernelFilter)
ELEMENT_REQUIRES(userlevel FakePcap KernelFilter NetmapInfo)
EXPORT_ELEMENT(FromDevice)
......@@ -21,9 +21,7 @@ void FromDevice_get_packet(u_char*, const struct pcap_pkthdr*, const u_char*);
#if HAVE_NET_NETMAP_H
# define FROMDEVICE_ALLOW_NETMAP 1
# include <net/if.h>
# include <net/netmap.h>
# include <net/netmap_user.h>
# include "elements/userlevel/netmapinfo.hh"
#endif
#if FROMDEVICE_ALLOW_NETMAP || FROMDEVICE_ALLOW_PCAP
......@@ -190,16 +188,7 @@ class FromDevice : public Element { public:
#endif
#if FROMDEVICE_ALLOW_NETMAP
struct netmap_type {
char *mem;
size_t memsize;
unsigned ring_begin;
unsigned ring_end;
struct netmap_if *nifp;
int open(const String &ifname, bool always_error,
ErrorHandler *errh);
};
const netmap_type *netmap() const { return _method == method_netmap ? &_netmap : 0; }
const NetmapInfo::ring *netmap() const { return _method == method_netmap ? &_netmap : 0; }
#endif
#if FROMDEVICE_ALLOW_NETMAP || FROMDEVICE_ALLOW_PCAP
......@@ -220,8 +209,7 @@ class FromDevice : public Element { public:
unsigned char *_linux_packetbuf;
#endif
#if FROMDEVICE_ALLOW_PCAP || FROMDEVICE_ALLOW_NETMAP
void emit_packet_data(const unsigned char *buf, int len, int fulllen,
const Timestamp &ts);
void emit_packet(WritablePacket *p, int extra_len, const Timestamp &ts);
#endif
#if FROMDEVICE_ALLOW_PCAP
pcap_t *_pcap;
......@@ -233,7 +221,7 @@ class FromDevice : public Element { public:
}
#endif
#if FROMDEVICE_ALLOW_NETMAP
netmap_type _netmap;
NetmapInfo::ring _netmap;
int netmap_dispatch();
#endif
......
// -*- mode: c++; c-basic-offset: 4 -*-
/*
* netmapinfo.{cc,hh} -- library for interfacing with netmap
* Eddie Kohler, Luigi Rizzo
*
* Copyright (c) 2012 Eddie Kohler
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the conditions
* listed in the Click LICENSE file. These conditions include: you must
* preserve this copyright notice, and you cannot mention the copyright
* holders in advertising related to the Software without their permission.
* The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
* notice is a summary of the Click LICENSE file; the license in that file is
* legally binding.
*/
#include <click/config.h>
#include <click/glue.hh>
#include "netmapinfo.hh"
#if HAVE_NET_NETMAP_H
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <click/sync.hh>
#include <unistd.h>
#include <fcntl.h>
CLICK_DECLS
static Spinlock netmap_memory_lock;
static void *netmap_memory = MAP_FAILED;
static size_t netmap_memory_size;
static uint32_t netmap_memory_users;
unsigned char *NetmapInfo::buffers;
int
NetmapInfo::ring::open(const String &ifname,
bool always_error, ErrorHandler *errh)
{
ErrorHandler *initial_errh = always_error ? errh : ErrorHandler::silent_handler();
int fd = ::open("/dev/netmap", O_RDWR);
if (fd < 0) {
initial_errh->error("/dev/netmap: %s", strerror(errno));
return -1;
}
struct nmreq req;
memset(&req, 0, sizeof(req));
strncpy(req.nr_name, ifname.c_str(), sizeof(req.nr_name));
req.nr_ringid = 0;
int r;
if ((r = ioctl(fd, NIOCGINFO, &req))) {
initial_errh->error("netmap %s: %s", ifname.c_str(), strerror(errno));
error:
close(fd);
return -1;
}
size_t memsize = req.nr_memsize;
if ((r = ioctl(fd, NIOCREGIF, &req))) {
errh->error("netmap register %s: %s", ifname.c_str(), strerror(errno));
goto error;
}
netmap_memory_lock.acquire();
if (netmap_memory == MAP_FAILED) {
netmap_memory_size = memsize;
netmap_memory = mmap(0, netmap_memory_size, PROT_WRITE | PROT_READ,
MAP_SHARED, fd, 0);
if (netmap_memory == MAP_FAILED) {
errh->error("netmap allocate %s: %s", ifname.c_str(), strerror(errno));
netmap_memory_lock.release();
goto error;
}
}
mem = (char *) netmap_memory;
++netmap_memory_users;
netmap_memory_lock.release();
nifp = NETMAP_IF(mem, req.nr_offset);
ring_begin = 0;
ring_end = req.nr_numrings;
// XXX timestamp off
for (unsigned i = ring_begin; i != ring_end; ++i)
NETMAP_RXRING(nifp, i)->flags = NR_TIMESTAMP;
return fd;
}
void
NetmapInfo::ring::close(int fd)
{
netmap_memory_lock.acquire();
if (--netmap_memory_users <= 0 && netmap_memory != MAP_FAILED) {
munmap(netmap_memory, netmap_memory_size);
netmap_memory = MAP_FAILED;
}
netmap_memory_lock.release();
ioctl(fd, NIOCUNREGIF, (struct nmreq *) 0);
::close(fd);
}
CLICK_ENDDECLS
#endif
ELEMENT_PROVIDES(NetmapInfo)
#ifndef CLICK_NETMAPINFO_HH
#define CLICK_NETMAPINFO_HH 1
#if HAVE_NET_NETMAP_H
#include <net/if.h>
#include <net/netmap.h>
#include <net/netmap_user.h>
#include <click/packet.hh>
#include <click/error.hh>
CLICK_DECLS
class NetmapInfo { public:
struct ring {
char *mem;
unsigned ring_begin;
unsigned ring_end;
struct netmap_if *nifp;
int open(const String &ifname,
bool always_error, ErrorHandler *errh);
void close(int fd);
};
static unsigned char *buffers; // XXX not thread safe
static bool is_netmap_buffer(Packet *p) {
return p->buffer_destructor() == buffer_destructor;
}
static void buffer_destructor(unsigned char *buf, size_t) {
*reinterpret_cast<unsigned char **>(buf) = buffers;
buffers = buf;
}
static bool refill(struct netmap_ring *ring) {
if (buffers) {
unsigned char *buf = buffers;
buffers = *reinterpret_cast<unsigned char **>(buffers);
unsigned res1idx = NETMAP_RING_FIRST_RESERVED(ring);
ring->slot[res1idx].buf_idx = NETMAP_BUF_IDX(ring, (char *) buf);
--ring->reserved;
return true;
} else
return false;
}
};
CLICK_ENDDECLS
#endif
#endif
......@@ -145,7 +145,7 @@ ToDevice::initialize(ErrorHandler *errh)
_timer.initialize(this);
FromDevice *fd = find_fromdevice();
if (_method == method_default) {
if (_method == method_default && fd) {
#if FROMDEVICE_ALLOW_NETMAP
if (fd->netmap())
_method = method_netmap;
......@@ -167,9 +167,10 @@ ToDevice::initialize(ErrorHandler *errh)
_netmap = *fd->netmap();
} else {
_fd = _netmap.open(_ifname, _method == method_netmap, errh);
if (_fd >= 0)
if (_fd >= 0) {
_my_fd = true;
else if (_method == method_netmap)
add_select(_fd, SELECT_READ); // NB NOT writable!
} else if (_method == method_netmap)
return -1;
}
if (_fd >= 0)
......@@ -264,9 +265,8 @@ ToDevice::cleanup(CleanupStage)
#endif
#if TODEVICE_ALLOW_NETMAP
if (_fd >= 0 && _my_fd && _method == method_netmap) {
munmap(_netmap.mem, _netmap.memsize);
ioctl(_fd, NIOCUNREGIF, (struct nmreq *) 0);
_netmap.mem = 0;
_netmap.close(_fd);
_fd = -1;
}
#endif
#if TODEVICE_ALLOW_LINUX || TODEVICE_ALLOW_DEVBPF || TODEVICE_ALLOW_PCAPFD || TODEVICE_ALLOW_NETMAP
......@@ -285,15 +285,19 @@ ToDevice::netmap_send_packet(Packet *p)
struct netmap_ring *ring = NETMAP_TXRING(_netmap.nifp, ri);
if (ring->avail == 0)
continue;
unsigned i = ring->cur;
unsigned buf_idx = ring->slot[i].buf_idx;
unsigned cur = ring->cur;
unsigned buf_idx = ring->slot[cur].buf_idx;
if (buf_idx < 2)
continue;
unsigned char *buf = (unsigned char *) NETMAP_BUF(ring, buf_idx);
memcpy(buf, p->data(), p->length());
ring->slot[i].len = p->length();
if (NetmapInfo::is_netmap_buffer(p)) {
ring->slot[cur].buf_idx = NETMAP_BUF_IDX(ring, (char *) p->buffer());
NetmapInfo::buffer_destructor(buf, 0);
} else
memcpy(buf, p->data(), p->length());
ring->slot[cur].len = p->length();
__asm__ volatile("" : : : "memory");
ring->cur = NETMAP_RING_NEXT(ring, i);
ring->cur = NETMAP_RING_NEXT(ring, cur);
ring->avail--;
return 0;
}
......
......@@ -83,10 +83,6 @@ extern "C" {
class ToDevice : public Element { public:
#if TODEVICE_ALLOW_NETMAP
typedef struct FromDevice::netmap_type netmap_type;
#endif
ToDevice();
~ToDevice();
......@@ -120,7 +116,7 @@ class ToDevice : public Element { public:
int _fd;
#endif
#if TODEVICE_ALLOW_NETMAP
netmap_type _netmap;
NetmapInfo::ring _netmap;
int netmap_send_packet(Packet *p);
#endif
enum { method_default, method_netmap, method_linux, method_pcap, method_devbpf, method_pcapfd };
......
......@@ -66,7 +66,7 @@ DEPCFLAGS = @DEPCFLAGS@