diff options
author | Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> | 2015-10-10 19:41:32 -0600 |
---|---|---|
committer | Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> | 2015-10-12 10:56:09 -0600 |
commit | 7efed4e30259da5348c4a7c2c77a0d0d4b13834d (patch) | |
tree | 333d4e6a4a5f0d87f0a2110e24664cffcb9d5a03 /tun.c | |
parent | 35b34f09ab343ae8a75fcb9ff3cea180cf58992a (diff) | |
download | android_external_android-clat-7efed4e30259da5348c4a7c2c77a0d0d4b13834d.tar.gz android_external_android-clat-7efed4e30259da5348c4a7c2c77a0d0d4b13834d.tar.bz2 android_external_android-clat-7efed4e30259da5348c4a7c2c77a0d0d4b13834d.zip |
clatd: Use the TUN_NOCHECKSUM flag for the tun device
This is needed to handle cases when the packet socket receives
a GRO coalesced packet which will not have a valid TCP checksum.
TUN_NOCHECKSUM is used only when the checksum has already been
verified prior to this and GRO is being used.
Change-Id: I1409967523152bb7620b4881526e78e8c222cc72
Diffstat (limited to 'tun.c')
-rw-r--r-- | tun.c | 71 |
1 files changed, 71 insertions, 0 deletions
@@ -22,10 +22,14 @@ #include <linux/if.h> #include <linux/if_tun.h> #include <sys/ioctl.h> +#include <linux/ethtool.h> #include <sys/uio.h> +#include "config.h" #include "clatd.h" +int rx_checksum_offloaded = 0; + /* function: tun_open * tries to open the tunnel device */ @@ -61,6 +65,11 @@ int tun_alloc(char *dev, int fd) { return err; } strcpy(dev, ifr.ifr_name); + + if (rx_checksum_offloaded) { + ioctl(fd, TUNSETNOCSUM, 1); + } + return 0; } @@ -87,3 +96,65 @@ int set_nonblocking(int fd) { int send_tun(int fd, clat_packet out, int iov_len) { return writev(fd, out, iov_len); } + +/* function: get_ethtool_feature_val + * gets if a particular ethtool feature is enabled + * dev - the device name to query the feature on + * cmd - the feature to query + * returns: 1 if feature is enabled, 0 if disabled + */ +int get_ethtool_feature_val(char *dev, int cmd) { + int fd; + struct ifreq ifr; + struct ethtool_value eval; + + if (!dev){ + return 0; + } + + if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { + return 0; + } + + memset(&ifr, 0, sizeof(ifr)); + memset(&eval, 0, sizeof(eval)); + strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); + eval.cmd = cmd; + eval.data = 0; + ifr.ifr_data = (caddr_t)&eval; + if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) { + close(fd); + return 0; + } + + close(fd); + + if (!eval.data) { + return 0; + } + + return 1; +} + +/* function: check_csum_offload + * checks if GRO and RXCSUM are enabled on the device + * dev - the device name to query on + * returns: 1 if checksum is offloaded, 0 if checksum needs + * to be validated in network stack. + */ +int check_csum_offload(char *dev) { + int fd; + struct ifreq ifr; + struct ethtool_value eval; + + if (!dev){ + return 0; + } + + if(get_ethtool_feature_val(dev, ETHTOOL_GGRO) && + get_ethtool_feature_val(dev, ETHTOOL_GRXCSUM)) { + return 1; + } + + return 0; +} |