[CLATJ#31] ClatCoordinator: tag raw socket to uid AID_CLAT
Tag socket as uid AID_CLAT to avoid duplicated data usage counting by
bpf program.
Test: atest FrameworksNetTests
Test: check dumpsys for tag mapping and check logging for socket cookie
$ adb shell dumpsys connectivity trafficcontroller
mCookieTagMap:
cookie=28831 tag=0x0 uid=1029
03-02 22:43:13.201 1719 1921 I jniClatCoordinator: tag uid AID_CLAT to socket fd 609, cookie 28831
03-02 22:43:13.217 5496 5496 I clatd : tunnel.write_fd6 609, cookie 28831, flags 0x0 (debug only)
Bug: 218407445
Change-Id: I67b9f30b143e791ddf59d5627e068ec3107e3328
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 71ddd11..5be8307 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -18,6 +18,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <linux/if_tun.h>
#include <linux/ioctl.h>
#include <log/log.h>
@@ -27,7 +28,11 @@
#include <sys/wait.h>
#include <string>
+#include <bpf/BpfMap.h>
+#include <bpf/BpfUtils.h>
+#include <bpf_shared.h>
#include <netjniutils/netjniutils.h>
+#include <private/android_filesystem_config.h>
#include "libclat/bpfhelper.h"
#include "libclat/clatutils.h"
@@ -473,6 +478,42 @@
stopClatdProcess(pid);
}
+static jlong com_android_server_connectivity_ClatCoordinator_tagSocketAsClat(
+ JNIEnv* env, jobject clazz, jobject sockJavaFd) {
+ int sockFd = netjniutils::GetNativeFileDescriptor(env, sockJavaFd);
+ if (sockFd < 0) {
+ jniThrowExceptionFmt(env, "java/io/IOException", "Invalid socket file descriptor");
+ return -1;
+ }
+
+ uint64_t sock_cookie = bpf::getSocketCookie(sockFd);
+ if (sock_cookie == bpf::NONEXISTENT_COOKIE) {
+ throwIOException(env, "get socket cookie failed", errno);
+ return -1;
+ }
+
+ bpf::BpfMap<uint64_t, UidTagValue> cookieTagMap;
+ auto res = cookieTagMap.init(COOKIE_TAG_MAP_PATH);
+ if (!res.ok()) {
+ throwIOException(env, "failed to init the cookieTagMap", res.error().code());
+ return -1;
+ }
+
+ // Tag raw socket with uid AID_CLAT and set tag as zero because tag is unused in bpf
+ // program for counting data usage in netd.c. Tagging socket is used to avoid counting
+ // duplicated clat traffic in bpf stat.
+ UidTagValue newKey = {.uid = (uint32_t)AID_CLAT, .tag = 0 /* unused */};
+ res = cookieTagMap.writeValue(sock_cookie, newKey, BPF_ANY);
+ if (!res.ok()) {
+ jniThrowExceptionFmt(env, "java/io/IOException", "Failed to tag the socket: %s, fd: %d",
+ strerror(res.error().code()), cookieTagMap.getMap().get());
+ return -1;
+ }
+
+ ALOGI("tag uid AID_CLAT to socket fd %d, cookie %" PRIu64 "", sockFd, sock_cookie);
+ return static_cast<jlong>(sock_cookie);
+}
+
/*
* JNI registration.
*/
@@ -502,6 +543,8 @@
{"native_stopClatd",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V",
(void*)com_android_server_connectivity_ClatCoordinator_stopClatd},
+ {"native_tagSocketAsClat", "(Ljava/io/FileDescriptor;)J",
+ (void*)com_android_server_connectivity_ClatCoordinator_tagSocketAsClat},
};
int register_com_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 c57983b..f8d5a28 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -67,6 +67,7 @@
private static final int INVALID_IFINDEX = 0;
private static final int INVALID_PID = 0;
+ private static final long INVALID_COOKIE = 0;
@NonNull
private final INetd mNetd;
@@ -81,6 +82,7 @@
@Nullable
private String mXlatLocalAddress6 = null;
private int mPid = INVALID_PID;
+ private long mCookie = INVALID_COOKIE;
@VisibleForTesting
abstract static class Dependencies {
@@ -185,6 +187,13 @@
throws IOException {
native_stopClatd(iface, pfx96, v4, v6, pid);
}
+
+ /**
+ * Tag socket as clat.
+ */
+ public long tagSocketAsClat(@NonNull FileDescriptor sock) throws IOException {
+ return native_tagSocketAsClat(sock);
+ }
}
@VisibleForTesting
@@ -335,6 +344,17 @@
throw new IOException("add anycast sockopt failed: " + e);
}
+ // Tag socket as AID_CLAT to avoid duplicated CLAT data usage accounting.
+ long cookie;
+ try {
+ cookie = mDeps.tagSocketAsClat(writeSock6.getFileDescriptor());
+ } catch (IOException e) {
+ tunFd.close();
+ readSock6.close();
+ writeSock6.close();
+ throw new IOException("tag raw socket failed: " + e);
+ }
+
// Update our packet socket filter to reflect the new 464xlat IP address.
try {
mDeps.configurePacketSocket(readSock6.getFileDescriptor(), v6, ifaceIndex);
@@ -353,7 +373,9 @@
mNat64Prefix = pfx96;
mXlatLocalAddress4 = v4;
mXlatLocalAddress6 = v6;
+ mCookie = cookie;
} catch (IOException e) {
+ // TODO: untag socket.
throw new IOException("Error start clatd on " + iface + ": " + e);
} finally {
tunFd.close();
@@ -403,4 +425,5 @@
throws IOException;
private static native void native_stopClatd(String iface, String pfx96, String v4, String v6,
int pid) throws IOException;
+ private static native long native_tagSocketAsClat(FileDescriptor sock) throws IOException;
}
diff --git a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
index 84e02ce..63050a3 100644
--- a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
@@ -82,6 +82,7 @@
private static final int TUN_FD = 534;
private static final int RAW_SOCK_FD = 535;
private static final int PACKET_SOCK_FD = 536;
+ private static final long RAW_SOCK_COOKIE = 27149;
private static final ParcelFileDescriptor TUN_PFD = new ParcelFileDescriptor(
new FileDescriptor());
private static final ParcelFileDescriptor RAW_SOCK_PFD = new ParcelFileDescriptor(
@@ -258,12 +259,25 @@
/**
* Stop clatd.
*/
+ @Override
public void stopClatd(@NonNull String iface, @NonNull String pfx96, @NonNull String v4,
@NonNull String v6, int pid) throws IOException {
if (pid == -1) {
fail("unsupported arg: " + pid);
}
}
+
+ /**
+ * Tag socket as clat.
+ */
+ @Override
+ public long tagSocketAsClat(@NonNull FileDescriptor sock) throws IOException {
+ if (Objects.equals(RAW_SOCK_PFD.getFileDescriptor(), sock)) {
+ return RAW_SOCK_COOKIE;
+ }
+ fail("unsupported arg: " + sock);
+ return 0;
+ }
};
@NonNull
@@ -326,6 +340,8 @@
inOrder.verify(mDeps).addAnycastSetsockopt(
argThat(fd -> Objects.equals(RAW_SOCK_PFD.getFileDescriptor(), fd)),
eq(XLAT_LOCAL_IPV6ADDR_STRING), eq(BASE_IFINDEX));
+ inOrder.verify(mDeps).tagSocketAsClat(
+ argThat(fd -> Objects.equals(RAW_SOCK_PFD.getFileDescriptor(), fd)));
inOrder.verify(mDeps).configurePacketSocket(
argThat(fd -> Objects.equals(PACKET_SOCK_PFD.getFileDescriptor(), fd)),
eq(XLAT_LOCAL_IPV6ADDR_STRING), eq(BASE_IFINDEX));