Dump BPF offload rules for upstream IPv4 and IPv6.
Add code to BpfCoordinator to dump upstream IPv4 and IPv6 rules.
For IPv4, currently only the upstream map is printed, because the
downstream map is expected to be symmetrical.
Example output:
=============
21(21) -> 12(rmnet_data2) 86dd 00:00:00:00:00:00 00:00:00:00:00:00
[wlan1]: iif(iface) oif(iface) v6addr srcmac dstmac
12(rmnet_data2) 21(wlan1) /2001:240:2425:b5dc:21a9:995d:bc57:bc37 b2:b5:e0:24:21:c2 ca:06:8d:54:99:ad
[IPv4]: iif(iface) oif(iface) src nat dst
21(21) 12(rmnet_data2) 192.168.16.247:41544 -> 100.101.80.108:41544 -> 216.239.36.135:443
21(21) 12(rmnet_data2) 192.168.16.247:42028 -> 100.101.80.108:42028 -> 8.8.4.4:853
21(21) 12(rmnet_data2) 192.168.16.247:42032 -> 100.101.80.108:42032 -> 8.8.4.4:853
21(21) 12(rmnet_data2) 192.168.16.247:42042 -> 100.101.80.108:42042 -> 8.8.4.4:853
21(21) 12(rmnet_data2) 192.168.16.247:41816 -> 100.101.80.108:41816 -> 8.8.8.8:853
21(21) 12(rmnet_data2) 192.168.16.247:42040 -> 100.101.80.108:42040 -> 8.8.4.4:853
=============
Also make it possible to do "dumpsys tethering bpf" and get only
the BPF dump.
Test: manual
Change-Id: I2aaa2fdda7d724994090c26feff585f24cd3283b
diff --git a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
index 2bdddc1..4dc1c51 100644
--- a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
@@ -324,20 +324,20 @@
return true;
}
+ private String mapStatus(BpfMap m, String name) {
+ return name + "{" + (m != null ? "OK" : "ERROR") + "}";
+ }
+
@Override
public String toString() {
- return "mBpfDownstream4Map{"
- + (mBpfDownstream4Map != null ? "initialized" : "not initialized") + "}, "
- + "mBpfUpstream4Map{"
- + (mBpfUpstream4Map != null ? "initialized" : "not initialized") + "}, "
- + "mBpfUpstream6Map{"
- + (mBpfUpstream6Map != null ? "initialized" : "not initialized") + "}, "
- + "mBpfDownstream6Map{"
- + (mBpfDownstream6Map != null ? "initialized" : "not initialized") + "}, "
- + "mBpfStatsMap{"
- + (mBpfStatsMap != null ? "initialized" : "not initialized") + "}, "
- + "mBpfLimitMap{"
- + (mBpfLimitMap != null ? "initialized" : "not initialized") + "} ";
+ return String.join(", ", new String[] {
+ mapStatus(mBpfDownstream6Map, "mBpfDownstream6Map"),
+ mapStatus(mBpfUpstream6Map, "mBpfUpstream6Map"),
+ mapStatus(mBpfDownstream4Map, "mBpfDownstream4Map"),
+ mapStatus(mBpfUpstream4Map, "mBpfUpstream4Map"),
+ mapStatus(mBpfStatsMap, "mBpfStatsMap"),
+ mapStatus(mBpfLimitMap, "mBpfLimitMap")
+ });
}
/**
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 35de400..b17bfcf 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -64,6 +64,7 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -677,6 +678,12 @@
}
}
+
+ // TODO: make mInterfaceNames accessible to the shim and move this code to there.
+ private String getIfName(long ifindex) {
+ return mInterfaceNames.get((int) ifindex, Long.toString(ifindex));
+ }
+
/**
* Dump information.
* Block the function until all the data are dumped on the handler thread or timed-out. The
@@ -705,11 +712,9 @@
pw.println("Forwarding rules:");
pw.increaseIndent();
- if (mIpv6ForwardingRules.size() == 0) {
- pw.println("<empty>");
- } else {
- dumpIpv6ForwardingRules(pw);
- }
+ dumpIpv6UpstreamRules(pw);
+ dumpIpv6ForwardingRules(pw);
+ dumpIpv4ForwardingRules(pw);
pw.decreaseIndent();
dumpDone.open();
@@ -729,6 +734,11 @@
}
private void dumpIpv6ForwardingRules(@NonNull IndentingPrintWriter pw) {
+ if (mIpv6ForwardingRules.size() == 0) {
+ pw.println("No IPv6 rules");
+ return;
+ }
+
for (Map.Entry<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>> entry :
mIpv6ForwardingRules.entrySet()) {
IpServer ipServer = entry.getKey();
@@ -749,6 +759,63 @@
}
}
+ private String ipv6UpstreamRuletoString(TetherUpstream6Key key, Tether6Value value) {
+ return String.format("%d(%s) -> %d(%s) %04x %s %s",
+ key.iif, getIfName(key.iif), value.oif, getIfName(value.oif),
+ value.ethProto, value.ethSrcMac, value.ethDstMac);
+ }
+
+ private void dumpIpv6UpstreamRules(IndentingPrintWriter pw) {
+ final BpfMap<TetherUpstream6Key, Tether6Value> ipv6UpstreamMap = mDeps.getBpfUpstream6Map();
+ if (ipv6UpstreamMap == null) {
+ pw.println("No IPv6 upstream");
+ return;
+ }
+ try {
+ if (ipv6UpstreamMap.isEmpty()) {
+ pw.println("No IPv6 upstream rules");
+ return;
+ }
+ ipv6UpstreamMap.forEach((k, v) -> pw.println(ipv6UpstreamRuletoString(k, v)));
+ } catch (ErrnoException e) {
+ pw.println("Error dumping IPv4 map: " + e);
+ }
+ }
+
+ private String ipv4RuleToString(Tether4Key key, Tether4Value value) {
+ final String private4, public4, dst4;
+ try {
+ private4 = InetAddress.getByAddress(key.src4).getHostAddress();
+ dst4 = InetAddress.getByAddress(key.dst4).getHostAddress();
+ public4 = InetAddress.getByAddress(value.src46).getHostAddress();
+ } catch (UnknownHostException impossible) {
+ throw new AssertionError("4-byte array not valid IPv4 address!");
+ }
+ return String.format("%d(%s) %d(%s) %s:%d -> %s:%d -> %s:%d",
+ key.iif, getIfName(key.iif), value.oif, getIfName(value.oif),
+ private4, key.srcPort, public4, value.srcPort, dst4, key.dstPort);
+ }
+
+ private void dumpIpv4ForwardingRules(IndentingPrintWriter pw) {
+ final BpfMap<Tether4Key, Tether4Value> ipv4UpstreamMap = mDeps.getBpfUpstream4Map();
+ if (ipv4UpstreamMap == null) {
+ pw.println("No IPv4 support");
+ return;
+ }
+ try {
+ if (ipv4UpstreamMap.isEmpty()) {
+ pw.println("No IPv4 rules");
+ return;
+ }
+ pw.println("[IPv4]: iif(iface) oif(iface) src nat dst");
+ pw.increaseIndent();
+ ipv4UpstreamMap.forEach((k, v) -> pw.println(ipv4RuleToString(k, v)));
+ } catch (ErrnoException e) {
+ pw.println("Error dumping IPv4 map: " + e);
+ }
+ pw.decreaseIndent();
+ }
+
/** IPv6 forwarding rule class. */
public static class Ipv6ForwardingRule {
public final int upstreamIfindex;
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 2354c2d..385c691 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -2225,6 +2225,13 @@
&& !isProvisioningNeededButUnavailable();
}
+ private void dumpBpf(IndentingPrintWriter pw) {
+ pw.println("BPF offload:");
+ pw.increaseIndent();
+ mBpfCoordinator.dump(pw);
+ pw.decreaseIndent();
+ }
+
void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
// Binder.java closes the resource for us.
@SuppressWarnings("resource")
@@ -2235,6 +2242,11 @@
return;
}
+ if (argsContain(args, "bpf")) {
+ dumpBpf(pw);
+ return;
+ }
+
pw.println("Tethering:");
pw.increaseIndent();
@@ -2286,10 +2298,7 @@
mOffloadController.dump(pw);
pw.decreaseIndent();
- pw.println("BPF offload:");
- pw.increaseIndent();
- mBpfCoordinator.dump(pw);
- pw.decreaseIndent();
+ dumpBpf(pw);
pw.println("Private address coordinator:");
pw.increaseIndent();