ipv4 tethering offload - decrement ttl during forwarding

Bug: 192635131
Test: atest, TreeHugger, flashed on phone, forwarded ipv4 traffic
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Original-Change: https://android-review.googlesource.com/1755049
Merged-In: I88e5293a54b7867a8e7dd76f6fd8e2a52d31e51a
Change-Id: I88e5293a54b7867a8e7dd76f6fd8e2a52d31e51a
This commit is contained in:
Maciej Żenczykowski
2021-07-02 21:36:48 +00:00
committed by Maciej Zenczykowski
parent 0868536de9
commit f416b8a1ff

View File

@@ -569,6 +569,16 @@ static inline __always_inline int do_forward4(struct __sk_buff* skb, const bool
// For a rawip tx interface it will simply be a bunch of zeroes and later stripped. // For a rawip tx interface it will simply be a bunch of zeroes and later stripped.
*eth = v->macHeader; *eth = v->macHeader;
// Decrement the IPv4 TTL, we already know it's greater than 1.
// u8 TTL field is followed by u8 protocol to make a u16 for ipv4 header checksum update.
// Since we're keeping the ipv4 checksum valid (which means the checksum of the entire
// ipv4 header remains 0), the overall checksum of the entire packet does not change.
const int sz2 = sizeof(__be16);
const __be16 old_ttl_proto = *(__be16 *)&ip->ttl;
const __be16 new_ttl_proto = old_ttl_proto - htons(0x0100);
bpf_l3_csum_replace(skb, ETH_IP4_OFFSET(check), old_ttl_proto, new_ttl_proto, sz2);
bpf_skb_store_bytes(skb, ETH_IP4_OFFSET(ttl), &new_ttl_proto, sz2, 0);
const int l4_offs_csum = is_tcp ? ETH_IP4_TCP_OFFSET(check) : ETH_IP4_UDP_OFFSET(check); const int l4_offs_csum = is_tcp ? ETH_IP4_TCP_OFFSET(check) : ETH_IP4_UDP_OFFSET(check);
const int sz4 = sizeof(__be32); const int sz4 = sizeof(__be32);
// UDP 0 is special and stored as FFFF (this flag also causes a csum of 0 to be unmodified) // UDP 0 is special and stored as FFFF (this flag also causes a csum of 0 to be unmodified)
@@ -586,7 +596,6 @@ static inline __always_inline int do_forward4(struct __sk_buff* skb, const bool
bpf_l3_csum_replace(skb, ETH_IP4_OFFSET(check), old_saddr, new_saddr, sz4); bpf_l3_csum_replace(skb, ETH_IP4_OFFSET(check), old_saddr, new_saddr, sz4);
bpf_skb_store_bytes(skb, ETH_IP4_OFFSET(saddr), &new_saddr, sz4, 0); bpf_skb_store_bytes(skb, ETH_IP4_OFFSET(saddr), &new_saddr, sz4, 0);
const int sz2 = sizeof(__be16);
// The offsets for TCP and UDP ports: source (u16 @ L4 offset 0) & dest (u16 @ L4 offset 2) are // The offsets for TCP and UDP ports: source (u16 @ L4 offset 0) & dest (u16 @ L4 offset 2) are
// actually the same, so the compiler should just optimize them both down to a constant. // actually the same, so the compiler should just optimize them both down to a constant.
bpf_l4_csum_replace(skb, l4_offs_csum, k.srcPort, v->srcPort, sz2 | l4_flags); bpf_l4_csum_replace(skb, l4_offs_csum, k.srcPort, v->srcPort, sz2 | l4_flags);
@@ -597,8 +606,6 @@ static inline __always_inline int do_forward4(struct __sk_buff* skb, const bool
bpf_skb_store_bytes(skb, is_tcp ? ETH_IP4_TCP_OFFSET(dest) : ETH_IP4_UDP_OFFSET(dest), bpf_skb_store_bytes(skb, is_tcp ? ETH_IP4_TCP_OFFSET(dest) : ETH_IP4_UDP_OFFSET(dest),
&v->dstPort, sz2, 0); &v->dstPort, sz2, 0);
// TEMP HACK: lack of TTL decrement
// This requires the bpf_ktime_get_boot_ns() helper which was added in 5.8, // This requires the bpf_ktime_get_boot_ns() helper which was added in 5.8,
// and backported to all Android Common Kernel 4.14+ trees. // and backported to all Android Common Kernel 4.14+ trees.
if (updatetime) v->last_used = bpf_ktime_get_boot_ns(); if (updatetime) v->last_used = bpf_ktime_get_boot_ns();