[CLATJ#19] ClatdCoordinator: configure bpf for clat

Configure eBPF offload at clat starting if possible.

Bug: 212345928
Test: connect to ipv6 only network and check bpf entries
$adb shell dumpsys netd --short | grep Clat -A10
  ClatdController
    Trackers: iif[iface] nat64Prefix v6Addr -> v4Addr v4iif[v4iface] [fwmark]
    BPF ingress map: iif(iface) nat64Prefix v6Addr -> v4Addr oif(iface)
      47(wlan0) 64:ff9b::/96 2a00:79e1:abc:6f02:b7aa:ff3c:9220:595c -> 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:b7aa:ff3c:9220:595c 64:ff9b::/96 47(wlan0) ether

Change-Id: I8ff77a2e3e86bfe6dbf43f4181414e444ba0da32
diff --git a/service/Android.bp b/service/Android.bp
index e376ff7..d1a9004 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -65,6 +65,7 @@
         "libbase_headers",
     ],
     static_libs: [
+        "libbase",
         "libclat",
         "libip_checksum",
         "libnetjniutils",
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index a9d7946..0272bc1 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -19,17 +19,22 @@
 #include <fcntl.h>
 #include <linux/if_tun.h>
 #include <linux/ioctl.h>
+#include <log/log.h>
 #include <nativehelper/JNIHelp.h>
 #include <net/if.h>
+#include <string>
 
 #include <netjniutils/netjniutils.h>
 
+#include "libclat/bpfhelper.h"
 #include "libclat/clatutils.h"
 #include "nativehelper/scoped_utf_chars.h"
 
 // Sync from system/netd/include/netid_client.h
 #define MARK_UNSET 0u
 
+#define DEVICEPREFIX "v4-"
+
 namespace android {
 static void throwIOException(JNIEnv* env, const char* msg, int error) {
     jniThrowExceptionFmt(env, "java/io/IOException", "%s: %s", msg, strerror(error));
@@ -237,6 +242,67 @@
     }
 }
 
+int initTracker(const std::string& iface, const std::string& pfx96, const std::string& v4,
+        const std::string& v6, net::clat::ClatdTracker* output) {
+    strlcpy(output->iface, iface.c_str(), sizeof(output->iface));
+    output->ifIndex = if_nametoindex(iface.c_str());
+    if (output->ifIndex == 0) {
+        ALOGE("interface %s not found", output->iface);
+        return -1;
+    }
+
+    unsigned len = snprintf(output->v4iface, sizeof(output->v4iface),
+            "%s%s", DEVICEPREFIX, iface.c_str());
+    if (len >= sizeof(output->v4iface)) {
+        ALOGE("interface name too long '%s'", output->v4iface);
+        return -1;
+    }
+
+    output->v4ifIndex = if_nametoindex(output->v4iface);
+    if (output->v4ifIndex == 0) {
+        ALOGE("v4-interface %s not found", output->v4iface);
+        return -1;
+    }
+
+    if (!inet_pton(AF_INET6, pfx96.c_str(), &output->pfx96)) {
+        ALOGE("invalid IPv6 address specified for plat prefix: %s", pfx96.c_str());
+        return -1;
+    }
+
+    if (!inet_pton(AF_INET, v4.c_str(), &output->v4)) {
+        ALOGE("Invalid IPv4 address %s", v4.c_str());
+        return -1;
+    }
+
+    if (!inet_pton(AF_INET6, v6.c_str(), &output->v6)) {
+        ALOGE("Invalid source address %s", v6.c_str());
+        return -1;
+    }
+
+    return 0;
+}
+
+// TODO: fork clatd and rename to .._startClatd.
+static jint com_android_server_connectivity_ClatCoordinator_maybeStartBpf(
+        JNIEnv* env, jobject clazz, jobject tunJavaFd, jobject readSockJavaFd,
+        jobject writeSockJavaFd, jstring iface, jstring pfx96, jstring v4, jstring v6) {
+    ScopedUtfChars ifaceStr(env, iface);
+    ScopedUtfChars pfx96Str(env, pfx96);
+    ScopedUtfChars v4Str(env, v4);
+    ScopedUtfChars v6Str(env, v6);
+
+    // Start BPF if any
+    if (!net::clat::initMaps()) {
+        net::clat::ClatdTracker tracker = {};
+        if (!initTracker(ifaceStr.c_str(), pfx96Str.c_str(), v4Str.c_str(), v6Str.c_str(),
+                &tracker)) {
+            net::clat::maybeStartBpf(tracker);
+        }
+    }
+
+    return 0; // TODO: return forked clatd pid.
+}
+
 /*
  * JNI registration.
  */
@@ -259,6 +325,10 @@
          (void*)com_android_server_connectivity_ClatCoordinator_addAnycastSetsockopt},
         {"native_configurePacketSocket", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V",
          (void*)com_android_server_connectivity_ClatCoordinator_configurePacketSocket},
+        {"native_maybeStartBpf",
+         "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/lang/"
+         "String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+         (void*)com_android_server_connectivity_ClatCoordinator_maybeStartBpf},
 };
 
 int register_android_server_connectivity_ClatCoordinator(JNIEnv* env) {
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index 4d243c4..a785974 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -162,6 +162,15 @@
                 throws IOException {
             native_configurePacketSocket(sock, v6, ifindex);
         }
+
+        /**
+         * Maybe start bpf.
+         */
+        public int maybeStartBpf(@NonNull FileDescriptor tunfd, @NonNull FileDescriptor readsock6,
+                @NonNull FileDescriptor writesock6, @NonNull String iface, @NonNull String pfx96,
+                @NonNull String v4, @NonNull String v6) throws IOException {
+            return native_maybeStartBpf(tunfd, readsock6, writesock6, iface, pfx96, v4, v6);
+        }
     }
 
     @VisibleForTesting
@@ -304,6 +313,14 @@
             throw new IOException("configure packet socket failed: " + e);
         }
 
+        // [5] Maybe start bpf.
+        try {
+            mDeps.maybeStartBpf(tunFd.getFileDescriptor(), readSock6.getFileDescriptor(),
+                    writeSock6.getFileDescriptor(), iface, pfx96, v4, v6);
+        } catch (IOException e) {
+            throw new IOException("Error start bpf on " + iface + ": " + e);
+        }
+
         // TODO: start clatd and returns local xlat464 v6 address.
         return null;
     }
@@ -321,4 +338,7 @@
             int ifindex) throws IOException;
     private static native void native_configurePacketSocket(FileDescriptor sock, String v6,
             int ifindex) throws IOException;
+    private static native int native_maybeStartBpf(FileDescriptor tunfd, FileDescriptor readsock6,
+            FileDescriptor writesock6, String iface, String pfx96, String v4, String v6)
+            throws IOException;
 }