Merge tag 'android-11.0.0_r48' into int/11/fp3

Android 11.0.0 Release 48 (RD2A.211001.002)

* tag 'android-11.0.0_r48':

Change-Id: I3acadcfe350f3cb94358319a2a5c8ee3e0a83881
diff --git a/clatd.c b/clatd.c
index 422cded..84b75dc 100644
--- a/clatd.c
+++ b/clatd.c
@@ -382,7 +382,7 @@
 
   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
diff --git a/clatd.h b/clatd.h
index a3f9326..512d424 100644
--- a/clatd.h
+++ b/clatd.h
@@ -24,7 +24,8 @@
 struct tun_data;
 
 #define MAXMTU 1500
-#define PACKETLEN (MAXMTU + sizeof(struct tun_pi))
+#define MAXMRU 65536
+#define PACKETLEN (MAXMRU + sizeof(struct tun_pi))
 #define CLATD_VERSION "1.4"
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
diff --git a/clatd_test.cpp b/clatd_test.cpp
index c16a4dd..bd2fb9f 100644
--- a/clatd_test.cpp
+++ b/clatd_test.cpp
@@ -461,7 +461,7 @@
       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) {
@@ -489,13 +489,15 @@
   }
 }
 
-void check_translated_packet(const uint8_t *original, size_t original_len, const uint8_t *expected,
-                             size_t expected_len, const char *msg) {
-  uint8_t translated[MAXMTU];
+void check_translated_packet(const uint8_t *original, size_t original_len,
+                             const uint8_t *expected, size_t expected_len, const char *msg) {
+  uint8_t *translated = new uint8_t[MAXMRU];
+  ASSERT_NE(translated, nullptr) << msg << ": Unable to allocate memory\n";
   size_t translated_len = sizeof(translated);
   do_translate_packet(original, original_len, translated, &translated_len, msg);
   EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
   check_data_matches(expected, translated, translated_len, msg);
+  delete [] translated;
 }
 
 void check_fragment_translation(const uint8_t *original[], const size_t original_lengths[],
@@ -510,15 +512,20 @@
   }
 
   // Sanity check that reassembling the original and translated fragments produces valid packets.
-  uint8_t reassembled[MAXMTU];
+  uint8_t *reassembled = new uint8_t[MAXMRU];
+  ASSERT_NE(reassembled, nullptr) << msg << ": Unable to allocate memory\n";
   size_t reassembled_len = sizeof(reassembled);
   reassemble_packet(original, original_lengths, numfragments, reassembled, &reassembled_len, msg);
   check_packet(reassembled, reassembled_len, msg);
 
-  uint8_t translated[MAXMTU];
+  uint8_t *translated = new uint8_t[MAXMRU];
+  ASSERT_NE(translated, nullptr) << msg << ": Unable to allocate memory\n";
   size_t translated_len = sizeof(translated);
   do_translate_packet(reassembled, reassembled_len, translated, &translated_len, msg);
   check_packet(translated, translated_len, msg);
+
+  delete [] translated;
+  delete [] reassembled;
 }
 
 int get_transport_checksum(const uint8_t *packet) {
@@ -679,7 +686,8 @@
   check_packet(ipv6_ping, sizeof(ipv6_ping), "IPv6 ping sanity check");
 
   // Sanity checks reassemble_packet.
-  uint8_t reassembled[MAXMTU];
+  uint8_t *reassembled = new uint8_t[MAXMRU];
+  ASSERT_NE(reassembled, nullptr) << ": Unable to allocate memory\n";
   size_t total_length = sizeof(reassembled);
   reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), reassembled,
                     &total_length, "Reassembly sanity check");
@@ -695,6 +703,7 @@
   ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *)reassembled, total_length))
     << "Sanity check: reassembled packet is a fragment!\n";
   check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
+  delete [] reassembled;
 }
 
 TEST_F(ClatdTest, PseudoChecksum) {
@@ -834,7 +843,8 @@
 
 void check_translate_checksum_neutral(const uint8_t *original, size_t original_len,
                                       size_t expected_len, const char *msg) {
-  uint8_t translated[MAXMTU];
+  uint8_t *translated = new uint8_t[MAXMRU];
+  ASSERT_NE(translated, nullptr) << msg << ": Unable to allocate memory\n";
   size_t translated_len = sizeof(translated);
   do_translate_packet(original, original_len, translated, &translated_len, msg);
   EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
@@ -845,6 +855,7 @@
   ASSERT_NE(-1, translated_check);
   ASSERT_EQ(original_check, translated_check)
     << "Not checksum neutral: original and translated checksums differ\n";
+  delete [] translated;
 }
 
 TEST_F(ClatdTest, TranslateChecksumNeutral) {
diff --git a/ring.c b/ring.c
index 7626c6d..b4b106e 100644
--- a/ring.c
+++ b/ring.c
@@ -29,6 +29,8 @@
 #include "ring.h"
 #include "translate.h"
 
+#define TP_STATUS_CSUM_UNNECESSARY (1 << 7)
+
 int ring_create(struct tun_data *tunnel) {
   // Will eventually be bound to htons(ETH_P_IPV6) protocol,
   // but only after appropriate bpf filter is attached.
@@ -119,9 +121,19 @@
  */
 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) {
-    uint8_t *packet = ((uint8_t *)tp) + tp->tp_net;
-    translate_packet(write_fd, to_ipv6, packet, tp->tp_len);
+    //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, val);
     tp->tp_status = TP_STATUS_KERNEL;
     tp            = ring_advance(ring);
   }
diff --git a/ring.h b/ring.h
index b9b8c11..20d2f98 100644
--- a/ring.h
+++ b/ring.h
@@ -27,10 +27,10 @@
 
 // Frame size. Must be a multiple of TPACKET_ALIGNMENT (=16)
 // Why the 16? http://lxr.free-electrons.com/source/net/packet/af_packet.c?v=3.4#L1764
-#define TP_FRAME_SIZE (TPACKET_ALIGN(MAXMTU) + TPACKET_ALIGN(TPACKET2_HDRLEN) + 16)
+#define TP_FRAME_SIZE (TPACKET_ALIGN(MAXMRU) + TPACKET_ALIGN(TPACKET2_HDRLEN) + 16)
 
 // Block size. Must be a multiple of the page size, and a power of two for efficient memory use.
-#define TP_BLOCK_SIZE 65536
+#define TP_BLOCK_SIZE 2686976
 
 // In order to save memory, our frames are not an exact divider of the block size. Therefore, the
 // mmaped region will have gaps corresponding to the empty space at the end of each block.
@@ -42,6 +42,9 @@
 // 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 728acc3..9c5c74a 100644
--- a/translate.c
+++ b/translate.c
@@ -109,8 +109,8 @@
  * 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);
 }
 
@@ -488,8 +488,9 @@
  * 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.
@@ -521,7 +522,7 @@
   } 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);
       writev(fd, out, iov_len);
     }
diff --git a/translate.h b/translate.h
index 0e520f7..2865ca9 100644
--- a/translate.h
+++ b/translate.h
@@ -43,14 +43,14 @@
 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);