clat bpf: add byte/packet counter

Bug: 285124667
Test: TreeHugger,
  atest FrameworksNetTests:android.net.connectivity.com.android.server.connectivity.ClatCoordinatorTest
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I5b59f0c05d41030f99160f68058c61eadd24fbbd
This commit is contained in:
Maciej Żenczykowski 2024-03-13 03:39:36 +00:00 • committed by KH Shi
commit 8b3f9d9e3e
6 changed files with 53 additions and 14 deletions

View file

@ -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 */);
}

View file

@ -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

View file

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

View file

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

View file

@ -847,12 +847,12 @@ public class ClatCoordinator {
if (mIngressMap.isEmpty()) {
pw.println("<empty>");
}
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("<empty>");
}
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) {

View file

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