diff --git a/bpf_progs/clatd.c b/bpf_progs/clatd.c index addb02fe8b..8877bfe156 100644 --- a/bpf_progs/clatd.c +++ b/bpf_progs/clatd.c @@ -265,6 +265,10 @@ static inline __always_inline int nat64(struct __sk_buff* skb, *(struct iphdr*)data = ip; } + // Count successfully translated packet + __sync_fetch_and_add(&v->packets, 1); + __sync_fetch_and_add(&v->bytes, skb->len - l2_header_size); + // Redirect, possibly back to same interface, so tcpdump sees packet twice. if (v->oif) return bpf_redirect(v->oif, BPF_F_INGRESS); @@ -416,6 +420,10 @@ DEFINE_BPF_PROG("schedcls/egress4/clat_rawip", AID_ROOT, AID_SYSTEM, sched_cls_e // Copy over the new ipv6 header without an ethernet header. *(struct ipv6hdr*)data = ip6; + // Count successfully translated packet + __sync_fetch_and_add(&v->packets, 1); + __sync_fetch_and_add(&v->bytes, skb->len); + // Redirect to non v4-* interface. Tcpdump only sees packet after this redirect. return bpf_redirect(v->oif, 0 /* this is effectively BPF_F_EGRESS */); } diff --git a/bpf_progs/clatd.h b/bpf_progs/clatd.h index b5f1cdc010..a75798f137 100644 --- a/bpf_progs/clatd.h +++ b/bpf_progs/clatd.h @@ -39,8 +39,10 @@ STRUCT_SIZE(ClatIngress6Key, 4 + 2 * 16); // 36 typedef struct { uint32_t oif; // The output interface to redirect to (0 means don't redirect) struct in_addr local4; // The destination IPv4 address + uint64_t packets; // Count of translated gso (large) packets + uint64_t bytes; // Sum of post-translation skb->len } ClatIngress6Value; -STRUCT_SIZE(ClatIngress6Value, 4 + 4); // 8 +STRUCT_SIZE(ClatIngress6Value, 4 + 4 + 8 + 8); // 24 typedef struct { uint32_t iif; // The input interface index @@ -54,7 +56,9 @@ typedef struct { struct in6_addr pfx96; // The destination /96 nat64 prefix, bottom 32 bits must be 0 bool oifIsEthernet; // Whether the output interface requires ethernet header uint8_t pad[3]; + uint64_t packets; // Count of translated gso (large) packets + uint64_t bytes; // Sum of post-translation skb->len } ClatEgress4Value; -STRUCT_SIZE(ClatEgress4Value, 4 + 2 * 16 + 1 + 3); // 40 +STRUCT_SIZE(ClatEgress4Value, 4 + 2 * 16 + 1 + 3 + 8 + 8); // 56 #undef STRUCT_SIZE diff --git a/common/src/com/android/net/module/util/bpf/ClatEgress4Value.java b/common/src/com/android/net/module/util/bpf/ClatEgress4Value.java index 69fab091e9..71f7516be7 100644 --- a/common/src/com/android/net/module/util/bpf/ClatEgress4Value.java +++ b/common/src/com/android/net/module/util/bpf/ClatEgress4Value.java @@ -36,11 +36,24 @@ public class ClatEgress4Value extends Struct { @Field(order = 3, type = Type.U8, padding = 3) public final short oifIsEthernet; // Whether the output interface requires ethernet header + @Field(order = 4, type = Type.U63) + public final long packets; // Count of translated gso (large) packets + + @Field(order = 5, type = Type.U63) + public final long bytes; // Sum of post-translation skb->len + public ClatEgress4Value(final int oif, final Inet6Address local6, final Inet6Address pfx96, - final short oifIsEthernet) { + final short oifIsEthernet, final long packets, final long bytes) { this.oif = oif; this.local6 = local6; this.pfx96 = pfx96; this.oifIsEthernet = oifIsEthernet; + this.packets = packets; + this.bytes = bytes; + } + + public ClatEgress4Value(final int oif, final Inet6Address local6, final Inet6Address pfx96, + final short oifIsEthernet) { + this(oif, local6, pfx96, oifIsEthernet, 0, 0); } } diff --git a/common/src/com/android/net/module/util/bpf/ClatIngress6Value.java b/common/src/com/android/net/module/util/bpf/ClatIngress6Value.java index fb81caa8f0..25f737b78c 100644 --- a/common/src/com/android/net/module/util/bpf/ClatIngress6Value.java +++ b/common/src/com/android/net/module/util/bpf/ClatIngress6Value.java @@ -30,8 +30,21 @@ public class ClatIngress6Value extends Struct { @Field(order = 1, type = Type.Ipv4Address) public final Inet4Address local4; // The destination IPv4 address - public ClatIngress6Value(final int oif, final Inet4Address local4) { + @Field(order = 2, type = Type.U63) + public final long packets; // Count of translated gso (large) packets + + @Field(order = 3, type = Type.U63) + public final long bytes; // Sum of post-translation skb->len + + public ClatIngress6Value(final int oif, final Inet4Address local4, final long packets, + final long bytes) { this.oif = oif; this.local4 = local4; + this.packets = packets; + this.bytes = bytes; + } + + public ClatIngress6Value(final int oif, final Inet4Address local4) { + this(oif, local4, 0, 0); } } diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java index daaf91daf9..eea16bf73e 100644 --- a/service/src/com/android/server/connectivity/ClatCoordinator.java +++ b/service/src/com/android/server/connectivity/ClatCoordinator.java @@ -847,12 +847,12 @@ public class ClatCoordinator { if (mIngressMap.isEmpty()) { pw.println(""); } - pw.println("BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif"); + pw.println("BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif (packets bytes)"); pw.increaseIndent(); mIngressMap.forEach((k, v) -> { // TODO: print interface name - pw.println(String.format("%d %s/96 %s -> %s %d", k.iif, k.pfx96, k.local6, - v.local4, v.oif)); + pw.println(String.format("%d %s/96 %s -> %s %d (%d %d)", k.iif, k.pfx96, k.local6, + v.local4, v.oif, v.packets, v.bytes)); }); pw.decreaseIndent(); } catch (ErrnoException e) { @@ -870,12 +870,13 @@ public class ClatCoordinator { if (mEgressMap.isEmpty()) { pw.println(""); } - pw.println("BPF egress map: iif v4Addr -> v6Addr nat64Prefix oif"); + pw.println("BPF egress map: iif v4Addr -> v6Addr nat64Prefix oif (packets bytes)"); pw.increaseIndent(); mEgressMap.forEach((k, v) -> { // TODO: print interface name - pw.println(String.format("%d %s -> %s %s/96 %d %s", k.iif, k.local4, v.local6, - v.pfx96, v.oif, v.oifIsEthernet != 0 ? "ether" : "rawip")); + pw.println(String.format("%d %s -> %s %s/96 %d %s (%d %d)", k.iif, k.local4, + v.local6, v.pfx96, v.oif, v.oifIsEthernet != 0 ? "ether" : "rawip", + v.packets, v.bytes)); }); pw.decreaseIndent(); } catch (ErrnoException e) { diff --git a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java index 88044be116..da7fda3849 100644 --- a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java +++ b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java @@ -526,13 +526,13 @@ public class ClatCoordinatorTest { + "v4: /192.0.0.46, v6: /2001:db8:0:b11::464, pfx96: /64:ff9b::, " + "pid: 10483, cookie: 27149", dumpStrings[0].trim()); assertEquals("Forwarding rules:", dumpStrings[1].trim()); - assertEquals("BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif", + assertEquals("BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif (packets bytes)", dumpStrings[2].trim()); - assertEquals("1000 /64:ff9b::/96 /2001:db8:0:b11::464 -> /192.0.0.46 1001", + assertEquals("1000 /64:ff9b::/96 /2001:db8:0:b11::464 -> /192.0.0.46 1001 (0 0)", dumpStrings[3].trim()); - assertEquals("BPF egress map: iif v4Addr -> v6Addr nat64Prefix oif", + assertEquals("BPF egress map: iif v4Addr -> v6Addr nat64Prefix oif (packets bytes)", dumpStrings[4].trim()); - assertEquals("1001 /192.0.0.46 -> /2001:db8:0:b11::464 /64:ff9b::/96 1000 ether", + assertEquals("1001 /192.0.0.46 -> /2001:db8:0:b11::464 /64:ff9b::/96 1000 ether (0 0)", dumpStrings[5].trim()); } else { assertEquals(1, dumpStrings.length);