face: enable immediate mode for packet capture on EthernetFace.

Fixes #1511

Change-Id: I6551de8d650c5d14e27713258d958ac3c77a1649
diff --git a/daemon/face/ethernet-face.cpp b/daemon/face/ethernet-face.cpp
index fb278d3..f51a8ae 100644
--- a/daemon/face/ethernet-face.cpp
+++ b/daemon/face/ethernet-face.cpp
@@ -120,6 +120,14 @@
   if (!m_pcap)
     throw Error("pcap_create(): " + std::string(errbuf));
 
+#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
+  // Enable "immediate mode", effectively disabling any read buffering in the kernel.
+  // This corresponds to the BIOCIMMEDIATE ioctl on BSD-like systems (including OS X)
+  // where libpcap uses a BPF device. On Linux this forces libpcap not to use TPACKET_V3,
+  // even if the kernel supports it, thus preventing bug #1511.
+  pcap_set_immediate_mode(m_pcap, 1);
+#endif
+
   /// \todo Do not rely on promisc mode, see task #1278
   if (!m_destAddress.isBroadcast())
     pcap_set_promisc(m_pcap, 1);
diff --git a/daemon/face/ethernet-face.hpp b/daemon/face/ethernet-face.hpp
index 381493c..805c0e0 100644
--- a/daemon/face/ethernet-face.hpp
+++ b/daemon/face/ethernet-face.hpp
@@ -25,6 +25,7 @@
 #ifndef NFD_DAEMON_FACE_ETHERNET_FACE_HPP
 #define NFD_DAEMON_FACE_ETHERNET_FACE_HPP
 
+#include "config.hpp"
 #include "ethernet.hpp"
 #include "face.hpp"
 
diff --git a/wscript b/wscript
index b3f1480..7fb16ca 100644
--- a/wscript
+++ b/wscript
@@ -59,6 +59,8 @@
                'boost', 'dependency-checker', 'websocket',
                'doxygen', 'sphinx_build'])
 
+    conf.find_program('bash', var='BASH')
+
     conf.check_cfg(package='libndn-cxx', args=['--cflags', '--libs'],
                    uselib_store='NDN_CXX', mandatory=True)
 
@@ -72,7 +74,6 @@
         conf.env['WITH_OTHER_TESTS'] = 1
 
     conf.check_boost(lib=boost_libs)
-
     if conf.env.BOOST_VERSION_NUMBER < 104800:
         Logs.error("Minimum required boost version is 1.48.0")
         Logs.error("Please upgrade your distribution or install custom boost libraries" +
@@ -84,15 +85,17 @@
 
     conf.checkDependency(name='librt', lib='rt', mandatory=False)
     conf.checkDependency(name='libresolv', lib='resolv', mandatory=False)
+
     if not conf.options.without_libpcap:
         conf.checkDependency(name='libpcap', lib='pcap', mandatory=True,
                              errmsg='not found, but required for Ethernet face support. '
                                     'Specify --without-libpcap to disable Ethernet face support.')
+    if conf.env['HAVE_LIBPCAP']:
+        conf.check_cxx(function_name='pcap_set_immediate_mode', header_name='pcap/pcap.h',
+                       cxxflags='-Wno-error', use='LIBPCAP', mandatory=False)
 
     conf.load('coverage')
 
-    conf.find_program('bash', var='BASH')
-
     conf.define('DEFAULT_CONFIG_FILE', '%s/ndn/nfd.conf' % conf.env['SYSCONFDIR'])
 
     conf.write_config_header('config.hpp')