TetherIngressValue - add output path/route mtu field

This doesn't actually change anything, since we initialize it with
1500 default just like we blindly assume it always is today.

Tested: builds
Bug: 149816401
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Ie448a988c3a769be07f895621711fe4e59d4535c
Merged-In: Ie448a988c3a769be07f895621711fe4e59d4535c
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index fbb5318..9bcfdcd 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -81,19 +81,22 @@
     // If we don't have a limit, then abort...
     if (!limit_v) return TC_ACT_OK;
 
-    // This is approximate handling of tcp/ip overhead for incoming LRO/GRO packets:
-    // mtu of 1500 is not necessarily correct, but worst case we simply undercount,
-    // which is still better then not accounting for this overhead at all.
-    // Note: this really shouldn't be device mtu at all, but rather should be derived
-    // from this particular connection's mss - which requires a much newer kernel.
-    const int mtu = 1500;
+    // Required IPv6 minimum mtu is 1280, below that not clear what we should do, abort...
+    const int pmtu = v->pmtu;
+    if (pmtu < IPV6_MIN_MTU) return TC_ACT_OK;
+
+    // Approximate handling of TCP/IPv6 overhead for incoming LRO/GRO packets: default
+    // outbound path mtu of 1500 is not necessarily correct, but worst case we simply
+    // undercount, which is still better then not accounting for this overhead at all.
+    // Note: this really shouldn't be device/path mtu at all, but rather should be
+    // derived from this particular connection's mss (ie. from gro segment size).
+    // This would require a much newer kernel with newer ebpf accessors.
+    // (This is also blindly assuming 12 bytes of tcp timestamp option in tcp header)
     uint64_t packets = 1;
     uint64_t bytes = skb->len;
-    if (bytes > mtu) {
-        const bool is_ipv6 = (skb->protocol == htons(ETH_P_IPV6));
-        const int ip_overhead = (is_ipv6 ? sizeof(struct ipv6hdr) : sizeof(struct iphdr));
-        const int tcp_overhead = ip_overhead + sizeof(struct tcphdr) + 12;
-        const int mss = mtu - tcp_overhead;
+    if (bytes > pmtu) {
+        const int tcp_overhead = sizeof(struct ipv6hdr) + sizeof(struct tcphdr) + 12;
+        const int mss = pmtu - tcp_overhead;
         const uint64_t payload = bytes - tcp_overhead;
         packets = (payload + mss - 1) / mss;
         bytes = tcp_overhead * packets + payload;
diff --git a/libnetdbpf/include/netdbpf/bpf_shared.h b/libnetdbpf/include/netdbpf/bpf_shared.h
index 9d5f690..6f31879 100644
--- a/libnetdbpf/include/netdbpf/bpf_shared.h
+++ b/libnetdbpf/include/netdbpf/bpf_shared.h
@@ -205,6 +205,7 @@
     // because all downstream types that are currently supported (WiFi, USB, Bluetooth and
     // Ethernet) have 6-byte MAC addresses.
     struct ethhdr macHeader;  // includes dst/src mac and ethertype
+    uint16_t pmtu;            // The maximum L3 output path/route mtu
 } TetherIngressValue;
 
 #define TETHER_STATS_MAP_PATH BPF_PATH "/map_offload_tether_stats_map"
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index 560a01c..50ae966 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -870,8 +870,9 @@
     };
 
     TetherIngressValue value = {
-            static_cast<uint32_t>(rule.outputInterfaceIndex),
-            hdr,
+            .oif = static_cast<uint32_t>(rule.outputInterfaceIndex),
+            .macHeader = hdr,
+            .pmtu = 1500,  // TODO: don't just blindly use this default
     };
 
     return mBpfIngressMap.writeValue(key, value, BPF_ANY);
@@ -1185,7 +1186,7 @@
         return;
     }
 
-    dw.println("BPF ingress map: iif v6addr -> oif srcmac dstmac ethertype");
+    dw.println("BPF ingress map: iif v6addr -> oif srcmac dstmac ethertype [pmtu]");
     const auto printIngressMap = [&dw](const TetherIngressKey& key, const TetherIngressValue& value,
                                        const BpfMap<TetherIngressKey, TetherIngressValue>&) {
         char addr[INET6_ADDRSTRLEN];
@@ -1193,8 +1194,8 @@
         std::string dst = l2ToString(value.macHeader.h_dest, sizeof(value.macHeader.h_dest));
         inet_ntop(AF_INET6, &key.neigh6, addr, sizeof(addr));
 
-        dw.println("%u %s -> %u %s %s %04x", key.iif, addr, value.oif, src.c_str(), dst.c_str(),
-                   ntohs(value.macHeader.h_proto));
+        dw.println("%u %s -> %u %s %s %04x [%u]", key.iif, addr, value.oif, src.c_str(),
+                   dst.c_str(), ntohs(value.macHeader.h_proto), value.pmtu);
 
         return Result<void>();
     };