]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
offloading: Linux ethtool offloading support
authorVictor Julien <victor@inliniac.net>
Mon, 20 Jun 2016 21:00:38 +0000 (23:00 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 22 Sep 2016 11:36:27 +0000 (13:36 +0200)
src/util-ioctl.c

index 5eb7b408c1f8803fdee2004f572b132a1099da69..ae1bded7e58f1dcee90df222a8f9731b1860f341 100644 (file)
@@ -19,6 +19,7 @@
  * \file
  *
  * \author Eric Leblond <eric@regit.org>
+ * \author Victor Julien <victor@inliniac.net>
  */
 
 #include "suricata-common.h"
@@ -292,6 +293,33 @@ static int GetEthtoolValue(const char *dev, int cmd, uint32_t *value)
     return 0;
 }
 
+static int SetEthtoolValue(const char *dev, int cmd, uint32_t value)
+{
+    struct ifreq ifr;
+    int fd;
+    struct ethtool_value ethv;
+
+    fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (fd == -1) {
+        return -1;
+    }
+    (void)strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
+
+    ethv.cmd = cmd;
+    ethv.data = value;
+    ifr.ifr_data = (void *) &ethv;
+    if (ioctl(fd, SIOCETHTOOL, (char *)&ifr) < 0) {
+        SCLogWarning(SC_ERR_SYSCALL,
+                  "Failure when trying to get feature via ioctl for '%s': %s (%d)",
+                  dev, strerror(errno), errno);
+        close(fd);
+        return -1;
+    }
+
+    close(fd);
+    return 0;
+}
+
 static int GetIfaceOffloadingLinux(const char *dev, int csum, int other)
 {
     int ret = 0;
@@ -372,6 +400,62 @@ static int GetIfaceOffloadingLinux(const char *dev, int csum, int other)
     return ret;
 }
 
+static int DisableIfaceOffloadingLinux(const char *dev, int csum, int other)
+{
+    int ret = 0;
+    uint32_t value = 0;
+
+    if (csum) {
+#ifdef ETHTOOL_GRXCSUM
+        if (GetEthtoolValue(dev, ETHTOOL_GRXCSUM, &value) == 0 && value != 0) {
+            SCLogInfo("%s: disabling rxcsum offloading", dev);
+            SetEthtoolValue(dev, ETHTOOL_SRXCSUM, 0);
+        }
+#endif
+#ifdef ETHTOOL_GTXCSUM
+        if (GetEthtoolValue(dev, ETHTOOL_GTXCSUM, &value) == 0 && value != 0) {
+            SCLogInfo("%s: disabling txcsum offloading", dev);
+            SetEthtoolValue(dev, ETHTOOL_STXCSUM, 0);
+        }
+#endif
+    }
+    if (other) {
+#ifdef ETHTOOL_GGRO
+        if (GetEthtoolValue(dev, ETHTOOL_GGRO, &value) == 0 && value != 0) {
+            SCLogInfo("%s: disabling gro offloading", dev);
+            SetEthtoolValue(dev, ETHTOOL_SGRO, 0);
+        }
+#endif
+#ifdef ETHTOOL_GTSO
+        if (GetEthtoolValue(dev, ETHTOOL_GTSO, &value) == 0 && value != 0) {
+            SCLogInfo("%s: disabling tso offloading", dev);
+            SetEthtoolValue(dev, ETHTOOL_STSO, 0);
+        }
+#endif
+#ifdef ETHTOOL_GGSO
+        if (GetEthtoolValue(dev, ETHTOOL_GGSO, &value) == 0 && value != 0) {
+            SCLogInfo("%s: disabling gso offloading", dev);
+            SetEthtoolValue(dev, ETHTOOL_SGSO, 0);
+        }
+#endif
+#ifdef ETHTOOL_GSG
+        if (GetEthtoolValue(dev, ETHTOOL_GSG, &value) == 0 && value != 0) {
+            SCLogInfo("%s: disabling sg offloading", dev);
+            SetEthtoolValue(dev, ETHTOOL_SSG, 0);
+        }
+#endif
+#ifdef ETHTOOL_GFLAGS
+        if (GetEthtoolValue(dev, ETHTOOL_GFLAGS, &value) == 0) {
+            if (value & ETH_FLAG_LRO) {
+                SCLogInfo("%s: disabling lro offloading", dev);
+                SetEthtoolValue(dev, ETHTOOL_SFLAGS, value & ~ETH_FLAG_LRO);
+            }
+        }
+#endif
+    }
+    return ret;
+}
+
 #endif /* defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL */
 
 #ifdef SIOCGIFCAP
@@ -472,7 +556,9 @@ int GetIfaceOffloading(const char *dev, int csum, int other)
 
 int DisableIfaceOffloading(const char *dev, int csum, int other)
 {
-#if defined SIOCSIFCAP
+#if defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL
+    return DisableIfaceOffloadingLinux(dev, csum, other);
+#elif defined SIOCSIFCAP
     return DisableIfaceOffloadingBSD(dev);
 #else
     return 0;