Skip to content

Commit

Permalink
util-ioctl: add GRO/LRO detection capabilities
Browse files Browse the repository at this point in the history
This patch adds a new function GetIfaceOffloading which return 0
if LRO and GRO are not set on a interface and 1 if not the case.
  • Loading branch information
regit committed Nov 25, 2013
1 parent 008ed41 commit fcc8759
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
1 change: 1 addition & 0 deletions configure.ac
Expand Up @@ -136,6 +136,7 @@
AC_CHECK_HEADERS([syslog.h sys/prctl.h sys/socket.h sys/stat.h sys/syscall.h])
AC_CHECK_HEADERS([sys/time.h time.h unistd.h])
AC_CHECK_HEADERS([sys/ioctl.h linux/if_ether.h linux/if_packet.h linux/filter.h])
AC_CHECK_HEADERS([linux/ethtool.h linux/sockios.h])

AC_CHECK_HEADERS([sys/socket.h net/if.h sys/mman.h linux/if_arp.h], [], [],
[[#ifdef HAVE_SYS_SOCKET_H
Expand Down
84 changes: 84 additions & 0 deletions src/util-ioctl.c
Expand Up @@ -28,6 +28,15 @@
#include <sys/ioctl.h>
#endif

#ifdef HAVE_LINUX_ETHTOOL_H
#include <linux/ethtool.h>
#ifdef HAVE_LINUX_SOCKIOS_H
#include <linux/sockios.h>
#else
#error "ethtool.h present but sockios.h is missing"
#endif /* HAVE_LINUX_SOCKIOS_H */
#endif /* HAVE_LINUX_ETHTOOL_H */

#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
Expand Down Expand Up @@ -119,3 +128,78 @@ int GetIfaceMaxPacketSize(char *pcap_dev)
}
return ll_header + mtu;
}

/**
* \brief output offloading status of the link
*
* Test interface for GRO and LRO features. If one of them is
* activated then suricata mays received packets merge at reception.
* The result is oversized packets and this may cause some serious
* problem in some capture mode where the size of the packet is
* limited (AF_PACKET in V2 more for example).
*
* ETHTOOL_GGRO ETH_FLAG_LRO
*
* \param Name of link
* \retval -1 in case of error, 0 if none, 1 if some
*/
int GetIfaceOffloading(char *pcap_dev)
{
#ifdef ETHTOOL_GGRO
struct ifreq ifr;
int fd;
struct ethtool_value ethv;
int ret = 0;

fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) {
return -1;
}
(void)strlcpy(ifr.ifr_name, pcap_dev, sizeof(ifr.ifr_name));

/* First get GRO */
ethv.cmd = ETHTOOL_GGRO;
ifr.ifr_data = (void *) &ethv;
if (ioctl(fd, SIOCETHTOOL, (char *)&ifr) < 0) {
SCLogWarning(SC_ERR_SYSCALL,
"Failure when trying to get feature via ioctl: %s (%d)",
strerror(errno), errno);
close(fd);
return -1;
} else {
if (ethv.data) {
SCLogInfo("Generic Receive Offload is set on %s", pcap_dev);
ret = 1;
} else {
SCLogInfo("Generic Receive Offload is unset on %s", pcap_dev);
}
}

/* Then get LRO which is set in a flag */
ethv.data = 0;
ethv.cmd = ETHTOOL_GFLAGS;
ifr.ifr_data = (void *) &ethv;
if (ioctl(fd, SIOCETHTOOL, (char *)&ifr) < 0) {
SCLogWarning(SC_ERR_SYSCALL,
"Failure when trying to get feature via ioctl: %s (%d)",
strerror(errno), errno);
close(fd);
return -1;
} else {
if (ethv.data & ETH_FLAG_LRO) {
SCLogInfo("Large Receive Offload is set on %s", pcap_dev);
ret = 1;
} else {
SCLogInfo("Large Receive Offload is unset on %s", pcap_dev);
}
}

close(fd);

return ret;
#else
/* ioctl is not defined, let's pretend returning 0 is ok */
return 0;
#endif
}

1 change: 1 addition & 0 deletions src/util-ioctl.h
Expand Up @@ -23,3 +23,4 @@

int GetIfaceMTU(char *pcap_dev);
int GetIfaceMaxPacketSize(char *pcap_dev);
int GetIfaceOffloading(char *pcap_dev);

0 comments on commit fcc8759

Please sign in to comment.