blob: 1e9ec8c5174a8d3a2187c69463a75376ebc058a6 [file] [log] [blame]
Chenbo Fengdc4e3252017-12-22 11:00:52 -08001/*
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
36#include <netdutils/MockSyscalls.h>
37#include "bpf/BpfNetworkStats.h"
38#include "bpf/BpfUtils.h"
39
40using namespace android::bpf;
41
42using ::testing::_;
43using ::testing::ByMove;
44using ::testing::Invoke;
45using ::testing::Return;
46using ::testing::StrictMock;
47using ::testing::Test;
48
49namespace android {
50namespace bpf {
51
52using base::unique_fd;
53using netdutils::status::ok;
54
55constexpr int TEST_MAP_SIZE = 10;
56constexpr uid_t TEST_UID1 = 10086;
57constexpr uid_t TEST_UID2 = 12345;
58constexpr uint32_t TEST_TAG = 42;
59constexpr int TEST_COUNTERSET0 = 0;
60constexpr int TEST_COUNTERSET1 = 1;
Chenbo Fengdc4e3252017-12-22 11:00:52 -080061constexpr const int COUNTERSETS_LIMIT = 2;
62constexpr uint64_t TEST_BYTES0 = 1000;
63constexpr uint64_t TEST_BYTES1 = 2000;
Chenbo Fengdc4e3252017-12-22 11:00:52 -080064constexpr uint64_t TEST_PACKET0 = 100;
65constexpr uint64_t TEST_PACKET1 = 200;
Chenbo Feng33a4de12018-03-16 18:10:07 -070066constexpr const char* IFACE_NAME1 = "lo";
67constexpr const char* IFACE_NAME2 = "wlan0";
68constexpr const char* IFACE_NAME3 = "rmnet_data0";
69constexpr uint32_t IFACE_INDEX1 = 1;
70constexpr uint32_t IFACE_INDEX2 = 2;
71constexpr uint32_t IFACE_INDEX3 = 3;
Chenbo Feng7e974052018-02-28 22:57:21 -080072constexpr uint32_t UNKNOWN_IFACE = 0;
Chenbo Fengdc4e3252017-12-22 11:00:52 -080073
74class BpfNetworkStatsHelperTest : public testing::Test {
75 protected:
76 BpfNetworkStatsHelperTest() {}
77 unique_fd mFakeCookieTagMap;
78 unique_fd mFakeUidStatsMap;
79 unique_fd mFakeTagStatsMap;
Chenbo Feng7e974052018-02-28 22:57:21 -080080 unique_fd mFakeIfaceIndexNameMap;
Chenbo Feng33a4de12018-03-16 18:10:07 -070081 unique_fd mFakeIfaceStatsMap;
Chenbo Fengdc4e3252017-12-22 11:00:52 -080082
83 void SetUp() {
84 mFakeCookieTagMap = unique_fd(createMap(BPF_MAP_TYPE_HASH, sizeof(uint64_t),
85 sizeof(struct UidTag), TEST_MAP_SIZE, 0));
86 ASSERT_LE(0, mFakeCookieTagMap);
87
88 mFakeUidStatsMap = unique_fd(createMap(BPF_MAP_TYPE_HASH, sizeof(struct StatsKey),
89 sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
90 ASSERT_LE(0, mFakeUidStatsMap);
91
92 mFakeTagStatsMap = unique_fd(createMap(BPF_MAP_TYPE_HASH, sizeof(struct StatsKey),
93 sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
94 ASSERT_LE(0, mFakeTagStatsMap);
Chenbo Feng7e974052018-02-28 22:57:21 -080095
96 mFakeIfaceIndexNameMap =
97 unique_fd(createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), IFNAMSIZ, TEST_MAP_SIZE, 0));
98 ASSERT_LE(0, mFakeIfaceIndexNameMap);
Chenbo Feng33a4de12018-03-16 18:10:07 -070099
100 mFakeIfaceStatsMap = unique_fd(createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t),
101 sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
102 ASSERT_LE(0, mFakeIfaceStatsMap);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800103 }
104
105 void TearDown() {
106 mFakeCookieTagMap.reset();
107 mFakeUidStatsMap.reset();
108 mFakeTagStatsMap.reset();
Chenbo Feng33a4de12018-03-16 18:10:07 -0700109 mFakeIfaceIndexNameMap.reset();
110 mFakeIfaceStatsMap.reset();
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800111 }
112
113 void expectUidTag(uint64_t cookie, uid_t uid, uint32_t tag) {
114 struct UidTag tagResult;
115 EXPECT_EQ(0, findMapEntry(mFakeCookieTagMap, &cookie, &tagResult));
116 EXPECT_EQ(uid, tagResult.uid);
117 EXPECT_EQ(tag, tagResult.tag);
118 }
119
120 void populateFakeStats(uid_t uid, uint32_t tag, uint32_t ifaceIndex, uint32_t counterSet,
121 StatsValue* value, const base::unique_fd& map_fd) {
122 StatsKey key = {
123 .uid = (uint32_t)uid, .tag = tag, .counterSet = counterSet, .ifaceIndex = ifaceIndex};
124 EXPECT_EQ(0, writeToMapEntry(map_fd, &key, value, BPF_ANY));
125 }
Chenbo Feng7e974052018-02-28 22:57:21 -0800126
Chenbo Feng33a4de12018-03-16 18:10:07 -0700127 void updateIfaceMap(const char* ifaceName, uint32_t ifaceIndex) {
Chenbo Feng7e974052018-02-28 22:57:21 -0800128 char iface[IFNAMSIZ];
129 strlcpy(iface, ifaceName, IFNAMSIZ);
130 EXPECT_EQ(0, writeToMapEntry(mFakeIfaceIndexNameMap, &ifaceIndex, iface, BPF_ANY));
Chenbo Feng33a4de12018-03-16 18:10:07 -0700131 }
132
133 void expectStatsEqual(const StatsValue& target, const Stats& result) {
134 EXPECT_EQ(target.rxPackets, result.rxPackets);
135 EXPECT_EQ(target.rxBytes, result.rxBytes);
136 EXPECT_EQ(target.txPackets, result.txPackets);
137 EXPECT_EQ(target.txBytes, result.txBytes);
138 }
139
140 void expectStatsLineEqual(const StatsValue target, const char* iface, uint32_t uid,
141 int counterSet, uint32_t tag, const stats_line& result) {
142 EXPECT_EQ(0, strcmp(iface, result.iface));
143 EXPECT_EQ(uid, (uint32_t)result.uid);
144 EXPECT_EQ(counterSet, result.set);
145 EXPECT_EQ(tag, (uint32_t)result.tag);
146 EXPECT_EQ(target.rxPackets, (uint64_t)result.rxPackets);
147 EXPECT_EQ(target.rxBytes, (uint64_t)result.rxBytes);
148 EXPECT_EQ(target.txPackets, (uint64_t)result.txPackets);
149 EXPECT_EQ(target.txBytes, (uint64_t)result.txBytes);
Chenbo Feng7e974052018-02-28 22:57:21 -0800150 }
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800151};
152
153// TEST to verify the behavior of bpf map when cocurrent deletion happens when
154// iterating the same map.
155TEST_F(BpfNetworkStatsHelperTest, TestIterateMapWithDeletion) {
Chenbo Feng837ddfc2018-05-08 13:45:08 -0700156 SKIP_IF_BPF_NOT_SUPPORTED;
157
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800158 for (int i = 0; i < 5; i++) {
159 uint64_t cookie = i + 1;
160 struct UidTag tag = {.uid = TEST_UID1, .tag = TEST_TAG};
161 EXPECT_EQ(0, writeToMapEntry(mFakeCookieTagMap, &cookie, &tag, BPF_ANY));
162 }
163 uint64_t curCookie = 0;
164 uint64_t nextCookie = 0;
165 struct UidTag tagResult;
166 EXPECT_EQ(0, getNextMapKey(mFakeCookieTagMap, &curCookie, &nextCookie));
167 uint64_t headOfMap = nextCookie;
168 curCookie = nextCookie;
169 // Find the second entry in the map, then immediately delete it.
170 EXPECT_EQ(0, getNextMapKey(mFakeCookieTagMap, &curCookie, &nextCookie));
171 EXPECT_EQ(0, deleteMapEntry(mFakeCookieTagMap, &nextCookie));
172 // Find the entry that is now immediately after headOfMap, then delete that.
173 EXPECT_EQ(0, getNextMapKey(mFakeCookieTagMap, &curCookie, &nextCookie));
174 EXPECT_EQ(0, deleteMapEntry(mFakeCookieTagMap, &nextCookie));
175 // Attempting to read an entry that has been deleted fails with ENOENT.
176 curCookie = nextCookie;
177 EXPECT_EQ(-1, findMapEntry(mFakeCookieTagMap, &curCookie, &tagResult));
178 EXPECT_EQ(ENOENT, errno);
179 // Finding the entry after our deleted entry restarts iteration from the beginning of the map.
180 EXPECT_EQ(0, getNextMapKey(mFakeCookieTagMap, &curCookie, &nextCookie));
181 EXPECT_EQ(headOfMap, nextCookie);
182}
183
Chenbo Fengc3bfd3e2018-04-24 11:50:02 -0700184TEST_F(BpfNetworkStatsHelperTest, TestBpfIterateMap) {
185 SKIP_IF_BPF_NOT_SUPPORTED;
186
187 for (int i = 0; i < 5; i++) {
188 uint64_t cookie = i + 1;
189 struct UidTag tag = {.uid = TEST_UID1, .tag = TEST_TAG};
190 EXPECT_EQ(0, writeToMapEntry(mFakeCookieTagMap, &cookie, &tag, BPF_ANY));
191 }
192 int totalCount = 0;
193 int totalSum = 0;
194 uint64_t dummyCookie;
195 auto iterateMapWithoutDeletion = [&totalCount, &totalSum](void* key, const base::unique_fd&) {
196 uint64_t cookie = *(uint64_t*)key;
197 EXPECT_GE((uint64_t)5, cookie);
198 totalCount++;
199 totalSum += cookie;
200 return BPF_CONTINUE;
201 };
202 EXPECT_EQ(0, bpfIterateMap(dummyCookie, mFakeCookieTagMap, iterateMapWithoutDeletion));
203 EXPECT_EQ(5, totalCount);
204 EXPECT_EQ(1 + 2 + 3 + 4 + 5, totalSum);
205}
206
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800207TEST_F(BpfNetworkStatsHelperTest, TestGetUidStatsTotal) {
Chenbo Feng837ddfc2018-05-08 13:45:08 -0700208 SKIP_IF_BPF_NOT_SUPPORTED;
209
Chenbo Feng33a4de12018-03-16 18:10:07 -0700210 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
Chenbo Fengeac6c472018-02-05 15:06:23 -0800211 StatsValue value1 = {.rxBytes = TEST_BYTES0,
212 .rxPackets = TEST_PACKET0,
213 .txBytes = TEST_BYTES1,
214 .txPackets = TEST_PACKET1,};
Chenbo Feng33a4de12018-03-16 18:10:07 -0700215 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, &value1, mFakeUidStatsMap);
216 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET1, &value1, mFakeUidStatsMap);
217 populateFakeStats(TEST_UID2, 0, IFACE_INDEX1, TEST_COUNTERSET1, &value1, mFakeUidStatsMap);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800218 Stats result1 = {};
219 ASSERT_EQ(0, bpfGetUidStatsInternal(TEST_UID1, &result1, mFakeUidStatsMap));
Chenbo Feng33a4de12018-03-16 18:10:07 -0700220 StatsValue uid1Value = {
221 .rxBytes = TEST_BYTES0 * 2,
222 .rxPackets = TEST_PACKET0 * 2,
223 .txBytes = TEST_BYTES1 * 2,
224 .txPackets = TEST_PACKET1 * 2,
225 };
226 expectStatsEqual(uid1Value, result1);
227
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800228 Stats result2 = {};
229 ASSERT_EQ(0, bpfGetUidStatsInternal(TEST_UID2, &result2, mFakeUidStatsMap));
Chenbo Feng33a4de12018-03-16 18:10:07 -0700230 expectStatsEqual(value1, result2);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800231 std::vector<stats_line> lines;
232 std::vector<std::string> ifaces;
Chenbo Feng16513482018-03-15 17:59:58 -0700233 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
234 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800235 ASSERT_EQ((unsigned long)2, lines.size());
236 lines.clear();
Chenbo Feng16513482018-03-15 17:59:58 -0700237 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
238 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800239 ASSERT_EQ((unsigned long)1, lines.size());
Chenbo Feng33a4de12018-03-16 18:10:07 -0700240 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET1, 0, lines.front());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800241}
242
243TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsInternal) {
Chenbo Feng837ddfc2018-05-08 13:45:08 -0700244 SKIP_IF_BPF_NOT_SUPPORTED;
245
Chenbo Feng33a4de12018-03-16 18:10:07 -0700246 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
247 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
248 updateIfaceMap(IFACE_NAME3, IFACE_INDEX3);
249 StatsValue value1 = {
250 .rxBytes = TEST_BYTES0,
251 .rxPackets = TEST_PACKET0,
252 .txBytes = TEST_BYTES1,
253 .txPackets = TEST_PACKET1,
254 };
255 StatsValue value2 = {
256 .rxBytes = TEST_BYTES1,
257 .rxPackets = TEST_PACKET1,
258 .txBytes = TEST_BYTES0,
259 .txPackets = TEST_PACKET0,
260 };
261 uint32_t ifaceStatsKey = IFACE_INDEX1;
262 EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value1, BPF_ANY));
263 ifaceStatsKey = IFACE_INDEX2;
264 EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value2, BPF_ANY));
265 ifaceStatsKey = IFACE_INDEX3;
266 EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value1, BPF_ANY));
267
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800268 Stats result1 = {};
Chenbo Feng33a4de12018-03-16 18:10:07 -0700269 ASSERT_EQ(0, bpfGetIfaceStatsInternal(IFACE_NAME1, &result1, mFakeIfaceStatsMap,
270 mFakeIfaceIndexNameMap));
271 expectStatsEqual(value1, result1);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800272 Stats result2 = {};
Chenbo Feng33a4de12018-03-16 18:10:07 -0700273 ASSERT_EQ(0, bpfGetIfaceStatsInternal(IFACE_NAME2, &result2, mFakeIfaceStatsMap,
274 mFakeIfaceIndexNameMap));
275 expectStatsEqual(value2, result2);
276 Stats totalResult = {};
277 ASSERT_EQ(0, bpfGetIfaceStatsInternal(NULL, &totalResult, mFakeIfaceStatsMap,
278 mFakeIfaceIndexNameMap));
279 StatsValue totalValue = {
280 .rxBytes = TEST_BYTES0 * 2 + TEST_BYTES1,
281 .rxPackets = TEST_PACKET0 * 2 + TEST_PACKET1,
282 .txBytes = TEST_BYTES1 * 2 + TEST_BYTES0,
283 .txPackets = TEST_PACKET1 * 2 + TEST_PACKET0,
284 };
285 expectStatsEqual(totalValue, totalResult);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800286}
287
288TEST_F(BpfNetworkStatsHelperTest, TestGetStatsDetail) {
Chenbo Feng837ddfc2018-05-08 13:45:08 -0700289 SKIP_IF_BPF_NOT_SUPPORTED;
290
Chenbo Feng33a4de12018-03-16 18:10:07 -0700291 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
292 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
Chenbo Fengeac6c472018-02-05 15:06:23 -0800293 StatsValue value1 = {.rxBytes = TEST_BYTES0,
294 .rxPackets = TEST_PACKET0,
295 .txBytes = TEST_BYTES1,
296 .txPackets = TEST_PACKET1,};
Chenbo Feng33a4de12018-03-16 18:10:07 -0700297 populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, &value1,
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800298 mFakeTagStatsMap);
Chenbo Feng33a4de12018-03-16 18:10:07 -0700299 populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, &value1,
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800300 mFakeTagStatsMap);
Chenbo Feng33a4de12018-03-16 18:10:07 -0700301 populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, &value1,
302 mFakeTagStatsMap);
303 populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, &value1,
304 mFakeTagStatsMap);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800305 std::vector<stats_line> lines;
306 std::vector<std::string> ifaces;
Chenbo Feng16513482018-03-15 17:59:58 -0700307 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
308 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng33a4de12018-03-16 18:10:07 -0700309 ASSERT_EQ((unsigned long)4, lines.size());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800310 lines.clear();
Chenbo Feng16513482018-03-15 17:59:58 -0700311 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
312 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng33a4de12018-03-16 18:10:07 -0700313 ASSERT_EQ((unsigned long)3, lines.size());
314 lines.clear();
315 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
316 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800317 ASSERT_EQ((unsigned long)2, lines.size());
318 lines.clear();
Chenbo Feng33a4de12018-03-16 18:10:07 -0700319 ifaces.push_back(std::string(IFACE_NAME1));
Chenbo Feng16513482018-03-15 17:59:58 -0700320 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
321 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng7e974052018-02-28 22:57:21 -0800322 ASSERT_EQ((unsigned long)1, lines.size());
Chenbo Feng33a4de12018-03-16 18:10:07 -0700323 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines.front());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800324}
325
326TEST_F(BpfNetworkStatsHelperTest, TestGetStatsWithSkippedIface) {
Chenbo Feng837ddfc2018-05-08 13:45:08 -0700327 SKIP_IF_BPF_NOT_SUPPORTED;
328
Chenbo Feng33a4de12018-03-16 18:10:07 -0700329 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
330 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
Chenbo Fengeac6c472018-02-05 15:06:23 -0800331 StatsValue value1 = {.rxBytes = TEST_BYTES0,
332 .rxPackets = TEST_PACKET0,
333 .txBytes = TEST_BYTES1,
334 .txPackets = TEST_PACKET1,};
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800335 populateFakeStats(0, 0, 0, COUNTERSETS_LIMIT, &value1, mFakeUidStatsMap);
Chenbo Feng33a4de12018-03-16 18:10:07 -0700336 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, &value1, mFakeUidStatsMap);
337 populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, &value1, mFakeUidStatsMap);
338 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET1, &value1, mFakeUidStatsMap);
339 populateFakeStats(TEST_UID2, 0, IFACE_INDEX1, TEST_COUNTERSET0, &value1, mFakeUidStatsMap);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800340 std::vector<stats_line> lines;
341 std::vector<std::string> ifaces;
Chenbo Feng16513482018-03-15 17:59:58 -0700342 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
343 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng33a4de12018-03-16 18:10:07 -0700344 ASSERT_EQ((unsigned long)4, lines.size());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800345 lines.clear();
Chenbo Feng16513482018-03-15 17:59:58 -0700346 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
347 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng33a4de12018-03-16 18:10:07 -0700348 ASSERT_EQ((unsigned long)3, lines.size());
Chenbo Feng7e974052018-02-28 22:57:21 -0800349 lines.clear();
Chenbo Feng16513482018-03-15 17:59:58 -0700350 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
351 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800352 ASSERT_EQ((unsigned long)1, lines.size());
Chenbo Feng33a4de12018-03-16 18:10:07 -0700353 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, 0, lines.front());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800354 lines.clear();
Chenbo Feng33a4de12018-03-16 18:10:07 -0700355 ifaces.push_back(std::string(IFACE_NAME1));
Chenbo Feng16513482018-03-15 17:59:58 -0700356 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
357 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800358 ASSERT_EQ((unsigned long)2, lines.size());
359}
360
Chenbo Feng7e974052018-02-28 22:57:21 -0800361TEST_F(BpfNetworkStatsHelperTest, TestUnkownIfaceError) {
Chenbo Feng837ddfc2018-05-08 13:45:08 -0700362 SKIP_IF_BPF_NOT_SUPPORTED;
363
Chenbo Feng33a4de12018-03-16 18:10:07 -0700364 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
Chenbo Feng7e974052018-02-28 22:57:21 -0800365 StatsValue value1 = {.rxBytes = TEST_BYTES0 * 20,
366 .rxPackets = TEST_PACKET0,
367 .txBytes = TEST_BYTES1 * 20,
368 .txPackets = TEST_PACKET1,};
369 uint32_t ifaceIndex = UNKNOWN_IFACE;
370 populateFakeStats(TEST_UID1, 0, ifaceIndex, TEST_COUNTERSET0, &value1, mFakeUidStatsMap);
Chenbo Feng33a4de12018-03-16 18:10:07 -0700371 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, &value1, mFakeUidStatsMap);
372 StatsValue value2 = {.rxBytes = TEST_BYTES0 * 40,
373 .rxPackets = TEST_PACKET0,
374 .txBytes = TEST_BYTES1 * 40,
375 .txPackets = TEST_PACKET1,};
376 populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, &value2, mFakeUidStatsMap);
Chenbo Feng7e974052018-02-28 22:57:21 -0800377 StatsKey curKey = {.uid = TEST_UID1,
378 .tag = 0,
379 .ifaceIndex = ifaceIndex,
380 .counterSet = TEST_COUNTERSET0};
381 char ifname[IFNAMSIZ];
Chenbo Feng33a4de12018-03-16 18:10:07 -0700382 int64_t unknownIfaceBytesTotal = 0;
383 ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeUidStatsMap, ifaceIndex,
384 ifname, &curKey, &unknownIfaceBytesTotal));
385 ASSERT_EQ(((int64_t)(TEST_BYTES0 * 20 + TEST_BYTES1 * 20)), unknownIfaceBytesTotal);
386 curKey.ifaceIndex = IFACE_INDEX2;
387 ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeUidStatsMap, ifaceIndex,
388 ifname, &curKey, &unknownIfaceBytesTotal));
389 ASSERT_EQ(-1, unknownIfaceBytesTotal);
390 std::vector<stats_line> lines;
391 std::vector<std::string> ifaces;
392 // TODO: find a way to test the total of unknown Iface Bytes go above limit.
393 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
394 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
395 ASSERT_EQ((unsigned long)1, lines.size());
396 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines.front());
Chenbo Feng7e974052018-02-28 22:57:21 -0800397}
398
Chenbo Fengf4b812d2018-04-18 15:27:19 -0700399TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsDetail) {
Chenbo Feng837ddfc2018-05-08 13:45:08 -0700400 SKIP_IF_BPF_NOT_SUPPORTED;
401
Chenbo Fengf4b812d2018-04-18 15:27:19 -0700402 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
403 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
404 updateIfaceMap(IFACE_NAME3, IFACE_INDEX3);
405 StatsValue value1 = {
406 .rxBytes = TEST_BYTES0,
407 .rxPackets = TEST_PACKET0,
408 .txBytes = TEST_BYTES1,
409 .txPackets = TEST_PACKET1,
410 };
411 StatsValue value2 = {
412 .rxBytes = TEST_BYTES1,
413 .rxPackets = TEST_PACKET1,
414 .txBytes = TEST_BYTES0,
415 .txPackets = TEST_PACKET0,
416 };
417 uint32_t ifaceStatsKey = IFACE_INDEX1;
418 EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value1, BPF_ANY));
419 ifaceStatsKey = IFACE_INDEX2;
420 EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value2, BPF_ANY));
421 ifaceStatsKey = IFACE_INDEX3;
422 EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value1, BPF_ANY));
423 std::vector<stats_line> lines;
424 ASSERT_EQ(0,
425 parseBpfNetworkStatsDevInternal(&lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
426 ASSERT_EQ((unsigned long)3, lines.size());
427 std::sort(lines.begin(), lines.end(), [](const auto& line1, const auto& line2)-> bool {
428 return strcmp(line1.iface, line2.iface) < 0;
429 });
430 expectStatsLineEqual(value1, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
431 expectStatsLineEqual(value1, IFACE_NAME3, UID_ALL, SET_ALL, TAG_NONE, lines[1]);
432 expectStatsLineEqual(value2, IFACE_NAME2, UID_ALL, SET_ALL, TAG_NONE, lines[2]);
433}
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800434} // namespace bpf
435} // namespace android