ClatdController - Add simple dump output for trackers and ebpf clat map

(heavily based on work by Lorenzo Colitti)

Test: atest netd_unit_test, and manually via 'adb shell dumpsys netd'
Bug: 65674744
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I0565a0c78bf655d099d68d3462b8eb7cf4e34483
diff --git a/server/ClatdController.cpp b/server/ClatdController.cpp
index 06e6d8c..57f24f3 100644
--- a/server/ClatdController.cpp
+++ b/server/ClatdController.cpp
@@ -32,11 +32,15 @@
 #include <log/log.h>
 
 #include "android-base/unique_fd.h"
+#include "bpf/BpfMap.h"
+#include "netdbpf/bpf_shared.h"
+#include "netdutils/DumpWriter.h"
 
 extern "C" {
 #include "netutils/checksum.h"
 }
 
+#include "ClatUtils.h"
 #include "Fwmark.h"
 #include "NetdConstants.h"
 #include "NetworkController.h"
@@ -51,6 +55,9 @@
 static const int kV4AddrLen = 29;
 
 using android::base::unique_fd;
+using android::bpf::BpfMap;
+using android::netdutils::DumpWriter;
+using android::netdutils::ScopedIndent;
 
 namespace android {
 namespace net {
@@ -287,6 +294,57 @@
     return 0;
 }
 
+void ClatdController::dump(DumpWriter& dw) {
+    std::lock_guard guard(mutex);
+
+    ScopedIndent clatdIndent(dw);
+    dw.println("ClatdController");
+
+    {
+        ScopedIndent trackerIndent(dw);
+        dw.println("Trackers: iif[iface] nat64Prefix v6Addr -> v4Addr [netId]");
+
+        ScopedIndent trackerDetailIndent(dw);
+        for (const auto& pair : mClatdTrackers) {
+            const ClatdTracker& tracker = pair.second;
+            dw.println("%u[%s] %s/96 %s -> %s [%u]", tracker.ifIndex, tracker.iface,
+                       tracker.pfx96String, tracker.v6Str, tracker.v4Str, tracker.netId);
+        }
+    }
+
+    int fd = getClatIngressMapFd();
+    if (fd < 0) return;  // if unsupported just don't dump anything
+    unique_fd mapFd(fd);
+
+    ScopedIndent bpfIndent(dw);
+    dw.println("BPF ingress map: iif(iface) nat64Prefix v6Addr -> v4Addr oif(iface)");
+
+    ScopedIndent bpfDetailIndent(dw);
+    BpfMap<ClatIngressKey, ClatIngressValue> configMap(mapFd);
+    const auto printClatMap = [&dw](const ClatIngressKey& key, const ClatIngressValue& value,
+                                    const BpfMap<ClatIngressKey, ClatIngressValue>&) {
+        char iifStr[IFNAMSIZ] = "?";
+        char pfx96Str[INET6_ADDRSTRLEN] = "?";
+        char local6Str[INET6_ADDRSTRLEN] = "?";
+        char local4Str[INET_ADDRSTRLEN] = "?";
+        char oifStr[IFNAMSIZ] = "?";
+
+        if_indextoname(key.iif, iifStr);
+        inet_ntop(AF_INET6, &key.pfx96, pfx96Str, sizeof(pfx96Str));
+        inet_ntop(AF_INET6, &key.local6, local6Str, sizeof(local6Str));
+        inet_ntop(AF_INET, &value.local4, local4Str, sizeof(local4Str));
+        if_indextoname(value.oif, oifStr);
+
+        dw.println("%u(%s) %s/96 %s -> %s %u(%s)", key.iif, iifStr, pfx96Str, local6Str, local4Str,
+                   value.oif, oifStr);
+        return netdutils::status::ok;
+    };
+    auto res = configMap.iterateWithValue(printClatMap);
+    if (!isOk(res)) {
+        dw.println("Error printing BPF map: %s", res.msg().c_str());
+    }
+}
+
 auto ClatdController::isIpv4AddressFreeFunc = isIpv4AddressFree;
 
 }  // namespace net
diff --git a/server/ClatdController.h b/server/ClatdController.h
index 5e97b73..cd5ad14 100644
--- a/server/ClatdController.h
+++ b/server/ClatdController.h
@@ -24,8 +24,11 @@
 #include <linux/if.h>
 #include <netinet/in.h>
 
+#include <android-base/thread_annotations.h>
+
 #include "Fwmark.h"
 #include "NetdConstants.h"
+#include "netdutils/DumpWriter.h"
 
 namespace android {
 namespace net {
@@ -41,6 +44,8 @@
                    std::string* v6Addr);
     int stopClatd(const std::string& interface);
 
+    void dump(netdutils::DumpWriter& dw) EXCLUDES(mutex);
+
     std::mutex mutex;
 
   private:
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index 15df7da..a455876 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -231,6 +231,9 @@
     gCtls->xfrmCtrl.dump(dw);
     dw.blankline();
 
+    gCtls->clatdCtrl.dump(dw);
+    dw.blankline();
+
     {
         ScopedIndent indentLog(dw);
         if (contains(args, String16(OPT_SHORT))) {