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);