[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;
}