#endif /* HAVE_NETMAP */
+#include "util-ioctl.h"
+
extern intmax_t max_pending_packets;
#ifndef HAVE_NETMAP
static NetmapDeviceList netmap_devlist = TAILQ_HEAD_INITIALIZER(netmap_devlist);
static SCMutex netmap_devlist_lock = SCMUTEX_INITIALIZER;
-/**
- * \brief Get interface flags.
- * \param fd Network susbystem file descritor.
- * \param ifname Inteface name.
- * \return Interface flags or -1 on error
- */
-static int NetmapGetIfaceFlags(int fd, const char *ifname)
-{
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
- SCLogError(SC_ERR_NETMAP_CREATE,
- "Unable to get flags for iface \"%s\": %s",
- ifname, strerror(errno));
- return -1;
- }
-
-#ifdef OS_FREEBSD
- int flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
- return flags;
-#else
- return ifr.ifr_flags;
-#endif
-}
-
-#ifdef SIOCGIFCAP
-static int NetmapGetIfaceCaps(int fd, const char *ifname)
-{
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-
- if (ioctl(fd, SIOCGIFCAP, &ifr) == -1) {
- SCLogError(SC_ERR_NETMAP_CREATE,
- "Unable to get caps for iface \"%s\": %s",
- ifname, strerror(errno));
- return -1;
- }
-
- return ifr.ifr_curcap;
-}
-#endif
-
-static void NetmapCheckOffloading(int fd, const char *ifname)
-{
-#ifdef SIOCGIFCAP
- int if_caps = NetmapGetIfaceCaps(fd, ifname);
- if (if_caps == -1) {
- return;
- }
- SCLogDebug("if_caps %X", if_caps);
-
- if (if_caps & IFCAP_RXCSUM) {
- SCLogWarning(SC_ERR_NETMAP_CREATE,
- "Using NETMAP with RXCSUM activated can lead to capture "
- "problems: ifconfig %s -rxcsum", ifname);
- }
- if (if_caps & (IFCAP_TSO|IFCAP_TOE|IFCAP_LRO)) {
- SCLogWarning(SC_ERR_NETMAP_CREATE,
- "Using NETMAP with TSO, TOE or LRO activated can lead to "
- "capture problems: ifconfig %s -tso -toe -lro", ifname);
- }
-#else
- if (GetIfaceOffloading(ifname) == 1) {
- SCLogWarning(SC_ERR_NETMAP_CREATE,
- "Using NETMAP with GRO or LRO activated can lead to "
- "capture problems: "
- "ethtool -K %s rx off sg off gro off gso off tso off",
- ifname);
- }
-#endif
-}
-
-/**
- * \brief Set interface flags.
- * \param fd Network susbystem file descritor.
- * \param ifname Inteface name.
- * \param flags Flags to set.
- * \return Zero on success.
- */
-static int NetmapSetIfaceFlags(int fd, const char *ifname, int flags)
-{
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-#ifdef OS_FREEBSD
- ifr.ifr_flags = flags & 0xffff;
- ifr.ifr_flagshigh = flags >> 16;
-#else
- ifr.ifr_flags = flags;
-#endif
-
- if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) {
- SCLogError(SC_ERR_NETMAP_CREATE,
- "Unable to set flags for iface \"%s\": %s",
- ifname, strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
/** \brief get RSS RX-queue count
* \retval rx_rings RSS RX queue count or 1 on error
*/
}
}
+ (void)GetIfaceOffloading(ifname);
+
/* not found, create new record */
pdev = SCMalloc(sizeof(*pdev));
if (unlikely(pdev == NULL)) {
}
/* check interface is up */
- int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (if_fd < 0) {
- SCLogError(SC_ERR_NETMAP_CREATE,
- "Couldn't create control socket for '%s' interface",
- ifname);
- goto error_fd;
- }
- int if_flags = NetmapGetIfaceFlags(if_fd, ifname);
+ int if_flags = GetIfaceFlags(ifname);
if (if_flags == -1) {
if (verbose) {
SCLogError(SC_ERR_NETMAP_CREATE,
"Can not access to interface '%s'",
ifname);
}
- close(if_fd);
goto error_fd;
}
if ((if_flags & IFF_UP) == 0) {
- if (verbose) {
- SCLogError(SC_ERR_NETMAP_CREATE, "Interface '%s' is down", ifname);
- }
- close(if_fd);
+ SCLogWarning(SC_ERR_NETMAP_CREATE, "Interface '%s' is down", ifname);
goto error_fd;
}
/* if needed, try to set iface in promisc mode */
if (promisc && (if_flags & (IFF_PROMISC|IFF_PPROMISC)) == 0) {
if_flags |= IFF_PPROMISC;
- NetmapSetIfaceFlags(if_fd, ifname, if_flags);
+ SetIfaceFlags(ifname, if_flags);
}
- NetmapCheckOffloading(if_fd, ifname);
- close(if_fd);
-
/* query netmap info */
memset(&nm_req, 0, sizeof(nm_req));
strlcpy(nm_req.nr_name, ifname, sizeof(nm_req.nr_name));
SCMutexUnlock(&pcap_bpf_compile_lock);
}
- /* Making it conditional to Linux even if GetIfaceOffloading return 0
- * for non Linux. */
-#ifdef HAVE_LINUX_ETHTOOL_H
- if (GetIfaceOffloading(pcapconfig->iface) == 1) {
- SCLogWarning(SC_ERR_PCAP_CREATE,
- "Using Pcap capture with GRO or LRO activated can lead to "
- "capture problems.");
- }
-#endif /* HAVE_LINUX_ETHTOOL_H */
+ (void)GetIfaceOffloading(pcapconfig->iface);
ptv->datalink = pcap_datalink(ptv->pcap_handle);
CASE_CODE (SC_ERR_NETFLOW_LOG_GENERIC);
CASE_CODE (SC_ERR_SMTP_LOG_GENERIC);
CASE_CODE (SC_ERR_SSH_LOG_GENERIC);
+ CASE_CODE (SC_ERR_NIC_OFFLOADING);
}
return "UNKNOWN_ERROR";
SC_ERR_NETFLOW_LOG_GENERIC,
SC_ERR_SMTP_LOG_GENERIC,
SC_ERR_SSH_LOG_GENERIC,
+ SC_ERR_NIC_OFFLOADING,
} SCError;
const char *SCErrorToString(SCError);
return ll_header + mtu;
}
+#ifdef SIOCGIFFLAGS
+/**
+ * \brief Get interface flags.
+ * \param ifname Inteface name.
+ * \return Interface flags or -1 on error
+ */
+int GetIfaceFlags(const char *ifname)
+{
+ struct ifreq ifr;
+
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
+ SCLogError(SC_ERR_SYSCALL,
+ "Unable to get flags for iface \"%s\": %s",
+ ifname, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+#ifdef OS_FREEBSD
+ int flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
+ return flags;
+#else
+ return ifr.ifr_flags;
+#endif
+}
+#endif
+
+#ifdef SIOCSIFFLAGS
+/**
+ * \brief Set interface flags.
+ * \param ifname Inteface name.
+ * \param flags Flags to set.
+ * \return Zero on success.
+ */
+int SetIfaceFlags(const char *ifname, int flags)
+{
+ struct ifreq ifr;
+
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+#ifdef OS_FREEBSD
+ ifr.ifr_flags = flags & 0xffff;
+ ifr.ifr_flagshigh = flags >> 16;
+#else
+ ifr.ifr_flags = flags;
+#endif
+
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) {
+ SCLogError(SC_ERR_SYSCALL,
+ "Unable to set flags for iface \"%s\": %s",
+ ifname, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+#endif /* SIOCGIFFLAGS */
+
+#ifdef SIOCGIFCAP
+int GetIfaceCaps(const char *ifname)
+{
+ struct ifreq ifr;
+
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+ if (ioctl(fd, SIOCGIFCAP, &ifr) == -1) {
+ SCLogError(SC_ERR_SYSCALL,
+ "Unable to get caps for iface \"%s\": %s",
+ ifname, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return ifr.ifr_curcap;
+}
+#endif
+
#if defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL
static int GetEthtoolValue(const char *dev, int cmd, uint32_t *value)
{
}
}
#endif
- SCLogInfo("NIC offloading on %s: SG: %s, GRO: %s, LRO: %s, "
- "TSO: %s, GSO: %s", dev, sg, gro, lro, tso, gso);
+ if (ret == 0) {
+ SCLogInfo("NIC offloading on %s: SG: %s, GRO: %s, LRO: %s, "
+ "TSO: %s, GSO: %s", dev, sg, gro, lro, tso, gso);
+ } else {
+ SCLogWarning(SC_ERR_NIC_OFFLOADING, "NIC offloading on %s: SG: %s, "
+ " GRO: %s, LRO: %s, TSO: %s, GSO: %s: "
+ "ethtool -K %s sg off gro off lro off tso off gso off",
+ dev, sg, gro, lro, tso, gso, dev);
+ }
return ret;
}
#endif /* defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL */
+#ifdef SIOCGIFCAP
+static int GetIfaceOffloadingBSD(const char *ifname)
+{
+ int ret = 0;
+ int if_caps = GetIfaceCaps(ifname);
+ if (if_caps == -1) {
+ return -1;
+ }
+ SCLogDebug("if_caps %X", if_caps);
+
+ if (if_caps & IFCAP_RXCSUM) {
+ SCLogWarning(SC_ERR_NIC_OFFLOADING,
+ "Using %s with RXCSUM activated can lead to capture "
+ "problems: ifconfig %s -rxcsum", ifname, ifname);
+ ret = 1;
+ }
+ if (if_caps & (IFCAP_TSO|IFCAP_TOE|IFCAP_LRO)) {
+ SCLogWarning(SC_ERR_NIC_OFFLOADING,
+ "Using %s with TSO, TOE or LRO activated can lead to "
+ "capture problems: ifconfig %s -tso -toe -lro",
+ ifname, ifname);
+ ret = 1;
+ }
+ return ret;
+}
+#endif
+
/**
* \brief output offloading status of the link
*
{
#if defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL
return GetIfaceOffloadingLinux(dev);
-#endif
+#elif defined SIOCGIFCAP
+ return GetIfaceOffloadingBSD(dev);
+#else
return 0;
+#endif
}
int GetIfaceRSSQueuesNum(const char *pcap_dev)
int GetIfaceMaxPacketSize(const char *pcap_dev);
int GetIfaceOffloading(const char *pcap_dev);
int GetIfaceRSSQueuesNum(const char *pcap_dev);
+#ifdef SIOCGIFFLAGS
+int GetIfaceFlags(const char *ifname);
+#endif
+#ifdef SIOCSIFFLAGS
+int SetIfaceFlags(const char *ifname, int flags);
+#endif
+#ifdef SIOCGIFCAP
+int GetIfaceCaps(const char *ifname);
+#endif