Merge "switch BpfBitmap key from U32 to S32"
diff --git a/staticlibs/device/com/android/net/module/util/BpfMap.java b/staticlibs/device/com/android/net/module/util/BpfMap.java
index 2267f31..9042085 100644
--- a/staticlibs/device/com/android/net/module/util/BpfMap.java
+++ b/staticlibs/device/com/android/net/module/util/BpfMap.java
@@ -67,8 +67,10 @@
private static ConcurrentHashMap<Pair<String, Integer>, ParcelFileDescriptor> sFdCache =
new ConcurrentHashMap<>();
- private static ParcelFileDescriptor cachedBpfFdGet(String path, int mode)
+ private static ParcelFileDescriptor cachedBpfFdGet(String path, int mode,
+ int keySize, int valueSize)
throws ErrnoException, NullPointerException {
+ // TODO: key should include keySize & valueSize, but really we should match specific types
Pair<String, Integer> key = Pair.create(path, mode);
// unlocked fetch is safe: map is concurrent read capable, and only inserted into
ParcelFileDescriptor fd = sFdCache.get(key);
@@ -79,7 +81,7 @@
fd = sFdCache.get(key);
if (fd != null) return fd;
// okay, we really haven't opened this before...
- fd = ParcelFileDescriptor.adoptFd(nativeBpfFdGet(path, mode));
+ fd = ParcelFileDescriptor.adoptFd(nativeBpfFdGet(path, mode, keySize, valueSize));
sFdCache.put(key, fd);
return fd;
}
@@ -94,11 +96,11 @@
*/
public BpfMap(@NonNull final String path, final int flag, final Class<K> key,
final Class<V> value) throws ErrnoException, NullPointerException {
- mMapFd = cachedBpfFdGet(path, flag);
mKeyClass = key;
mValueClass = value;
mKeySize = Struct.getSize(key);
mValueSize = Struct.getSize(value);
+ mMapFd = cachedBpfFdGet(path, flag, mKeySize, mValueSize);
}
/**
@@ -295,7 +297,7 @@
}
}
- private static native int nativeBpfFdGet(String path, int mode)
+ private static native int nativeBpfFdGet(String path, int mode, int keySize, int valueSize)
throws ErrnoException, NullPointerException;
// Note: the following methods appear to not require the object by virtue of taking the
diff --git a/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
index 28d4b8b..e2cb676 100644
--- a/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
+++ b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
@@ -16,6 +16,7 @@
#pragma once
+#include <errno.h>
#include <linux/if_ether.h>
#include <linux/pfkeyv2.h>
#include <net/if.h>
@@ -25,9 +26,10 @@
#include <sys/socket.h>
#include <sys/utsname.h>
-#include <android-base/unique_fd.h>
#include <log/log.h>
+#include "KernelVersion.h"
+
namespace android {
namespace bpf {
@@ -84,27 +86,5 @@
return res;
}
-#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c))
-
-static inline unsigned uncachedKernelVersion() {
- struct utsname buf;
- if (uname(&buf)) return 0;
-
- unsigned kver_major = 0;
- unsigned kver_minor = 0;
- unsigned kver_sub = 0;
- (void)sscanf(buf.release, "%u.%u.%u", &kver_major, &kver_minor, &kver_sub);
- return KVER(kver_major, kver_minor, kver_sub);
-}
-
-static inline unsigned kernelVersion() {
- static unsigned kver = uncachedKernelVersion();
- return kver;
-}
-
-static inline bool isAtLeastKernelVersion(unsigned major, unsigned minor, unsigned sub) {
- return kernelVersion() >= KVER(major, minor, sub);
-}
-
} // namespace bpf
} // namespace android
diff --git a/staticlibs/native/bpf_headers/include/bpf/KernelVersion.h b/staticlibs/native/bpf_headers/include/bpf/KernelVersion.h
new file mode 100644
index 0000000..e0e53a9
--- /dev/null
+++ b/staticlibs/native/bpf_headers/include/bpf/KernelVersion.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/utsname.h>
+
+namespace android {
+namespace bpf {
+
+#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c))
+
+static inline unsigned uncachedKernelVersion() {
+ struct utsname buf;
+ if (uname(&buf)) return 0;
+
+ unsigned kver_major = 0;
+ unsigned kver_minor = 0;
+ unsigned kver_sub = 0;
+ (void)sscanf(buf.release, "%u.%u.%u", &kver_major, &kver_minor, &kver_sub);
+ return KVER(kver_major, kver_minor, kver_sub);
+}
+
+static inline unsigned kernelVersion() {
+ static unsigned kver = uncachedKernelVersion();
+ return kver;
+}
+
+static inline bool isAtLeastKernelVersion(unsigned major, unsigned minor, unsigned sub) {
+ return kernelVersion() >= KVER(major, minor, sub);
+}
+
+} // namespace bpf
+} // namespace android
diff --git a/staticlibs/native/bpfmapjni/Android.bp b/staticlibs/native/bpfmapjni/Android.bp
index cd254d4..8babcce 100644
--- a/staticlibs/native/bpfmapjni/Android.bp
+++ b/staticlibs/native/bpfmapjni/Android.bp
@@ -23,7 +23,7 @@
"com_android_net_module_util_TcUtils.cpp",
],
header_libs: [
- "bpf_syscall_wrappers",
+ "bpf_headers",
"jni_headers",
],
shared_libs: [
diff --git a/staticlibs/native/bpfmapjni/com_android_net_module_util_BpfMap.cpp b/staticlibs/native/bpfmapjni/com_android_net_module_util_BpfMap.cpp
index 2e88fc8..2146d17 100644
--- a/staticlibs/native/bpfmapjni/com_android_net_module_util_BpfMap.cpp
+++ b/staticlibs/native/bpfmapjni/com_android_net_module_util_BpfMap.cpp
@@ -25,15 +25,34 @@
#define BPF_FD_JUST_USE_INT
#include "BpfSyscallWrappers.h"
+#include "bpf/KernelVersion.h"
+
namespace android {
static jint com_android_net_module_util_BpfMap_nativeBpfFdGet(JNIEnv *env, jclass clazz,
- jstring path, jint mode) {
+ jstring path, jint mode, jint keySize, jint valueSize) {
ScopedUtfChars pathname(env, path);
jint fd = bpf::bpfFdGet(pathname.c_str(), static_cast<unsigned>(mode));
- if (fd < 0) jniThrowErrnoException(env, "nativeBpfFdGet", errno);
+ if (fd < 0) {
+ jniThrowErrnoException(env, "nativeBpfFdGet", errno);
+ return -1;
+ }
+
+ if (bpf::isAtLeastKernelVersion(4, 14, 0)) {
+ // These likely fail with -1 and set errno to EINVAL on <4.14
+ if (bpf::bpfGetFdKeySize(fd) != keySize) {
+ close(fd);
+ jniThrowErrnoException(env, "nativeBpfFdGet KeySize", EBADFD);
+ return -1;
+ }
+ if (bpf::bpfGetFdValueSize(fd) != valueSize) {
+ close(fd);
+ jniThrowErrnoException(env, "nativeBpfFdGet ValueSize", EBADFD);
+ return -1;
+ }
+ }
return fd;
}
@@ -103,7 +122,7 @@
*/
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
- { "nativeBpfFdGet", "(Ljava/lang/String;I)I",
+ { "nativeBpfFdGet", "(Ljava/lang/String;III)I",
(void*) com_android_net_module_util_BpfMap_nativeBpfFdGet },
{ "nativeWriteToMapEntry", "(I[B[BI)V",
(void*) com_android_net_module_util_BpfMap_nativeWriteToMapEntry },
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java
index 4e48332..a66dacd 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java
@@ -57,8 +57,8 @@
@Test
public void testToBase64EncodedString() {
- final Struct.U32 key = new Struct.U32(TEST_KEY);
- final Struct.U32 value = new Struct.U32(TEST_VAL);
+ final Struct.S32 key = new Struct.S32(TEST_KEY);
+ final Struct.S32 value = new Struct.S32(TEST_VAL);
// Verified in python:
// import base64
@@ -71,15 +71,15 @@
@Test
public void testFromBase64EncodedString() {
- Pair<Struct.U32, Struct.U32> decodedKeyValue = BpfDump.fromBase64EncodedString(
- Struct.U32.class, Struct.U32.class, TEST_KEY_VAL_BASE64);
+ Pair<Struct.S32, Struct.S32> decodedKeyValue = BpfDump.fromBase64EncodedString(
+ Struct.S32.class, Struct.S32.class, TEST_KEY_VAL_BASE64);
assertEquals(TEST_KEY, decodedKeyValue.first.val);
assertEquals(TEST_VAL, decodedKeyValue.second.val);
}
private void assertThrowsIllegalArgumentException(final String testStr) {
assertThrows(IllegalArgumentException.class,
- () -> BpfDump.fromBase64EncodedString(Struct.U32.class, Struct.U32.class, testStr));
+ () -> BpfDump.fromBase64EncodedString(Struct.S32.class, Struct.S32.class, testStr));
}
@Test
@@ -96,7 +96,7 @@
TEST_KEY_VAL_BASE64 + BASE64_DELIMITER + TEST_KEY_BASE64);
}
- private String getDumpMap(final IBpfMap<Struct.U32, Struct.U32> map) {
+ private String getDumpMap(final IBpfMap<Struct.S32, Struct.S32> map) {
final StringWriter sw = new StringWriter();
BpfDump.dumpMap(map, new PrintWriter(sw), "mapName", "header",
(key, val) -> "key=" + key.val + ", val=" + val.val);
@@ -105,9 +105,9 @@
@Test
public void testDumpMap() throws Exception {
- final IBpfMap<Struct.U32, Struct.U32> map =
- new TestBpfMap<>(Struct.U32.class, Struct.U32.class);
- map.updateEntry(new Struct.U32(123), new Struct.U32(456));
+ final IBpfMap<Struct.S32, Struct.S32> map =
+ new TestBpfMap<>(Struct.S32.class, Struct.S32.class);
+ map.updateEntry(new Struct.S32(123), new Struct.S32(456));
final String dump = getDumpMap(map);
assertEquals(dump, "mapName:\n"
@@ -117,10 +117,10 @@
@Test
public void testDumpMapMultipleEntries() throws Exception {
- final IBpfMap<Struct.U32, Struct.U32> map =
- new TestBpfMap<>(Struct.U32.class, Struct.U32.class);
- map.updateEntry(new Struct.U32(123), new Struct.U32(456));
- map.updateEntry(new Struct.U32(789), new Struct.U32(123));
+ final IBpfMap<Struct.S32, Struct.S32> map =
+ new TestBpfMap<>(Struct.S32.class, Struct.S32.class);
+ map.updateEntry(new Struct.S32(123), new Struct.S32(456));
+ map.updateEntry(new Struct.S32(789), new Struct.S32(123));
final String dump = getDumpMap(map);
assertTrue(dump.contains("mapName:"));
@@ -129,7 +129,7 @@
assertTrue(dump.contains("key=789, val=123"));
}
- private String getDumpMapStatus(final IBpfMap<Struct.U32, Struct.U32> map) {
+ private String getDumpMapStatus(final IBpfMap<Struct.S32, Struct.S32> map) {
final StringWriter sw = new StringWriter();
BpfDump.dumpMapStatus(map, new PrintWriter(sw), "mapName", "mapPath");
return sw.toString();
@@ -137,8 +137,8 @@
@Test
public void testGetMapStatus() {
- final IBpfMap<Struct.U32, Struct.U32> map =
- new TestBpfMap<>(Struct.U32.class, Struct.U32.class);
+ final IBpfMap<Struct.S32, Struct.S32> map =
+ new TestBpfMap<>(Struct.S32.class, Struct.S32.class);
assertEquals("mapName: OK\n", getDumpMapStatus(map));
}