blob: d0737b0f78f9b63621d452ee0b6cb4891018fd5f [file] [log] [blame]
Chenbo Feng75b410b2018-10-10 15:01:19 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <fstream>
18#include <iostream>
19#include <string>
20#include <vector>
21
22#include <fcntl.h>
23#include <inttypes.h>
24#include <linux/inet_diag.h>
25#include <linux/sock_diag.h>
26#include <net/if.h>
27#include <sys/socket.h>
28#include <sys/types.h>
29#include <unistd.h>
30
31#include <gtest/gtest.h>
32
33#include <android-base/stringprintf.h>
34#include <android-base/strings.h>
35
Chenbo Feng75b410b2018-10-10 15:01:19 -070036#include "bpf/BpfMap.h"
Chenbo Feng75b410b2018-10-10 15:01:19 -070037#include "bpf/BpfUtils.h"
38
Chenbo Feng75b410b2018-10-10 15:01:19 -070039using ::testing::Test;
40
41namespace android {
42namespace bpf {
43
Steven Morelande7cd2a72020-01-10 17:49:35 -080044using base::Result;
Chenbo Feng75b410b2018-10-10 15:01:19 -070045using base::unique_fd;
Chenbo Feng75b410b2018-10-10 15:01:19 -070046
47constexpr uint32_t TEST_MAP_SIZE = 10;
48constexpr uint32_t TEST_KEY1 = 1;
49constexpr uint32_t TEST_VALUE1 = 10;
50constexpr const char PINNED_MAP_PATH[] = "/sys/fs/bpf/testMap";
51
52class BpfMapTest : public testing::Test {
53 protected:
54 BpfMapTest() {}
Maciej Żenczykowskie6cbd402019-08-09 18:20:26 -070055
Chenbo Feng75b410b2018-10-10 15:01:19 -070056 void SetUp() {
Chenbo Feng0a1a9a12019-04-09 12:05:04 -070057 EXPECT_EQ(0, setrlimitForTest());
Chenbo Feng75b410b2018-10-10 15:01:19 -070058 if (!access(PINNED_MAP_PATH, R_OK)) {
59 EXPECT_EQ(0, remove(PINNED_MAP_PATH));
60 }
Chenbo Feng75b410b2018-10-10 15:01:19 -070061 }
62
63 void TearDown() {
64 if (!access(PINNED_MAP_PATH, R_OK)) {
65 EXPECT_EQ(0, remove(PINNED_MAP_PATH));
66 }
Chenbo Feng75b410b2018-10-10 15:01:19 -070067 }
68
69 void checkMapInvalid(BpfMap<uint32_t, uint32_t>& map) {
70 EXPECT_FALSE(map.isValid());
71 EXPECT_EQ(-1, map.getMap().get());
Chenbo Feng75b410b2018-10-10 15:01:19 -070072 }
73
74 void checkMapValid(BpfMap<uint32_t, uint32_t>& map) {
75 EXPECT_LE(0, map.getMap().get());
76 EXPECT_TRUE(map.isValid());
77 }
78
79 void writeToMapAndCheck(BpfMap<uint32_t, uint32_t>& map, uint32_t key, uint32_t value) {
Bernie Innocenti43d25382020-02-10 07:25:16 +090080 ASSERT_RESULT_OK(map.writeValue(key, value, BPF_ANY));
Chenbo Feng75b410b2018-10-10 15:01:19 -070081 uint32_t value_read;
82 ASSERT_EQ(0, findMapEntry(map.getMap(), &key, &value_read));
83 checkValueAndStatus(value, value_read);
84 }
85
Steven Morelande7cd2a72020-01-10 17:49:35 -080086 void checkValueAndStatus(uint32_t refValue, Result<uint32_t> value) {
Bernie Innocenti43d25382020-02-10 07:25:16 +090087 ASSERT_RESULT_OK(value);
Chenbo Feng75b410b2018-10-10 15:01:19 -070088 ASSERT_EQ(refValue, value.value());
89 }
90
91 void populateMap(uint32_t total, BpfMap<uint32_t, uint32_t>& map) {
92 for (uint32_t key = 0; key < total; key++) {
93 uint32_t value = key * 10;
Bernie Innocenti43d25382020-02-10 07:25:16 +090094 EXPECT_RESULT_OK(map.writeValue(key, value, BPF_ANY));
Chenbo Feng75b410b2018-10-10 15:01:19 -070095 }
96 }
97
98 void expectMapEmpty(BpfMap<uint32_t, uint32_t>& map) {
Steven Morelande7cd2a72020-01-10 17:49:35 -080099 Result<bool> isEmpty = map.isEmpty();
Bernie Innocenti43d25382020-02-10 07:25:16 +0900100 ASSERT_RESULT_OK(isEmpty);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700101 ASSERT_TRUE(isEmpty.value());
102 }
103};
104
105TEST_F(BpfMapTest, constructor) {
106 BpfMap<uint32_t, uint32_t> testMap1;
107 checkMapInvalid(testMap1);
108
Maciej Żenczykowski7c9a9842020-01-20 15:51:31 -0800109 BpfMap<uint32_t, uint32_t> testMap2(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700110 checkMapValid(testMap2);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700111}
112
113TEST_F(BpfMapTest, basicHelpers) {
Maciej Żenczykowski7c9a9842020-01-20 15:51:31 -0800114 BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700115 uint32_t key = TEST_KEY1;
116 uint32_t value_write = TEST_VALUE1;
117 writeToMapAndCheck(testMap, key, value_write);
Steven Morelande7cd2a72020-01-10 17:49:35 -0800118 Result<uint32_t> value_read = testMap.readValue(key);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700119 checkValueAndStatus(value_write, value_read);
Steven Morelande7cd2a72020-01-10 17:49:35 -0800120 Result<uint32_t> key_read = testMap.getFirstKey();
Chenbo Feng75b410b2018-10-10 15:01:19 -0700121 checkValueAndStatus(key, key_read);
Bernie Innocenti43d25382020-02-10 07:25:16 +0900122 ASSERT_RESULT_OK(testMap.deleteValue(key));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700123 ASSERT_GT(0, findMapEntry(testMap.getMap(), &key, &value_read));
124 ASSERT_EQ(ENOENT, errno);
125}
126
127TEST_F(BpfMapTest, reset) {
Maciej Żenczykowski7c9a9842020-01-20 15:51:31 -0800128 BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700129 uint32_t key = TEST_KEY1;
130 uint32_t value_write = TEST_VALUE1;
131 writeToMapAndCheck(testMap, key, value_write);
Maciej Żenczykowskie6cbd402019-08-09 18:20:26 -0700132
Maciej Żenczykowski4f657392020-01-20 15:06:22 -0800133 testMap.reset(-1);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700134 checkMapInvalid(testMap);
Maciej Żenczykowskie6cbd402019-08-09 18:20:26 -0700135 ASSERT_GT(0, findMapEntry(testMap.getMap(), &key, &value_write));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700136 ASSERT_EQ(EBADF, errno);
137}
138
139TEST_F(BpfMapTest, moveConstructor) {
Maciej Żenczykowski7c9a9842020-01-20 15:51:31 -0800140 BpfMap<uint32_t, uint32_t> testMap1(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700141 BpfMap<uint32_t, uint32_t> testMap2;
142 testMap2 = std::move(testMap1);
143 uint32_t key = TEST_KEY1;
144 checkMapInvalid(testMap1);
145 uint32_t value = TEST_VALUE1;
146 writeToMapAndCheck(testMap2, key, value);
147}
148
Chenbo Feng75b410b2018-10-10 15:01:19 -0700149TEST_F(BpfMapTest, SetUpMap) {
Maciej Żenczykowski04d88b72019-04-01 10:34:26 -0700150 EXPECT_NE(0, access(PINNED_MAP_PATH, R_OK));
151 BpfMap<uint32_t, uint32_t> testMap1(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
152 ASSERT_EQ(0, bpfFdPin(testMap1.getMap(), PINNED_MAP_PATH));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700153 EXPECT_EQ(0, access(PINNED_MAP_PATH, R_OK));
154 checkMapValid(testMap1);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700155 BpfMap<uint32_t, uint32_t> testMap2;
Bernie Innocenti43d25382020-02-10 07:25:16 +0900156 EXPECT_RESULT_OK(testMap2.init(PINNED_MAP_PATH));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700157 checkMapValid(testMap2);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700158 uint32_t key = TEST_KEY1;
159 uint32_t value = TEST_VALUE1;
160 writeToMapAndCheck(testMap1, key, value);
Steven Morelande7cd2a72020-01-10 17:49:35 -0800161 Result<uint32_t> value_read = testMap2.readValue(key);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700162 checkValueAndStatus(value, value_read);
163}
164
165TEST_F(BpfMapTest, iterate) {
Maciej Żenczykowski7c9a9842020-01-20 15:51:31 -0800166 BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700167 populateMap(TEST_MAP_SIZE, testMap);
168 int totalCount = 0;
169 int totalSum = 0;
170 const auto iterateWithDeletion = [&totalCount, &totalSum](const uint32_t& key,
171 BpfMap<uint32_t, uint32_t>& map) {
172 EXPECT_GE((uint32_t)TEST_MAP_SIZE, key);
173 totalCount++;
174 totalSum += key;
175 return map.deleteValue(key);
176 };
Bernie Innocenti43d25382020-02-10 07:25:16 +0900177 EXPECT_RESULT_OK(testMap.iterate(iterateWithDeletion));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700178 EXPECT_EQ((int)TEST_MAP_SIZE, totalCount);
179 EXPECT_EQ(((1 + TEST_MAP_SIZE - 1) * (TEST_MAP_SIZE - 1)) / 2, (uint32_t)totalSum);
180 expectMapEmpty(testMap);
181}
182
183TEST_F(BpfMapTest, iterateWithValue) {
Maciej Żenczykowski7c9a9842020-01-20 15:51:31 -0800184 BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700185 populateMap(TEST_MAP_SIZE, testMap);
186 int totalCount = 0;
187 int totalSum = 0;
188 const auto iterateWithDeletion = [&totalCount, &totalSum](const uint32_t& key,
189 const uint32_t& value,
190 BpfMap<uint32_t, uint32_t>& map) {
191 EXPECT_GE((uint32_t)TEST_MAP_SIZE, key);
192 EXPECT_EQ(value, key * 10);
193 totalCount++;
194 totalSum += value;
195 return map.deleteValue(key);
196 };
Bernie Innocenti43d25382020-02-10 07:25:16 +0900197 EXPECT_RESULT_OK(testMap.iterateWithValue(iterateWithDeletion));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700198 EXPECT_EQ((int)TEST_MAP_SIZE, totalCount);
199 EXPECT_EQ(((1 + TEST_MAP_SIZE - 1) * (TEST_MAP_SIZE - 1)) * 5, (uint32_t)totalSum);
200 expectMapEmpty(testMap);
201}
202
203TEST_F(BpfMapTest, mapIsEmpty) {
Maciej Żenczykowski7c9a9842020-01-20 15:51:31 -0800204 BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700205 expectMapEmpty(testMap);
206 uint32_t key = TEST_KEY1;
207 uint32_t value_write = TEST_VALUE1;
208 writeToMapAndCheck(testMap, key, value_write);
Steven Morelande7cd2a72020-01-10 17:49:35 -0800209 Result<bool> isEmpty = testMap.isEmpty();
Bernie Innocenti43d25382020-02-10 07:25:16 +0900210 ASSERT_RESULT_OK(isEmpty);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700211 ASSERT_FALSE(isEmpty.value());
Bernie Innocenti43d25382020-02-10 07:25:16 +0900212 ASSERT_RESULT_OK(testMap.deleteValue(key));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700213 ASSERT_GT(0, findMapEntry(testMap.getMap(), &key, &value_write));
214 ASSERT_EQ(ENOENT, errno);
215 expectMapEmpty(testMap);
216 int entriesSeen = 0;
Bernie Innocenti43d25382020-02-10 07:25:16 +0900217 EXPECT_RESULT_OK(testMap.iterate(
Steven Morelande7cd2a72020-01-10 17:49:35 -0800218 [&entriesSeen](const unsigned int&,
219 const BpfMap<unsigned int, unsigned int>&) -> Result<void> {
220 entriesSeen++;
221 return {};
222 }));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700223 EXPECT_EQ(0, entriesSeen);
Bernie Innocenti43d25382020-02-10 07:25:16 +0900224 EXPECT_RESULT_OK(testMap.iterateWithValue(
Steven Morelande7cd2a72020-01-10 17:49:35 -0800225 [&entriesSeen](const unsigned int&, const unsigned int&,
226 const BpfMap<unsigned int, unsigned int>&) -> Result<void> {
227 entriesSeen++;
228 return {};
229 }));
Chenbo Feng75b410b2018-10-10 15:01:19 -0700230 EXPECT_EQ(0, entriesSeen);
231}
232
233TEST_F(BpfMapTest, mapClear) {
Maciej Żenczykowski7c9a9842020-01-20 15:51:31 -0800234 BpfMap<uint32_t, uint32_t> testMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, BPF_F_NO_PREALLOC);
Chenbo Feng75b410b2018-10-10 15:01:19 -0700235 populateMap(TEST_MAP_SIZE, testMap);
Steven Morelande7cd2a72020-01-10 17:49:35 -0800236 Result<bool> isEmpty = testMap.isEmpty();
Bernie Innocenti43d25382020-02-10 07:25:16 +0900237 ASSERT_RESULT_OK(isEmpty);
Steven Morelande7cd2a72020-01-10 17:49:35 -0800238 ASSERT_FALSE(*isEmpty);
Bernie Innocenti43d25382020-02-10 07:25:16 +0900239 ASSERT_RESULT_OK(testMap.clear());
Chenbo Feng75b410b2018-10-10 15:01:19 -0700240 expectMapEmpty(testMap);
241}
242
243} // namespace bpf
244} // namespace android