blob: c7d66fb0d135ea90b3840cba559c439ddecdb407 [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>
Chenbo Feng2c67f262018-04-26 10:37:55 -070037#include "bpf/BpfMap.h"
Chenbo Fengdc4e3252017-12-22 11:00:52 -080038#include "bpf/BpfNetworkStats.h"
39#include "bpf/BpfUtils.h"
40
41using namespace android::bpf;
42
43using ::testing::_;
44using ::testing::ByMove;
45using ::testing::Invoke;
46using ::testing::Return;
47using ::testing::StrictMock;
48using ::testing::Test;
49
50namespace android {
51namespace bpf {
52
53using base::unique_fd;
Chenbo Fengdc4e3252017-12-22 11:00:52 -080054
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 uint64_t TEST_BYTES0 = 1000;
62constexpr uint64_t TEST_BYTES1 = 2000;
Chenbo Fengdc4e3252017-12-22 11:00:52 -080063constexpr uint64_t TEST_PACKET0 = 100;
64constexpr uint64_t TEST_PACKET1 = 200;
Chenbo Feng2c67f262018-04-26 10:37:55 -070065constexpr const char IFACE_NAME1[] = "lo";
66constexpr const char IFACE_NAME2[] = "wlan0";
67constexpr const char IFACE_NAME3[] = "rmnet_data0";
Chenbo Feng58a09b52018-05-11 19:15:15 -070068// A iface name that the size is bigger then IFNAMSIZ
69constexpr const char LONG_IFACE_NAME[] = "wlanWithALongName";
70constexpr const char TRUNCATED_IFACE_NAME[] = "wlanWithALongNa";
Chenbo Feng3c69a392018-03-16 18:10:07 -070071constexpr uint32_t IFACE_INDEX1 = 1;
72constexpr uint32_t IFACE_INDEX2 = 2;
73constexpr uint32_t IFACE_INDEX3 = 3;
Chenbo Feng58a09b52018-05-11 19:15:15 -070074constexpr uint32_t IFACE_INDEX4 = 4;
Chenbo Feng8cc480c2018-02-28 22:57:21 -080075constexpr uint32_t UNKNOWN_IFACE = 0;
Chenbo Fengdc4e3252017-12-22 11:00:52 -080076
77class BpfNetworkStatsHelperTest : public testing::Test {
78 protected:
79 BpfNetworkStatsHelperTest() {}
Chenbo Feng2c67f262018-04-26 10:37:55 -070080 BpfMap<uint64_t, UidTag> mFakeCookieTagMap;
Chenbo Feng58a09b52018-05-11 19:15:15 -070081 BpfMap<uint32_t, StatsValue> mFakeAppUidStatsMap;
Chenbo Feng2c67f262018-04-26 10:37:55 -070082 BpfMap<StatsKey, StatsValue> mFakeUidStatsMap;
83 BpfMap<StatsKey, StatsValue> mFakeTagStatsMap;
84 BpfMap<uint32_t, IfaceValue> mFakeIfaceIndexNameMap;
85 BpfMap<uint32_t, StatsValue> mFakeIfaceStatsMap;
Chenbo Fengdc4e3252017-12-22 11:00:52 -080086
87 void SetUp() {
Chenbo Feng2c67f262018-04-26 10:37:55 -070088 mFakeCookieTagMap = BpfMap<uint64_t, UidTag>(createMap(
89 BPF_MAP_TYPE_HASH, sizeof(uint64_t), sizeof(struct UidTag), TEST_MAP_SIZE, 0));
90 ASSERT_LE(0, mFakeCookieTagMap.getMap());
Chenbo Fengdc4e3252017-12-22 11:00:52 -080091
Chenbo Feng58a09b52018-05-11 19:15:15 -070092 mFakeAppUidStatsMap = BpfMap<uint32_t, StatsValue>(createMap(
93 BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
94 ASSERT_LE(0, mFakeAppUidStatsMap.getMap());
95
Chenbo Feng2c67f262018-04-26 10:37:55 -070096 mFakeUidStatsMap =
97 BpfMap<StatsKey, StatsValue>(createMap(BPF_MAP_TYPE_HASH, sizeof(struct StatsKey),
98 sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
99 ASSERT_LE(0, mFakeUidStatsMap.getMap());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800100
Chenbo Feng2c67f262018-04-26 10:37:55 -0700101 mFakeTagStatsMap =
102 BpfMap<StatsKey, StatsValue>(createMap(BPF_MAP_TYPE_HASH, sizeof(struct StatsKey),
103 sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
104 ASSERT_LE(0, mFakeTagStatsMap.getMap());
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800105
Chenbo Feng2c67f262018-04-26 10:37:55 -0700106 mFakeIfaceIndexNameMap = BpfMap<uint32_t, IfaceValue>(
107 createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(IfaceValue), TEST_MAP_SIZE, 0));
108 ASSERT_LE(0, mFakeIfaceIndexNameMap.getMap());
Chenbo Feng3c69a392018-03-16 18:10:07 -0700109
Chenbo Feng2c67f262018-04-26 10:37:55 -0700110 mFakeIfaceStatsMap = BpfMap<uint32_t, StatsValue>(createMap(
111 BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
112 ASSERT_LE(0, mFakeIfaceStatsMap.getMap());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800113 }
114
115 void expectUidTag(uint64_t cookie, uid_t uid, uint32_t tag) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700116 auto tagResult = mFakeCookieTagMap.readValue(cookie);
117 EXPECT_TRUE(isOk(tagResult));
118 EXPECT_EQ(uid, tagResult.value().uid);
119 EXPECT_EQ(tag, tagResult.value().tag);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800120 }
121
122 void populateFakeStats(uid_t uid, uint32_t tag, uint32_t ifaceIndex, uint32_t counterSet,
Chenbo Feng2c67f262018-04-26 10:37:55 -0700123 StatsValue value, BpfMap<StatsKey, StatsValue>& map) {
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800124 StatsKey key = {
125 .uid = (uint32_t)uid, .tag = tag, .counterSet = counterSet, .ifaceIndex = ifaceIndex};
Chenbo Feng2c67f262018-04-26 10:37:55 -0700126 EXPECT_TRUE(isOk(map.writeValue(key, value, BPF_ANY)));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800127 }
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800128
Chenbo Feng3c69a392018-03-16 18:10:07 -0700129 void updateIfaceMap(const char* ifaceName, uint32_t ifaceIndex) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700130 IfaceValue iface;
131 strlcpy(iface.name, ifaceName, IFNAMSIZ);
132 EXPECT_TRUE(isOk(mFakeIfaceIndexNameMap.writeValue(ifaceIndex, iface, BPF_ANY)));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700133 }
134
135 void expectStatsEqual(const StatsValue& target, const Stats& result) {
136 EXPECT_EQ(target.rxPackets, result.rxPackets);
137 EXPECT_EQ(target.rxBytes, result.rxBytes);
138 EXPECT_EQ(target.txPackets, result.txPackets);
139 EXPECT_EQ(target.txBytes, result.txBytes);
140 }
141
142 void expectStatsLineEqual(const StatsValue target, const char* iface, uint32_t uid,
143 int counterSet, uint32_t tag, const stats_line& result) {
144 EXPECT_EQ(0, strcmp(iface, result.iface));
145 EXPECT_EQ(uid, (uint32_t)result.uid);
junyulaiaa7a4742018-11-13 10:12:46 +0800146 EXPECT_EQ((uint32_t) counterSet, result.set);
Chenbo Feng3c69a392018-03-16 18:10:07 -0700147 EXPECT_EQ(tag, (uint32_t)result.tag);
148 EXPECT_EQ(target.rxPackets, (uint64_t)result.rxPackets);
149 EXPECT_EQ(target.rxBytes, (uint64_t)result.rxBytes);
150 EXPECT_EQ(target.txPackets, (uint64_t)result.txPackets);
151 EXPECT_EQ(target.txBytes, (uint64_t)result.txBytes);
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800152 }
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800153};
154
155// TEST to verify the behavior of bpf map when cocurrent deletion happens when
156// iterating the same map.
157TEST_F(BpfNetworkStatsHelperTest, TestIterateMapWithDeletion) {
Chenbo Fengcc6cbb72018-05-08 13:45:08 -0700158 SKIP_IF_BPF_NOT_SUPPORTED;
159
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800160 for (int i = 0; i < 5; i++) {
161 uint64_t cookie = i + 1;
162 struct UidTag tag = {.uid = TEST_UID1, .tag = TEST_TAG};
Chenbo Feng2c67f262018-04-26 10:37:55 -0700163 EXPECT_TRUE(isOk(mFakeCookieTagMap.writeValue(cookie, tag, BPF_ANY)));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800164 }
165 uint64_t curCookie = 0;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700166 auto nextCookie = mFakeCookieTagMap.getNextKey(curCookie);
167 EXPECT_TRUE(isOk(nextCookie));
168 uint64_t headOfMap = nextCookie.value();
169 curCookie = nextCookie.value();
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800170 // Find the second entry in the map, then immediately delete it.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700171 nextCookie = mFakeCookieTagMap.getNextKey(curCookie);
172 EXPECT_TRUE(isOk(nextCookie));
173 EXPECT_TRUE(isOk(mFakeCookieTagMap.deleteValue((nextCookie.value()))));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800174 // Find the entry that is now immediately after headOfMap, then delete that.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700175 nextCookie = mFakeCookieTagMap.getNextKey(curCookie);
176 EXPECT_TRUE(isOk(nextCookie));
177 EXPECT_TRUE(isOk(mFakeCookieTagMap.deleteValue((nextCookie.value()))));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800178 // Attempting to read an entry that has been deleted fails with ENOENT.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700179 curCookie = nextCookie.value();
180 auto tagResult = mFakeCookieTagMap.readValue(curCookie);
181 EXPECT_EQ(ENOENT, tagResult.status().code());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800182 // Finding the entry after our deleted entry restarts iteration from the beginning of the map.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700183 nextCookie = mFakeCookieTagMap.getNextKey(curCookie);
184 EXPECT_TRUE(isOk(nextCookie));
185 EXPECT_EQ(headOfMap, nextCookie.value());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800186}
187
Chenbo Feng29503212018-04-24 11:50:02 -0700188TEST_F(BpfNetworkStatsHelperTest, TestBpfIterateMap) {
189 SKIP_IF_BPF_NOT_SUPPORTED;
190
191 for (int i = 0; i < 5; i++) {
192 uint64_t cookie = i + 1;
193 struct UidTag tag = {.uid = TEST_UID1, .tag = TEST_TAG};
Chenbo Feng2c67f262018-04-26 10:37:55 -0700194 EXPECT_TRUE(isOk(mFakeCookieTagMap.writeValue(cookie, tag, BPF_ANY)));
Chenbo Feng29503212018-04-24 11:50:02 -0700195 }
196 int totalCount = 0;
197 int totalSum = 0;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700198 const auto iterateWithoutDeletion = [&totalCount, &totalSum](const uint64_t& key,
199 const BpfMap<uint64_t, UidTag>&) {
200 EXPECT_GE((uint64_t)5, key);
Chenbo Feng29503212018-04-24 11:50:02 -0700201 totalCount++;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700202 totalSum += key;
203 return netdutils::status::ok;
Chenbo Feng29503212018-04-24 11:50:02 -0700204 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700205 EXPECT_TRUE(isOk(mFakeCookieTagMap.iterate(iterateWithoutDeletion)));
Chenbo Feng29503212018-04-24 11:50:02 -0700206 EXPECT_EQ(5, totalCount);
207 EXPECT_EQ(1 + 2 + 3 + 4 + 5, totalSum);
208}
209
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800210TEST_F(BpfNetworkStatsHelperTest, TestGetUidStatsTotal) {
Chenbo Fengcc6cbb72018-05-08 13:45:08 -0700211 SKIP_IF_BPF_NOT_SUPPORTED;
212
Chenbo Feng3c69a392018-03-16 18:10:07 -0700213 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
Chenbo Feng2c67f262018-04-26 10:37:55 -0700214 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
215 updateIfaceMap(IFACE_NAME3, IFACE_INDEX3);
Chenbo Fengeac6c472018-02-05 15:06:23 -0800216 StatsValue value1 = {.rxBytes = TEST_BYTES0,
217 .rxPackets = TEST_PACKET0,
218 .txBytes = TEST_BYTES1,
219 .txPackets = TEST_PACKET1,};
Chenbo Feng58a09b52018-05-11 19:15:15 -0700220 StatsValue value2 = {
Chenbo Feng3c69a392018-03-16 18:10:07 -0700221 .rxBytes = TEST_BYTES0 * 2,
222 .rxPackets = TEST_PACKET0 * 2,
223 .txBytes = TEST_BYTES1 * 2,
224 .txPackets = TEST_PACKET1 * 2,
225 };
Chenbo Feng58a09b52018-05-11 19:15:15 -0700226 ASSERT_TRUE(isOk(mFakeAppUidStatsMap.writeValue(TEST_UID1, value1, BPF_ANY)));
227 ASSERT_TRUE(isOk(mFakeAppUidStatsMap.writeValue(TEST_UID2, value2, BPF_ANY)));
228 Stats result1 = {};
229 ASSERT_EQ(0, bpfGetUidStatsInternal(TEST_UID1, &result1, mFakeAppUidStatsMap));
230 expectStatsEqual(value1, result1);
Chenbo Feng3c69a392018-03-16 18:10:07 -0700231
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800232 Stats result2 = {};
Chenbo Feng58a09b52018-05-11 19:15:15 -0700233 ASSERT_EQ(0, bpfGetUidStatsInternal(TEST_UID2, &result2, mFakeAppUidStatsMap));
234 expectStatsEqual(value2, result2);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800235 std::vector<stats_line> lines;
236 std::vector<std::string> ifaces;
Chenbo Feng58a09b52018-05-11 19:15:15 -0700237 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
238 populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET1, value1, mFakeUidStatsMap);
239 populateFakeStats(TEST_UID2, 0, IFACE_INDEX3, TEST_COUNTERSET1, value1, mFakeUidStatsMap);
Chenbo Feng40508ea2018-03-15 17:59:58 -0700240 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
241 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800242 ASSERT_EQ((unsigned long)2, lines.size());
243 lines.clear();
Chenbo Feng40508ea2018-03-15 17:59:58 -0700244 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
245 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800246 ASSERT_EQ((unsigned long)1, lines.size());
Chenbo Feng2c67f262018-04-26 10:37:55 -0700247 expectStatsLineEqual(value1, IFACE_NAME3, TEST_UID2, TEST_COUNTERSET1, 0, lines.front());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800248}
249
250TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsInternal) {
Chenbo Fengcc6cbb72018-05-08 13:45:08 -0700251 SKIP_IF_BPF_NOT_SUPPORTED;
252
Chenbo Feng3c69a392018-03-16 18:10:07 -0700253 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
254 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
255 updateIfaceMap(IFACE_NAME3, IFACE_INDEX3);
256 StatsValue value1 = {
257 .rxBytes = TEST_BYTES0,
258 .rxPackets = TEST_PACKET0,
259 .txBytes = TEST_BYTES1,
260 .txPackets = TEST_PACKET1,
261 };
262 StatsValue value2 = {
263 .rxBytes = TEST_BYTES1,
264 .rxPackets = TEST_PACKET1,
265 .txBytes = TEST_BYTES0,
266 .txPackets = TEST_PACKET0,
267 };
268 uint32_t ifaceStatsKey = IFACE_INDEX1;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700269 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY)));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700270 ifaceStatsKey = IFACE_INDEX2;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700271 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY)));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700272 ifaceStatsKey = IFACE_INDEX3;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700273 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY)));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700274
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800275 Stats result1 = {};
Chenbo Feng3c69a392018-03-16 18:10:07 -0700276 ASSERT_EQ(0, bpfGetIfaceStatsInternal(IFACE_NAME1, &result1, mFakeIfaceStatsMap,
277 mFakeIfaceIndexNameMap));
278 expectStatsEqual(value1, result1);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800279 Stats result2 = {};
Chenbo Feng3c69a392018-03-16 18:10:07 -0700280 ASSERT_EQ(0, bpfGetIfaceStatsInternal(IFACE_NAME2, &result2, mFakeIfaceStatsMap,
281 mFakeIfaceIndexNameMap));
282 expectStatsEqual(value2, result2);
283 Stats totalResult = {};
284 ASSERT_EQ(0, bpfGetIfaceStatsInternal(NULL, &totalResult, mFakeIfaceStatsMap,
285 mFakeIfaceIndexNameMap));
286 StatsValue totalValue = {
287 .rxBytes = TEST_BYTES0 * 2 + TEST_BYTES1,
288 .rxPackets = TEST_PACKET0 * 2 + TEST_PACKET1,
289 .txBytes = TEST_BYTES1 * 2 + TEST_BYTES0,
290 .txPackets = TEST_PACKET1 * 2 + TEST_PACKET0,
291 };
292 expectStatsEqual(totalValue, totalResult);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800293}
294
295TEST_F(BpfNetworkStatsHelperTest, TestGetStatsDetail) {
Chenbo Fengcc6cbb72018-05-08 13:45:08 -0700296 SKIP_IF_BPF_NOT_SUPPORTED;
297
Chenbo Feng3c69a392018-03-16 18:10:07 -0700298 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
299 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
Chenbo Fengeac6c472018-02-05 15:06:23 -0800300 StatsValue value1 = {.rxBytes = TEST_BYTES0,
301 .rxPackets = TEST_PACKET0,
302 .txBytes = TEST_BYTES1,
303 .txPackets = TEST_PACKET1,};
Chenbo Feng2c67f262018-04-26 10:37:55 -0700304 populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
305 populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
306 populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, value1,
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800307 mFakeTagStatsMap);
Chenbo Feng2c67f262018-04-26 10:37:55 -0700308 populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800309 std::vector<stats_line> lines;
310 std::vector<std::string> ifaces;
Chenbo Feng40508ea2018-03-15 17:59:58 -0700311 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
312 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700313 ASSERT_EQ((unsigned long)4, lines.size());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800314 lines.clear();
Chenbo Feng40508ea2018-03-15 17:59:58 -0700315 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
316 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700317 ASSERT_EQ((unsigned long)3, lines.size());
318 lines.clear();
319 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
320 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800321 ASSERT_EQ((unsigned long)2, lines.size());
322 lines.clear();
Chenbo Feng3c69a392018-03-16 18:10:07 -0700323 ifaces.push_back(std::string(IFACE_NAME1));
Chenbo Feng40508ea2018-03-15 17:59:58 -0700324 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
325 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800326 ASSERT_EQ((unsigned long)1, lines.size());
Chenbo Feng3c69a392018-03-16 18:10:07 -0700327 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines.front());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800328}
329
330TEST_F(BpfNetworkStatsHelperTest, TestGetStatsWithSkippedIface) {
Chenbo Fengcc6cbb72018-05-08 13:45:08 -0700331 SKIP_IF_BPF_NOT_SUPPORTED;
332
Chenbo Feng3c69a392018-03-16 18:10:07 -0700333 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
334 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
Chenbo Fengeac6c472018-02-05 15:06:23 -0800335 StatsValue value1 = {.rxBytes = TEST_BYTES0,
336 .rxPackets = TEST_PACKET0,
337 .txBytes = TEST_BYTES1,
338 .txPackets = TEST_PACKET1,};
Chenbo Feng2c67f262018-04-26 10:37:55 -0700339 populateFakeStats(0, 0, 0, OVERFLOW_COUNTERSET, value1, mFakeUidStatsMap);
340 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
341 populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
342 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET1, value1, mFakeUidStatsMap);
343 populateFakeStats(TEST_UID2, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800344 std::vector<stats_line> lines;
345 std::vector<std::string> ifaces;
Chenbo Feng40508ea2018-03-15 17:59:58 -0700346 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
347 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700348 ASSERT_EQ((unsigned long)4, lines.size());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800349 lines.clear();
Chenbo Feng40508ea2018-03-15 17:59:58 -0700350 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
351 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700352 ASSERT_EQ((unsigned long)3, lines.size());
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800353 lines.clear();
Chenbo Feng40508ea2018-03-15 17:59:58 -0700354 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
355 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800356 ASSERT_EQ((unsigned long)1, lines.size());
Chenbo Feng3c69a392018-03-16 18:10:07 -0700357 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, 0, lines.front());
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800358 lines.clear();
Chenbo Feng3c69a392018-03-16 18:10:07 -0700359 ifaces.push_back(std::string(IFACE_NAME1));
Chenbo Feng40508ea2018-03-15 17:59:58 -0700360 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
361 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800362 ASSERT_EQ((unsigned long)2, lines.size());
363}
364
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800365TEST_F(BpfNetworkStatsHelperTest, TestUnkownIfaceError) {
Chenbo Fengcc6cbb72018-05-08 13:45:08 -0700366 SKIP_IF_BPF_NOT_SUPPORTED;
367
Chenbo Feng3c69a392018-03-16 18:10:07 -0700368 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800369 StatsValue value1 = {.rxBytes = TEST_BYTES0 * 20,
370 .rxPackets = TEST_PACKET0,
371 .txBytes = TEST_BYTES1 * 20,
372 .txPackets = TEST_PACKET1,};
373 uint32_t ifaceIndex = UNKNOWN_IFACE;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700374 populateFakeStats(TEST_UID1, 0, ifaceIndex, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
375 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
Chenbo Feng3c69a392018-03-16 18:10:07 -0700376 StatsValue value2 = {.rxBytes = TEST_BYTES0 * 40,
377 .rxPackets = TEST_PACKET0,
378 .txBytes = TEST_BYTES1 * 40,
379 .txPackets = TEST_PACKET1,};
Chenbo Feng2c67f262018-04-26 10:37:55 -0700380 populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value2, mFakeUidStatsMap);
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800381 StatsKey curKey = {.uid = TEST_UID1,
382 .tag = 0,
383 .ifaceIndex = ifaceIndex,
384 .counterSet = TEST_COUNTERSET0};
385 char ifname[IFNAMSIZ];
Chenbo Feng3c69a392018-03-16 18:10:07 -0700386 int64_t unknownIfaceBytesTotal = 0;
387 ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeUidStatsMap, ifaceIndex,
Chenbo Feng2c67f262018-04-26 10:37:55 -0700388 ifname, curKey, &unknownIfaceBytesTotal));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700389 ASSERT_EQ(((int64_t)(TEST_BYTES0 * 20 + TEST_BYTES1 * 20)), unknownIfaceBytesTotal);
390 curKey.ifaceIndex = IFACE_INDEX2;
391 ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeUidStatsMap, ifaceIndex,
Chenbo Feng2c67f262018-04-26 10:37:55 -0700392 ifname, curKey, &unknownIfaceBytesTotal));
Chenbo Feng3c69a392018-03-16 18:10:07 -0700393 ASSERT_EQ(-1, unknownIfaceBytesTotal);
394 std::vector<stats_line> lines;
395 std::vector<std::string> ifaces;
396 // TODO: find a way to test the total of unknown Iface Bytes go above limit.
397 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
398 mFakeUidStatsMap, mFakeIfaceIndexNameMap));
399 ASSERT_EQ((unsigned long)1, lines.size());
400 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines.front());
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800401}
402
Chenbo Fengb9c3fdb2018-04-18 15:27:19 -0700403TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsDetail) {
Chenbo Fengcc6cbb72018-05-08 13:45:08 -0700404 SKIP_IF_BPF_NOT_SUPPORTED;
405
Chenbo Fengb9c3fdb2018-04-18 15:27:19 -0700406 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
407 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
408 updateIfaceMap(IFACE_NAME3, IFACE_INDEX3);
Chenbo Feng58a09b52018-05-11 19:15:15 -0700409 updateIfaceMap(LONG_IFACE_NAME, IFACE_INDEX4);
Chenbo Fengb9c3fdb2018-04-18 15:27:19 -0700410 StatsValue value1 = {
411 .rxBytes = TEST_BYTES0,
412 .rxPackets = TEST_PACKET0,
413 .txBytes = TEST_BYTES1,
414 .txPackets = TEST_PACKET1,
415 };
416 StatsValue value2 = {
417 .rxBytes = TEST_BYTES1,
418 .rxPackets = TEST_PACKET1,
419 .txBytes = TEST_BYTES0,
420 .txPackets = TEST_PACKET0,
421 };
422 uint32_t ifaceStatsKey = IFACE_INDEX1;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700423 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY)));
Chenbo Fengb9c3fdb2018-04-18 15:27:19 -0700424 ifaceStatsKey = IFACE_INDEX2;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700425 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY)));
Chenbo Fengb9c3fdb2018-04-18 15:27:19 -0700426 ifaceStatsKey = IFACE_INDEX3;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700427 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY)));
Chenbo Feng58a09b52018-05-11 19:15:15 -0700428 ifaceStatsKey = IFACE_INDEX4;
429 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY)));
Chenbo Fengb9c3fdb2018-04-18 15:27:19 -0700430 std::vector<stats_line> lines;
431 ASSERT_EQ(0,
432 parseBpfNetworkStatsDevInternal(&lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
Chenbo Feng58a09b52018-05-11 19:15:15 -0700433 ASSERT_EQ((unsigned long)4, lines.size());
junyulaiaa7a4742018-11-13 10:12:46 +0800434
Chenbo Fengb9c3fdb2018-04-18 15:27:19 -0700435 expectStatsLineEqual(value1, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
436 expectStatsLineEqual(value1, IFACE_NAME3, UID_ALL, SET_ALL, TAG_NONE, lines[1]);
437 expectStatsLineEqual(value2, IFACE_NAME2, UID_ALL, SET_ALL, TAG_NONE, lines[2]);
Chenbo Feng58a09b52018-05-11 19:15:15 -0700438 ASSERT_EQ(0, strcmp(TRUNCATED_IFACE_NAME, lines[3].iface));
439 expectStatsLineEqual(value2, TRUNCATED_IFACE_NAME, UID_ALL, SET_ALL, TAG_NONE, lines[3]);
Chenbo Fengb9c3fdb2018-04-18 15:27:19 -0700440}
junyulaiaa7a4742018-11-13 10:12:46 +0800441
442TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortedAndGrouped) {
443 SKIP_IF_BPF_NOT_SUPPORTED;
444
445 // Create iface indexes with duplicate iface name.
446 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
447 updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
448 updateIfaceMap(IFACE_NAME1, IFACE_INDEX3); // Duplicate!
449
450 StatsValue value1 = {
451 .rxBytes = TEST_BYTES0,
452 .rxPackets = TEST_PACKET0,
453 .txBytes = TEST_BYTES1,
454 .txPackets = TEST_PACKET1,
455 };
456 StatsValue value2 = {
457 .rxBytes = TEST_BYTES1,
458 .rxPackets = TEST_PACKET1,
459 .txBytes = TEST_BYTES0,
460 .txPackets = TEST_PACKET0,
461 };
462 StatsValue value3 = {
463 .rxBytes = TEST_BYTES0 * 2,
464 .rxPackets = TEST_PACKET0 * 2,
465 .txBytes = TEST_BYTES1 * 2,
466 .txPackets = TEST_PACKET1 * 2,
467 };
468
469 std::vector<stats_line> lines;
470 std::vector<std::string> ifaces;
471
472 // Test empty stats.
473 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
474 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
475 ASSERT_EQ((size_t) 0, lines.size());
476 lines.clear();
477
478 // Test 1 line stats.
479 populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1,
480 mFakeTagStatsMap);
481 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
482 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
483 ASSERT_EQ((size_t) 1, lines.size());
484 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[0]);
485 lines.clear();
486
487 // These items should not be grouped.
488 populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, value2,
489 mFakeTagStatsMap);
490 populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET1, value2,
491 mFakeTagStatsMap);
492 populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, value2,
493 mFakeTagStatsMap);
494 populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1,
495 mFakeTagStatsMap);
496 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
497 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
498 ASSERT_EQ((size_t) 5, lines.size());
499 lines.clear();
500
501 // These items should be grouped.
502 populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1,
503 mFakeTagStatsMap);
504 populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1,
505 mFakeTagStatsMap);
506
507 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
508 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
509 ASSERT_EQ((size_t) 5, lines.size());
510
511 // Verify Sorted & Grouped.
512 expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[0]);
513 expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET1, TEST_TAG, lines[1]);
514 expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG + 1, lines[2]);
515 expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, TEST_TAG, lines[3]);
516 expectStatsLineEqual(value2, IFACE_NAME2, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[4]);
517 lines.clear();
518
519 // Perform test on IfaceStats.
520 uint32_t ifaceStatsKey = IFACE_INDEX2;
521 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY)));
522 ifaceStatsKey = IFACE_INDEX1;
523 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY)));
524
525 // This should be grouped.
526 ifaceStatsKey = IFACE_INDEX3;
527 EXPECT_TRUE(isOk(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY)));
528
529 ASSERT_EQ(0,
530 parseBpfNetworkStatsDevInternal(&lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
531 ASSERT_EQ((size_t) 2, lines.size());
532
533 expectStatsLineEqual(value3, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
534 expectStatsLineEqual(value2, IFACE_NAME2, UID_ALL, SET_ALL, TAG_NONE, lines[1]);
535 lines.clear();
536}
537
538// Test to verify that subtract overflow will not be triggered by the compare function invoked from
539// sorting. See http:/b/119193941.
540TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortAndOverflow) {
541 updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
542
543 StatsValue value1 = {
544 .rxBytes = TEST_BYTES0,
545 .rxPackets = TEST_PACKET0,
546 .txBytes = TEST_BYTES1,
547 .txPackets = TEST_PACKET1,
548 };
549
550 // Mutate uid, 0 < TEST_UID1 < INT_MAX < INT_MIN < UINT_MAX.
551 populateFakeStats(0, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
552 populateFakeStats(UINT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
553 populateFakeStats(INT_MIN, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
554 populateFakeStats(INT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
555
556 // Mutate tag, 0 < TEST_TAG < INT_MAX < INT_MIN < UINT_MAX.
557 populateFakeStats(TEST_UID1, INT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
558 populateFakeStats(TEST_UID1, INT_MIN, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
559 populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
560 populateFakeStats(TEST_UID1, UINT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1,
561 mFakeTagStatsMap);
562
563 // TODO: Mutate counterSet and enlarge TEST_MAP_SIZE if overflow on counterSet is possible.
564
565 std::vector<stats_line> lines;
566 std::vector<std::string> ifaces;
567 ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
568 mFakeTagStatsMap, mFakeIfaceIndexNameMap));
569 ASSERT_EQ((size_t) 8, lines.size());
570
571 // Uid 0 first
572 expectStatsLineEqual(value1, IFACE_NAME1, 0, TEST_COUNTERSET0, TEST_TAG, lines[0]);
573
574 // Test uid, mutate tag.
575 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines[1]);
576 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, INT_MAX, lines[2]);
577 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, INT_MIN, lines[3]);
578 expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, UINT_MAX, lines[4]);
579
580 // Mutate uid.
581 expectStatsLineEqual(value1, IFACE_NAME1, INT_MAX, TEST_COUNTERSET0, TEST_TAG, lines[5]);
582 expectStatsLineEqual(value1, IFACE_NAME1, INT_MIN, TEST_COUNTERSET0, TEST_TAG, lines[6]);
583 expectStatsLineEqual(value1, IFACE_NAME1, UINT_MAX, TEST_COUNTERSET0, TEST_TAG, lines[7]);
584 lines.clear();
585}
Chenbo Fengdc4e3252017-12-22 11:00:52 -0800586} // namespace bpf
587} // namespace android