ClatCoordinator: dump BPF forwarding rules

This is a preparation for moving clat map dump from netd to
mainline module.

Test: compare dumpsys connectivity and netd

$ adb shell dumpsys connectivity
Nat464Xlat:
  ClatCoordinator:
    Forwarding rules:
      BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif
        47 /64:ff9b::/96 /2a00:79e1:abc:6f02:4aac:17dd:b40e:8bcc -> /192.0.0.4 52
      BPF egress map: iif v4Addr -> v6Addr nat64Prefix oif
        52 /192.0.0.4 -> /2a00:79e1:abc:6f02:4aac:17dd:b40e:8bcc /64:ff9b::/96 47 ether

$ adb shell dumpsys netd
ClatdController
  BPF ingress map: iif(iface) nat64Prefix v6Addr -> v4Addr oif(iface)
    47(wlan0) 64:ff9b::/96 2a00:79e1:abc:6f02:4aac:17dd:b40e:8bcc -> 192.0.0.4 52(v4-wlan0)
  BPF egress map: iif(iface) v4Addr -> v6Addr nat64Prefix oif(iface)
    52(v4-wlan0) 192.0.0.4 -> 2a00:79e1:abc:6f02:4aac:17dd:b40e:8bcc 64:ff9b::/96 47(wlan0) ether

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2017317

Merged-In: I597709663477b62005b0bc5cc1bf0fc22743e10b
Change-Id: I597709663477b62005b0bc5cc1bf0fc22743e10b
Signed-off-by: Nucca Chen <nuccachen@google.com>
(cherry picked from commit 8be50a6d905d1d6810c0c148ba50f8bef614cde9)
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 843d33d..6de6625 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -3431,6 +3431,10 @@
             pw.increaseIndent();
             nai.dumpInactivityTimers(pw);
             pw.decreaseIndent();
+            pw.println("Nat464Xlat:");
+            pw.increaseIndent();
+            nai.dumpNat464Xlat(pw);
+            pw.decreaseIndent();
             pw.decreaseIndent();
         }
     }
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index cc81522..4a7c77a 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.modules.utils.build.SdkLevel;
 import com.android.net.module.util.BpfMap;
 import com.android.net.module.util.IBpfMap;
@@ -742,6 +743,69 @@
         mClatdTracker = null;
     }
 
+    private void dumpBpfIngress(@NonNull IndentingPrintWriter pw) {
+        if (mIngressMap == null) {
+            pw.println("No BPF ingress6 map");
+            return;
+        }
+
+        try {
+            if (mIngressMap.isEmpty()) {
+                pw.println("<empty>");
+            }
+            pw.println("BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif");
+            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.decreaseIndent();
+        } catch (ErrnoException e) {
+            pw.println("Error dumping BPF ingress6 map: " + e);
+        }
+    }
+
+    private void dumpBpfEgress(@NonNull IndentingPrintWriter pw) {
+        if (mEgressMap == null) {
+            pw.println("No BPF egress4 map");
+            return;
+        }
+
+        try {
+            if (mEgressMap.isEmpty()) {
+                pw.println("<empty>");
+            }
+            pw.println("BPF egress map: iif v4Addr -> v6Addr nat64Prefix oif");
+            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.decreaseIndent();
+        } catch (ErrnoException e) {
+            pw.println("Error dumping BPF egress4 map: " + e);
+        }
+    }
+
+    /**
+     * Dump the cordinator information.
+     *
+     * @param pw print writer.
+     */
+    public void dump(@NonNull IndentingPrintWriter pw) {
+        // TODO: dump ClatdTracker
+        // TODO: move map dump to a global place to avoid duplicate dump while there are two or
+        // more IPv6 only networks.
+        pw.println("Forwarding rules:");
+        pw.increaseIndent();
+        dumpBpfIngress(pw);
+        dumpBpfEgress(pw);
+        pw.decreaseIndent();
+        pw.println();
+    }
+
     /**
      * Get clatd tracker. For test only.
      */
diff --git a/service/src/com/android/server/connectivity/Nat464Xlat.java b/service/src/com/android/server/connectivity/Nat464Xlat.java
index 35e02ca..e8fc06d 100644
--- a/service/src/com/android/server/connectivity/Nat464Xlat.java
+++ b/service/src/com/android/server/connectivity/Nat464Xlat.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.modules.utils.build.SdkLevel;
 import com.android.net.module.util.NetworkStackConstants;
 import com.android.server.ConnectivityService;
@@ -526,6 +527,24 @@
         mNetwork.handler().post(() -> handleInterfaceRemoved(iface));
     }
 
+    /**
+     * Dump the NAT64 xlat information.
+     *
+     * @param pw print writer.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        if (SdkLevel.isAtLeastT()) {
+            if (isStarted()) {
+                pw.println("ClatCoordinator:");
+                pw.increaseIndent();
+                mClatCoordinator.dump(pw);
+                pw.decreaseIndent();
+            } else {
+                pw.println("<not start>");
+            }
+        }
+    }
+
     @Override
     public String toString() {
         return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mState: " + mState;
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index 1fc5a8f..323888a 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -59,6 +59,7 @@
 import android.util.Pair;
 import android.util.SparseArray;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.WakeupMessage;
 import com.android.modules.utils.build.SdkLevel;
 import com.android.server.ConnectivityService;
@@ -1186,6 +1187,15 @@
     }
 
     /**
+     * Dump the NAT64 xlat information.
+     *
+     * @param pw print writer.
+     */
+    public void dumpNat464Xlat(IndentingPrintWriter pw) {
+        clatd.dump(pw);
+    }
+
+    /**
      * Sets the most recent ConnectivityReport for this network.
      *
      * <p>This should only be called from the ConnectivityService thread.