summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2015-12-07 22:52:58 -0800
committerSteve Kondik <steve@cyngn.com>2015-12-07 22:52:58 -0800
commit54455ee38fc75efa23fc7b8e57ca1c954380ecbe (patch)
treec1e80bcbc7c1c0bb7792e1ac5fb4b0aa690bb633
parent11ffa2451829c9bcb86f00c1cfff9f3be4b7064c (diff)
parent32961d08e3abe5b4e81178bb8c37dd4df231306d (diff)
downloadandroid_external_android-clat-stable/cm-13.0-ZNH2KB.tar.gz
android_external_android-clat-stable/cm-13.0-ZNH2KB.tar.bz2
android_external_android-clat-stable/cm-13.0-ZNH2KB.zip
Merge branch 'LA.BF64.1.2.2_rb4.9' of git://codeaurora.org/platform/external/android-clat into cm-13.0stable/cm-13.0-ZNH2KBstable/cm-13.0-ZNH2Kstable/cm-13.0-ZNH0E
Change-Id: I8ff75c228032b83459bfc1090488fb670c01734e
-rw-r--r--clatd.c5
-rw-r--r--clatd_test.cpp3
-rw-r--r--config.h2
-rw-r--r--ring.c12
-rw-r--r--ring.h3
-rw-r--r--translate.c9
-rw-r--r--translate.h4
-rw-r--r--tun.c67
-rw-r--r--tun.h1
9 files changed, 24 insertions, 82 deletions
diff --git a/clatd.c b/clatd.c
index ca21984..a454770 100644
--- a/clatd.c
+++ b/clatd.c
@@ -364,7 +364,7 @@ void read_packet(int read_fd, int write_fd, int to_ipv6) {
packet = (uint8_t *) (tun_header + 1);
readlen -= sizeof(*tun_header);
- translate_packet(write_fd, to_ipv6, packet, readlen);
+ translate_packet(write_fd, to_ipv6, packet, readlen, TP_CSUM_NONE);
}
/* function: event_loop
@@ -496,9 +496,6 @@ int main(int argc, char **argv) {
// run under a regular user
drop_root();
- //check HW features and disable checksum validation if already handled by hardware
- rx_checksum_offloaded = check_csum_offload(uplink_interface);
-
// we can create tun devices as non-root because we're in the VPN group.
tunnel.fd4 = tun_open();
if(tunnel.fd4 < 0) {
diff --git a/clatd_test.cpp b/clatd_test.cpp
index 7e218f0..6e374d2 100644
--- a/clatd_test.cpp
+++ b/clatd_test.cpp
@@ -30,6 +30,7 @@ extern "C" {
#include "translate.h"
#include "config.h"
#include "clatd.h"
+#include "ring.h"
}
// For convenience.
@@ -456,7 +457,7 @@ void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *
break;
}
- translate_packet(write_fd, (version == 4), original, original_len);
+ translate_packet(write_fd, (version == 4), original, original_len, TP_CSUM_NONE);
snprintf(foo, sizeof(foo), "%s: Invalid translated packet", msg);
if (version == 6) {
diff --git a/config.h b/config.h
index 82a91be..e31a81d 100644
--- a/config.h
+++ b/config.h
@@ -39,8 +39,6 @@ struct clat_config {
extern struct clat_config Global_Clatd_Config;
-extern int rx_checksum_offloaded;
-
int read_config(const char *file, const char *uplink_interface, const char *plat_prefix,
unsigned net_id);
void config_generate_local_ipv6_subnet(struct in6_addr *interface_ip);
diff --git a/ring.c b/ring.c
index 5e99fd5..17f8026 100644
--- a/ring.c
+++ b/ring.c
@@ -117,9 +117,19 @@ static struct tpacket2_hdr* ring_advance(struct packet_ring *ring) {
*/
void ring_read(struct packet_ring *ring, int write_fd, int to_ipv6) {
struct tpacket2_hdr *tp = ring->next;
+ uint16_t val = TP_CSUM_NONE;
if (tp->tp_status & TP_STATUS_USER) {
+ //We expect only GRO coalesced packets to have TP_STATUS_CSUMNOTREADY
+ //(ip_summed = CHECKSUM_PARTIAL) in this path. Note that these packets have already gone
+ //through checksum validation in GRO engine. CHECKSUM_PARTIAL is defined to be 3 while
+ //CHECKSUM_UNNECESSARY is defined to be 1.
+ //Kernel only checks for CHECKSUM_UNNECESSARY (TP_CSUM_UNNECESSARY) bit while processing a
+ //packet, so its ok to pass only this bit rather than the full ip_summed field.
+ if ((tp->tp_status & TP_STATUS_CSUMNOTREADY) || (tp->tp_status & TP_STATUS_CSUM_UNNECESSARY)) {
+ val = TP_CSUM_UNNECESSARY;
+ }
uint8_t *packet = ((uint8_t *) tp) + tp->tp_net;
- translate_packet(write_fd, to_ipv6, packet, tp->tp_len);
+ translate_packet(write_fd, to_ipv6, packet, tp->tp_len, val);
tp->tp_status = TP_STATUS_KERNEL;
tp = ring_advance(ring);
}
diff --git a/ring.h b/ring.h
index b9b8c11..9e517be 100644
--- a/ring.h
+++ b/ring.h
@@ -42,6 +42,9 @@ struct tun_data;
// results in 656 frames (1048576 bytes).
#define TP_NUM_BLOCKS 16
+#define TP_CSUM_NONE (0)
+#define TP_CSUM_UNNECESSARY (1)
+
struct packet_ring {
uint8_t *base;
struct tpacket2_hdr *next;
diff --git a/translate.c b/translate.c
index ddc9bac..bce9270 100644
--- a/translate.c
+++ b/translate.c
@@ -108,8 +108,8 @@ struct in6_addr ipv4_addr_to_ipv6_addr(uint32_t addr4) {
* tun_header - tunnel header, already allocated
* proto - ethernet protocol id: ETH_P_IP(ipv4) or ETH_P_IPV6(ipv6)
*/
-void fill_tun_header(struct tun_pi *tun_header, uint16_t proto) {
- tun_header->flags = 0;
+void fill_tun_header(struct tun_pi *tun_header, uint16_t proto, uint16_t skip_csum) {
+ tun_header->flags = htons(skip_csum);
tun_header->proto = htons(proto);
}
@@ -491,8 +491,9 @@ void send_rawv6(int fd, clat_packet out, int iov_len) {
* to_ipv6 - true if translating to ipv6, false if translating to ipv4
* packet - packet
* packetsize - size of packet
+ * skip_csum - true if kernel has to skip checksum validation, false if it has to validate checksum.
*/
-void translate_packet(int fd, int to_ipv6, const uint8_t *packet, size_t packetsize) {
+void translate_packet(int fd, int to_ipv6, const uint8_t *packet, size_t packetsize, uint16_t skip_csum) {
int iov_len = 0;
// Allocate buffers for all packet headers.
@@ -524,7 +525,7 @@ void translate_packet(int fd, int to_ipv6, const uint8_t *packet, size_t packets
} else {
iov_len = ipv6_packet(out, CLAT_POS_IPHDR, packet, packetsize);
if (iov_len > 0) {
- fill_tun_header(&tun_targ, ETH_P_IP);
+ fill_tun_header(&tun_targ, ETH_P_IP, skip_csum);
out[CLAT_POS_TUNHDR].iov_len = sizeof(tun_targ);
send_tun(fd, out, iov_len);
}
diff --git a/translate.h b/translate.h
index aa8b736..3c249eb 100644
--- a/translate.h
+++ b/translate.h
@@ -42,14 +42,14 @@ uint16_t packet_length(clat_packet packet, clat_packet_index pos);
int is_in_plat_subnet(const struct in6_addr *addr6);
// Functions to create tun, IPv4, and IPv6 headers.
-void fill_tun_header(struct tun_pi *tun_header, uint16_t proto);
+void fill_tun_header(struct tun_pi *tun_header, uint16_t proto, uint16_t skip_csum);
void fill_ip_header(struct iphdr *ip_targ, uint16_t payload_len, uint8_t protocol,
const struct ip6_hdr *old_header);
void fill_ip6_header(struct ip6_hdr *ip6, uint16_t payload_len, uint8_t protocol,
const struct iphdr *old_header);
// Translate and send packets.
-void translate_packet(int fd, int to_ipv6, const uint8_t *packet, size_t packetsize);
+void translate_packet(int fd, int to_ipv6, const uint8_t *packet, size_t packetsize, uint16_t skip_csum);
// Translate IPv4 and IPv6 packets.
int ipv4_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, size_t len);
diff --git a/tun.c b/tun.c
index 1b48a4f..49f0ea7 100644
--- a/tun.c
+++ b/tun.c
@@ -22,14 +22,10 @@
#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
*/
@@ -65,11 +61,6 @@ int tun_alloc(char *dev, int fd) {
return err;
}
strcpy(dev, ifr.ifr_name);
-
- if (rx_checksum_offloaded) {
- ioctl(fd, TUNSETNOCSUM, 1);
- }
-
return 0;
}
@@ -96,61 +87,3 @@ 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) {
- if (!dev){
- return 0;
- }
-
- if(get_ethtool_feature_val(dev, ETHTOOL_GGRO) &&
- get_ethtool_feature_val(dev, ETHTOOL_GRXCSUM)) {
- return 1;
- }
-
- return 0;
-}
diff --git a/tun.h b/tun.h
index f1c41bf..bcdd10e 100644
--- a/tun.h
+++ b/tun.h
@@ -33,6 +33,5 @@ int tun_open();
int tun_alloc(char *dev, int fd);
int send_tun(int fd, clat_packet out, int iov_len);
int set_nonblocking(int fd);
-int check_csum_offload(char *dev);
#endif