* \file
*
* \author Eric Leblond <eric@regit.org>
+ * \author Victor Julien <victor@inliniac.net>
*/
#include "suricata-common.h"
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 *) ðv;
+ 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;
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
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;