Merge "Set /proc/sys/net/core/bpf_jit_{enable,kallsyms} to 1"
diff --git a/libbpf_android/BpfLoadTest.cpp b/libbpf_android/BpfLoadTest.cpp
index d8d6da6..d27c70b 100644
--- a/libbpf_android/BpfLoadTest.cpp
+++ b/libbpf_android/BpfLoadTest.cpp
@@ -35,7 +35,7 @@
class BpfLoadTest : public testing::Test {
protected:
BpfLoadTest() {}
- int mProgFd, mMapFd;
+ int mProgFd;
void SetUp() {
SKIP_IF_BPF_NOT_SUPPORTED;
@@ -48,9 +48,6 @@
mProgFd = bpf_obj_get(tp_prog_path);
EXPECT_GT(mProgFd, 0);
- mMapFd = bpf_obj_get(tp_map_path);
- EXPECT_GT(mMapFd, 0);
-
int ret = bpf_attach_tracepoint(mProgFd, "sched", "sched_switch");
EXPECT_NE(ret, 0);
}
@@ -59,7 +56,6 @@
SKIP_IF_BPF_NOT_SUPPORTED;
close(mProgFd);
- close(mMapFd);
unlink(tp_prog_path);
unlink(tp_map_path);
}
@@ -67,7 +63,7 @@
void checkMapNonZero() {
// The test program installs a tracepoint on sched:sched_switch
// and expects the kernel to populate a PID corresponding to CPU
- android::bpf::BpfMap<uint32_t, uint32_t> m(mMapFd);
+ android::bpf::BpfMap<uint32_t, uint32_t> m(tp_map_path);
// Wait for program to run a little
sleep(1);
diff --git a/libbpf_android/BpfMapTest.cpp b/libbpf_android/BpfMapTest.cpp
index 445aa6a..a3c9004 100644
--- a/libbpf_android/BpfMapTest.cpp
+++ b/libbpf_android/BpfMapTest.cpp
@@ -53,13 +53,6 @@
protected:
BpfMapTest() {}
- // SetUp() will always populate this with a map, but only some tests will use it.
- // They may use it once via 'mMapFd.release()', or multiple times via 'dup(mMapFd)'
- // to initialize a BpfMap object.
- // If it's not used or only dup'ed then TearDown() will close() it, otherwise
- // whoever got ownership via mMapFd.release() will close() it - possibly much earlier.
- unique_fd mMapFd;
-
void SetUp() {
SKIP_IF_BPF_NOT_SUPPORTED;
@@ -67,9 +60,6 @@
if (!access(PINNED_MAP_PATH, R_OK)) {
EXPECT_EQ(0, remove(PINNED_MAP_PATH));
}
- mMapFd.reset(createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint32_t), TEST_MAP_SIZE,
- BPF_F_NO_PREALLOC));
- ASSERT_LE(0, mMapFd);
}
void TearDown() {
@@ -78,8 +68,6 @@
if (!access(PINNED_MAP_PATH, R_OK)) {
EXPECT_EQ(0, remove(PINNED_MAP_PATH));
}
-
- mMapFd.reset(-1); // close(mMapFd) if still open
}
void checkMapInvalid(BpfMap<uint32_t, uint32_t>& map) {
@@ -124,17 +112,14 @@
BpfMap<uint32_t, uint32_t> testMap1;
checkMapInvalid(testMap1);
- BpfMap<uint32_t, uint32_t> testMap2(mMapFd.release());
+ BpfMap<uint32_t, uint32_t> testMap2(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
checkMapValid(testMap2);
-
- BpfMap<uint32_t, uint32_t> testMap3(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
- checkMapValid(testMap3);
}
TEST_F(BpfMapTest, basicHelpers) {
SKIP_IF_BPF_NOT_SUPPORTED;
- BpfMap<uint32_t, uint32_t> testMap(mMapFd.release());
+ BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
uint32_t key = TEST_KEY1;
uint32_t value_write = TEST_VALUE1;
writeToMapAndCheck(testMap, key, value_write);
@@ -150,13 +135,12 @@
TEST_F(BpfMapTest, reset) {
SKIP_IF_BPF_NOT_SUPPORTED;
- BpfMap<uint32_t, uint32_t> testMap;
- testMap.reset(mMapFd.release());
+ BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
uint32_t key = TEST_KEY1;
uint32_t value_write = TEST_VALUE1;
writeToMapAndCheck(testMap, key, value_write);
- testMap.reset();
+ testMap.reset(-1);
checkMapInvalid(testMap);
ASSERT_GT(0, findMapEntry(testMap.getMap(), &key, &value_write));
ASSERT_EQ(EBADF, errno);
@@ -165,7 +149,7 @@
TEST_F(BpfMapTest, moveConstructor) {
SKIP_IF_BPF_NOT_SUPPORTED;
- BpfMap<uint32_t, uint32_t> testMap1(mMapFd.release());
+ BpfMap<uint32_t, uint32_t> testMap1(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
BpfMap<uint32_t, uint32_t> testMap2;
testMap2 = std::move(testMap1);
uint32_t key = TEST_KEY1;
@@ -195,7 +179,7 @@
TEST_F(BpfMapTest, iterate) {
SKIP_IF_BPF_NOT_SUPPORTED;
- BpfMap<uint32_t, uint32_t> testMap(mMapFd.release());
+ BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
populateMap(TEST_MAP_SIZE, testMap);
int totalCount = 0;
int totalSum = 0;
@@ -215,7 +199,7 @@
TEST_F(BpfMapTest, iterateWithValue) {
SKIP_IF_BPF_NOT_SUPPORTED;
- BpfMap<uint32_t, uint32_t> testMap(mMapFd.release());
+ BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
populateMap(TEST_MAP_SIZE, testMap);
int totalCount = 0;
int totalSum = 0;
@@ -237,7 +221,7 @@
TEST_F(BpfMapTest, mapIsEmpty) {
SKIP_IF_BPF_NOT_SUPPORTED;
- BpfMap<uint32_t, uint32_t> testMap(mMapFd.release());
+ BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
expectMapEmpty(testMap);
uint32_t key = TEST_KEY1;
uint32_t value_write = TEST_VALUE1;
@@ -269,7 +253,7 @@
TEST_F(BpfMapTest, mapClear) {
SKIP_IF_BPF_NOT_SUPPORTED;
- BpfMap<uint32_t, uint32_t> testMap(mMapFd.release());
+ BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
populateMap(TEST_MAP_SIZE, testMap);
Result<bool> isEmpty = testMap.isEmpty();
ASSERT_TRUE(isEmpty);
diff --git a/libbpf_android/include/bpf/BpfMap.h b/libbpf_android/include/bpf/BpfMap.h
index 31efd58..243d9dc 100644
--- a/libbpf_android/include/bpf/BpfMap.h
+++ b/libbpf_android/include/bpf/BpfMap.h
@@ -46,25 +46,20 @@
class BpfMap {
public:
BpfMap<Key, Value>() {};
- explicit BpfMap<Key, Value>(int fd) : mMapFd(fd){};
- // We could technically implement this constructor either with
- // : mMapFd(dup(fd)) {} // fd valid in caller, we have our own local copy
- // or
- // : mMapFd(fd.release()) {} // fd no longer valid in caller, we 'stole' it
- //
- // However, I think we're much better off with a compile time failure, since
- // it's better for whoever passes in a unique_fd to think twice about whether
- // they're trying to pass in ownership or not.
- explicit BpfMap<Key, Value>(base::unique_fd fd) = delete;
+ protected:
+ // flag must be within BPF_OBJ_FLAG_MASK, ie. 0, BPF_F_RDONLY, BPF_F_WRONLY
+ BpfMap<Key, Value>(const char* pathname, uint32_t flags) {
+ int map_fd = mapRetrieve(pathname, flags);
+ if (map_fd >= 0) mMapFd.reset(map_fd);
+ }
+
+ public:
+ explicit BpfMap<Key, Value>(const char* pathname) : BpfMap<Key, Value>(pathname, 0) {}
BpfMap<Key, Value>(bpf_map_type map_type, uint32_t max_entries, uint32_t map_flags) {
int map_fd = createMap(map_type, sizeof(Key), sizeof(Value), max_entries, map_flags);
- if (map_fd < 0) {
- mMapFd.reset(-1);
- } else {
- mMapFd.reset(map_fd);
- }
+ if (map_fd >= 0) mMapFd.reset(map_fd);
}
base::Result<Key> getFirstKey() const {
@@ -136,12 +131,12 @@
// Move constructor
void operator=(BpfMap<Key, Value>&& other) noexcept {
mMapFd = std::move(other.mMapFd);
- other.reset();
+ other.reset(-1);
}
- void reset(int fd = -1) {
- mMapFd.reset(fd);
- }
+ void reset(base::unique_fd fd) = delete;
+
+ void reset(int fd) { mMapFd.reset(fd); }
bool isValid() const { return mMapFd != -1; }
@@ -177,7 +172,6 @@
base::Result<void> BpfMap<Key, Value>::init(const char* path) {
mMapFd = base::unique_fd(mapRetrieve(path, 0));
if (mMapFd == -1) {
- reset();
return base::ErrnoErrorf("Pinned map not accessible or does not exist: ({})", path);
}
return {};
@@ -246,6 +240,13 @@
return curKey.error();
}
+template <class Key, class Value>
+class BpfMapRO : public BpfMap<Key, Value> {
+ public:
+ explicit BpfMapRO<Key, Value>(const char* pathname)
+ : BpfMap<Key, Value>(pathname, BPF_F_RDONLY) {}
+};
+
} // namespace bpf
} // namespace android