• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "bpf/BpfMap.h"
37 #include "bpf/BpfUtils.h"
38 #include "netdbpf/BpfNetworkStats.h"
39 
40 using ::testing::Test;
41 
42 namespace android {
43 namespace bpf {
44 
45 using base::Result;
46 using base::unique_fd;
47 
48 constexpr int TEST_MAP_SIZE = 10;
49 constexpr uid_t TEST_UID1 = 10086;
50 constexpr uid_t TEST_UID2 = 12345;
51 constexpr uint32_t TEST_TAG = 42;
52 constexpr int TEST_COUNTERSET0 = 0;
53 constexpr int TEST_COUNTERSET1 = 1;
54 constexpr uint64_t TEST_BYTES0 = 1000;
55 constexpr uint64_t TEST_BYTES1 = 2000;
56 constexpr uint64_t TEST_PACKET0 = 100;
57 constexpr uint64_t TEST_PACKET1 = 200;
58 constexpr const char IFACE_NAME1[] = "lo";
59 constexpr const char IFACE_NAME2[] = "wlan0";
60 constexpr const char IFACE_NAME3[] = "rmnet_data0";
61 // A iface name that the size is bigger than IFNAMSIZ
62 constexpr const char LONG_IFACE_NAME[] = "wlanWithALongName";
63 constexpr const char TRUNCATED_IFACE_NAME[] = "wlanWithALongNa";
64 constexpr uint32_t IFACE_INDEX1 = 1;
65 constexpr uint32_t IFACE_INDEX2 = 2;
66 constexpr uint32_t IFACE_INDEX3 = 3;
67 constexpr uint32_t IFACE_INDEX4 = 4;
68 constexpr uint32_t UNKNOWN_IFACE = 0;
69 
70 class BpfNetworkStatsHelperTest : public testing::Test {
71   protected:
BpfNetworkStatsHelperTest()72     BpfNetworkStatsHelperTest() {}
73     BpfMap<uint64_t, UidTagValue> mFakeCookieTagMap;
74     BpfMap<uint32_t, StatsValue> mFakeAppUidStatsMap;
75     BpfMap<StatsKey, StatsValue> mFakeStatsMap;
76     BpfMap<uint32_t, IfaceValue> mFakeIfaceIndexNameMap;
77     BpfMap<uint32_t, StatsValue> mFakeIfaceStatsMap;
78 
SetUp()79     void SetUp() {
80         ASSERT_EQ(0, setrlimitForTest());
81 
82         mFakeCookieTagMap = BpfMap<uint64_t, UidTagValue>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, 0);
83         ASSERT_LE(0, mFakeCookieTagMap.getMap());
84 
85         mFakeAppUidStatsMap = BpfMap<uint32_t, StatsValue>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, 0);
86         ASSERT_LE(0, mFakeAppUidStatsMap.getMap());
87 
88         mFakeStatsMap = BpfMap<StatsKey, StatsValue>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, 0);
89         ASSERT_LE(0, mFakeStatsMap.getMap());
90 
91         mFakeIfaceIndexNameMap = BpfMap<uint32_t, IfaceValue>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, 0);
92         ASSERT_LE(0, mFakeIfaceIndexNameMap.getMap());
93 
94         mFakeIfaceStatsMap = BpfMap<uint32_t, StatsValue>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, 0);
95         ASSERT_LE(0, mFakeIfaceStatsMap.getMap());
96     }
97 
expectUidTag(uint64_t cookie,uid_t uid,uint32_t tag)98     void expectUidTag(uint64_t cookie, uid_t uid, uint32_t tag) {
99         auto tagResult = mFakeCookieTagMap.readValue(cookie);
100         EXPECT_RESULT_OK(tagResult);
101         EXPECT_EQ(uid, tagResult.value().uid);
102         EXPECT_EQ(tag, tagResult.value().tag);
103     }
104 
populateFakeStats(uid_t uid,uint32_t tag,uint32_t ifaceIndex,uint32_t counterSet,StatsValue value,BpfMap<StatsKey,StatsValue> & map)105     void populateFakeStats(uid_t uid, uint32_t tag, uint32_t ifaceIndex, uint32_t counterSet,
106                            StatsValue value, BpfMap<StatsKey, StatsValue>& map) {
107         StatsKey key = {
108             .uid = (uint32_t)uid, .tag = tag, .counterSet = counterSet, .ifaceIndex = ifaceIndex};
109         EXPECT_RESULT_OK(map.writeValue(key, value, BPF_ANY));
110     }
111 
updateIfaceMap(const char * ifaceName,uint32_t ifaceIndex)112     void updateIfaceMap(const char* ifaceName, uint32_t ifaceIndex) {
113         IfaceValue iface;
114         strlcpy(iface.name, ifaceName, IFNAMSIZ);
115         EXPECT_RESULT_OK(mFakeIfaceIndexNameMap.writeValue(ifaceIndex, iface, BPF_ANY));
116     }
117 
expectStatsEqual(const StatsValue & target,const Stats & result)118     void expectStatsEqual(const StatsValue& target, const Stats& result) {
119         EXPECT_EQ(target.rxPackets, result.rxPackets);
120         EXPECT_EQ(target.rxBytes, result.rxBytes);
121         EXPECT_EQ(target.txPackets, result.txPackets);
122         EXPECT_EQ(target.txBytes, result.txBytes);
123     }
124 
expectStatsLineEqual(const StatsValue target,const char * iface,uint32_t uid,int counterSet,uint32_t tag,const stats_line & result)125     void expectStatsLineEqual(const StatsValue target, const char* iface, uint32_t uid,
126                               int counterSet, uint32_t tag, const stats_line& result) {
127         EXPECT_EQ(0, strcmp(iface, result.iface));
128         EXPECT_EQ(uid, (uint32_t)result.uid);
129         EXPECT_EQ((uint32_t) counterSet, result.set);
130         EXPECT_EQ(tag, (uint32_t)result.tag);
131         EXPECT_EQ(target.rxPackets, (uint64_t)result.rxPackets);
132         EXPECT_EQ(target.rxBytes, (uint64_t)result.rxBytes);
133         EXPECT_EQ(target.txPackets, (uint64_t)result.txPackets);
134         EXPECT_EQ(target.txBytes, (uint64_t)result.txBytes);
135     }
136 };
137 
138 // TEST to verify the behavior of bpf map when cocurrent deletion happens when
139 // iterating the same map.
TEST_F(BpfNetworkStatsHelperTest,TestIterateMapWithDeletion)140 TEST_F(BpfNetworkStatsHelperTest, TestIterateMapWithDeletion) {
141     for (int i = 0; i < 5; i++) {
142         uint64_t cookie = i + 1;
143         UidTagValue tag = {.uid = TEST_UID1, .tag = TEST_TAG};
144         EXPECT_RESULT_OK(mFakeCookieTagMap.writeValue(cookie, tag, BPF_ANY));
145     }
146     uint64_t curCookie = 0;
147     auto nextCookie = mFakeCookieTagMap.getNextKey(curCookie);
148     EXPECT_RESULT_OK(nextCookie);
149     uint64_t headOfMap = nextCookie.value();
150     curCookie = nextCookie.value();
151     // Find the second entry in the map, then immediately delete it.
152     nextCookie = mFakeCookieTagMap.getNextKey(curCookie);
153     EXPECT_RESULT_OK(nextCookie);
154     EXPECT_RESULT_OK(mFakeCookieTagMap.deleteValue((nextCookie.value())));
155     // Find the entry that is now immediately after headOfMap, then delete that.
156     nextCookie = mFakeCookieTagMap.getNextKey(curCookie);
157     EXPECT_RESULT_OK(nextCookie);
158     EXPECT_RESULT_OK(mFakeCookieTagMap.deleteValue((nextCookie.value())));
159     // Attempting to read an entry that has been deleted fails with ENOENT.
160     curCookie = nextCookie.value();
161     auto tagResult = mFakeCookieTagMap.readValue(curCookie);
162     EXPECT_EQ(ENOENT, tagResult.error().code());
163     // Finding the entry after our deleted entry restarts iteration from the beginning of the map.
164     nextCookie = mFakeCookieTagMap.getNextKey(curCookie);
165     EXPECT_RESULT_OK(nextCookie);
166     EXPECT_EQ(headOfMap, nextCookie.value());
167 }
168 
TEST_F(BpfNetworkStatsHelperTest,TestBpfIterateMap)169 TEST_F(BpfNetworkStatsHelperTest, TestBpfIterateMap) {
170     for (int i = 0; i < 5; i++) {
171         uint64_t cookie = i + 1;
172         UidTagValue tag = {.uid = TEST_UID1, .tag = TEST_TAG};
173         EXPECT_RESULT_OK(mFakeCookieTagMap.writeValue(cookie, tag, BPF_ANY));
174     }
175     int totalCount = 0;
176     int totalSum = 0;
177     const auto iterateWithoutDeletion =
178             [&totalCount, &totalSum](const uint64_t& key, const BpfMap<uint64_t, UidTagValue>&) {
179                 EXPECT_GE((uint64_t)5, key);
180                 totalCount++;
181                 totalSum += key;
182                 return Result<void>();
183             };
184     EXPECT_RESULT_OK(mFakeCookieTagMap.iterate(iterateWithoutDeletion));
185     EXPECT_EQ(5, totalCount);
186     EXPECT_EQ(1 + 2 + 3 + 4 + 5, totalSum);
187 }
188 
TEST_F(BpfNetworkStatsHelperTest,TestUidStatsNoTraffic)189 TEST_F(BpfNetworkStatsHelperTest, TestUidStatsNoTraffic) {
190     StatsValue value1 = {
191             .rxPackets = 0,
192             .rxBytes = 0,
193             .txPackets = 0,
194             .txBytes = 0,
195     };
196     Stats result1 = {};
197     ASSERT_EQ(0, bpfGetUidStatsInternal(TEST_UID1, &result1, mFakeAppUidStatsMap));
198     expectStatsEqual(value1, result1);
199 }
200 
TEST_F(BpfNetworkStatsHelperTest,TestGetUidStatsTotal)201 TEST_F(BpfNetworkStatsHelperTest, TestGetUidStatsTotal) {
202     updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
203     updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
204     updateIfaceMap(IFACE_NAME3, IFACE_INDEX3);
205     StatsValue value1 = {
206             .rxPackets = TEST_PACKET0,
207             .rxBytes = TEST_BYTES0,
208             .txPackets = TEST_PACKET1,
209             .txBytes = TEST_BYTES1,
210     };
211     StatsValue value2 = {
212             .rxPackets = TEST_PACKET0 * 2,
213             .rxBytes = TEST_BYTES0 * 2,
214             .txPackets = TEST_PACKET1 * 2,
215             .txBytes = TEST_BYTES1 * 2,
216     };
217     ASSERT_RESULT_OK(mFakeAppUidStatsMap.writeValue(TEST_UID1, value1, BPF_ANY));
218     ASSERT_RESULT_OK(mFakeAppUidStatsMap.writeValue(TEST_UID2, value2, BPF_ANY));
219     Stats result1 = {};
220     ASSERT_EQ(0, bpfGetUidStatsInternal(TEST_UID1, &result1, mFakeAppUidStatsMap));
221     expectStatsEqual(value1, result1);
222 
223     Stats result2 = {};
224     ASSERT_EQ(0, bpfGetUidStatsInternal(TEST_UID2, &result2, mFakeAppUidStatsMap));
225     expectStatsEqual(value2, result2);
226     std::vector<stats_line> lines;
227     std::vector<std::string> ifaces;
228     populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
229     populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET1, value1, mFakeStatsMap);
230     populateFakeStats(TEST_UID2, 0, IFACE_INDEX3, TEST_COUNTERSET1, value1, mFakeStatsMap);
231     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
232                                                     mFakeStatsMap, mFakeIfaceIndexNameMap));
233     ASSERT_EQ((unsigned long)2, lines.size());
234     lines.clear();
235     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
236                                                     mFakeStatsMap, mFakeIfaceIndexNameMap));
237     ASSERT_EQ((unsigned long)1, lines.size());
238     expectStatsLineEqual(value1, IFACE_NAME3, TEST_UID2, TEST_COUNTERSET1, 0, lines.front());
239 }
240 
TEST_F(BpfNetworkStatsHelperTest,TestGetIfaceStatsInternal)241 TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsInternal) {
242     updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
243     updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
244     updateIfaceMap(IFACE_NAME3, IFACE_INDEX3);
245     StatsValue value1 = {
246             .rxPackets = TEST_PACKET0,
247             .rxBytes = TEST_BYTES0,
248             .txPackets = TEST_PACKET1,
249             .txBytes = TEST_BYTES1,
250     };
251     StatsValue value2 = {
252             .rxPackets = TEST_PACKET1,
253             .rxBytes = TEST_BYTES1,
254             .txPackets = TEST_PACKET0,
255             .txBytes = TEST_BYTES0,
256     };
257     uint32_t ifaceStatsKey = IFACE_INDEX1;
258     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
259     ifaceStatsKey = IFACE_INDEX2;
260     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY));
261     ifaceStatsKey = IFACE_INDEX3;
262     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
263 
264     Stats result1 = {};
265     ASSERT_EQ(0, bpfGetIfaceStatsInternal(IFACE_NAME1, &result1, mFakeIfaceStatsMap,
266                                           mFakeIfaceIndexNameMap));
267     expectStatsEqual(value1, result1);
268     Stats result2 = {};
269     ASSERT_EQ(0, bpfGetIfaceStatsInternal(IFACE_NAME2, &result2, mFakeIfaceStatsMap,
270                                           mFakeIfaceIndexNameMap));
271     expectStatsEqual(value2, result2);
272     Stats totalResult = {};
273     ASSERT_EQ(0, bpfGetIfaceStatsInternal(NULL, &totalResult, mFakeIfaceStatsMap,
274                                           mFakeIfaceIndexNameMap));
275     StatsValue totalValue = {
276             .rxPackets = TEST_PACKET0 * 2 + TEST_PACKET1,
277             .rxBytes = TEST_BYTES0 * 2 + TEST_BYTES1,
278             .txPackets = TEST_PACKET1 * 2 + TEST_PACKET0,
279             .txBytes = TEST_BYTES1 * 2 + TEST_BYTES0,
280     };
281     expectStatsEqual(totalValue, totalResult);
282 }
283 
TEST_F(BpfNetworkStatsHelperTest,TestGetStatsDetail)284 TEST_F(BpfNetworkStatsHelperTest, TestGetStatsDetail) {
285     updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
286     updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
287     StatsValue value1 = {
288             .rxPackets = TEST_PACKET0,
289             .rxBytes = TEST_BYTES0,
290             .txPackets = TEST_PACKET1,
291             .txBytes = TEST_BYTES1,
292     };
293     populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
294     populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeStatsMap);
295     populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, value1,
296                       mFakeStatsMap);
297     populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
298     std::vector<stats_line> lines;
299     std::vector<std::string> ifaces;
300     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
301                                                     mFakeIfaceIndexNameMap));
302     ASSERT_EQ((unsigned long)4, lines.size());
303     lines.clear();
304     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
305                                                     mFakeStatsMap, mFakeIfaceIndexNameMap));
306     ASSERT_EQ((unsigned long)3, lines.size());
307     lines.clear();
308     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
309                                                     mFakeStatsMap, mFakeIfaceIndexNameMap));
310     ASSERT_EQ((unsigned long)2, lines.size());
311     lines.clear();
312     ifaces.push_back(std::string(IFACE_NAME1));
313     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
314                                                     mFakeStatsMap, mFakeIfaceIndexNameMap));
315     ASSERT_EQ((unsigned long)1, lines.size());
316     expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines.front());
317 }
318 
TEST_F(BpfNetworkStatsHelperTest,TestGetStatsWithSkippedIface)319 TEST_F(BpfNetworkStatsHelperTest, TestGetStatsWithSkippedIface) {
320     updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
321     updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
322     StatsValue value1 = {
323             .rxPackets = TEST_PACKET0,
324             .rxBytes = TEST_BYTES0,
325             .txPackets = TEST_PACKET1,
326             .txBytes = TEST_BYTES1,
327     };
328     populateFakeStats(0, 0, 0, OVERFLOW_COUNTERSET, value1, mFakeStatsMap);
329     populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
330     populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeStatsMap);
331     populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET1, value1, mFakeStatsMap);
332     populateFakeStats(TEST_UID2, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
333     std::vector<stats_line> lines;
334     std::vector<std::string> ifaces;
335     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
336                                                     mFakeIfaceIndexNameMap));
337     ASSERT_EQ((unsigned long)4, lines.size());
338     lines.clear();
339     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
340                                                     mFakeStatsMap, mFakeIfaceIndexNameMap));
341     ASSERT_EQ((unsigned long)3, lines.size());
342     lines.clear();
343     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
344                                                     mFakeStatsMap, mFakeIfaceIndexNameMap));
345     ASSERT_EQ((unsigned long)1, lines.size());
346     expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, 0, lines.front());
347     lines.clear();
348     ifaces.push_back(std::string(IFACE_NAME1));
349     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
350                                                     mFakeStatsMap, mFakeIfaceIndexNameMap));
351     ASSERT_EQ((unsigned long)2, lines.size());
352 }
353 
TEST_F(BpfNetworkStatsHelperTest,TestUnknownIfaceError)354 TEST_F(BpfNetworkStatsHelperTest, TestUnknownIfaceError) {
355     updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
356     StatsValue value1 = {
357             .rxPackets = TEST_PACKET0,
358             .rxBytes = TEST_BYTES0 * 20,
359             .txPackets = TEST_PACKET1,
360             .txBytes = TEST_BYTES1 * 20,
361     };
362     uint32_t ifaceIndex = UNKNOWN_IFACE;
363     populateFakeStats(TEST_UID1, 0, ifaceIndex, TEST_COUNTERSET0, value1, mFakeStatsMap);
364     populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
365     StatsValue value2 = {
366             .rxPackets = TEST_PACKET0,
367             .rxBytes = TEST_BYTES0 * 40,
368             .txPackets = TEST_PACKET1,
369             .txBytes = TEST_BYTES1 * 40,
370     };
371     populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value2, mFakeStatsMap);
372     StatsKey curKey = {
373             .uid = TEST_UID1,
374             .tag = 0,
375             .counterSet = TEST_COUNTERSET0,
376             .ifaceIndex = ifaceIndex,
377     };
378     char ifname[IFNAMSIZ];
379     int64_t unknownIfaceBytesTotal = 0;
380     ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeStatsMap, ifaceIndex,
381                                            ifname, curKey, &unknownIfaceBytesTotal));
382     ASSERT_EQ(((int64_t)(TEST_BYTES0 * 20 + TEST_BYTES1 * 20)), unknownIfaceBytesTotal);
383     curKey.ifaceIndex = IFACE_INDEX2;
384     ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeStatsMap, ifaceIndex,
385                                            ifname, curKey, &unknownIfaceBytesTotal));
386     ASSERT_EQ(-1, unknownIfaceBytesTotal);
387     std::vector<stats_line> lines;
388     std::vector<std::string> ifaces;
389     // TODO: find a way to test the total of unknown Iface Bytes go above limit.
390     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
391                                                     mFakeIfaceIndexNameMap));
392     ASSERT_EQ((unsigned long)1, lines.size());
393     expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines.front());
394 }
395 
TEST_F(BpfNetworkStatsHelperTest,TestGetIfaceStatsDetail)396 TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsDetail) {
397     updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
398     updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
399     updateIfaceMap(IFACE_NAME3, IFACE_INDEX3);
400     updateIfaceMap(LONG_IFACE_NAME, IFACE_INDEX4);
401     StatsValue value1 = {
402             .rxPackets = TEST_PACKET0,
403             .rxBytes = TEST_BYTES0,
404             .txPackets = TEST_PACKET1,
405             .txBytes = TEST_BYTES1,
406     };
407     StatsValue value2 = {
408             .rxPackets = TEST_PACKET1,
409             .rxBytes = TEST_BYTES1,
410             .txPackets = TEST_PACKET0,
411             .txBytes = TEST_BYTES0,
412     };
413     uint32_t ifaceStatsKey = IFACE_INDEX1;
414     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
415     ifaceStatsKey = IFACE_INDEX2;
416     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY));
417     ifaceStatsKey = IFACE_INDEX3;
418     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
419     ifaceStatsKey = IFACE_INDEX4;
420     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY));
421     std::vector<stats_line> lines;
422     ASSERT_EQ(0,
423               parseBpfNetworkStatsDevInternal(&lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
424     ASSERT_EQ((unsigned long)4, lines.size());
425 
426     expectStatsLineEqual(value1, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
427     expectStatsLineEqual(value1, IFACE_NAME3, UID_ALL, SET_ALL, TAG_NONE, lines[1]);
428     expectStatsLineEqual(value2, IFACE_NAME2, UID_ALL, SET_ALL, TAG_NONE, lines[2]);
429     ASSERT_EQ(0, strcmp(TRUNCATED_IFACE_NAME, lines[3].iface));
430     expectStatsLineEqual(value2, TRUNCATED_IFACE_NAME, UID_ALL, SET_ALL, TAG_NONE, lines[3]);
431 }
432 
TEST_F(BpfNetworkStatsHelperTest,TestGetStatsSortedAndGrouped)433 TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortedAndGrouped) {
434     // Create iface indexes with duplicate iface name.
435     updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
436     updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
437     updateIfaceMap(IFACE_NAME1, IFACE_INDEX3);  // Duplicate!
438 
439     StatsValue value1 = {
440             .rxPackets = TEST_PACKET0,
441             .rxBytes = TEST_BYTES0,
442             .txPackets = TEST_PACKET1,
443             .txBytes = TEST_BYTES1,
444     };
445     StatsValue value2 = {
446             .rxPackets = TEST_PACKET1,
447             .rxBytes = TEST_BYTES1,
448             .txPackets = TEST_PACKET0,
449             .txBytes = TEST_BYTES0,
450     };
451     StatsValue value3 = {
452             .rxPackets = TEST_PACKET0 * 2,
453             .rxBytes = TEST_BYTES0 * 2,
454             .txPackets = TEST_PACKET1 * 2,
455             .txBytes = TEST_BYTES1 * 2,
456     };
457 
458     std::vector<stats_line> lines;
459     std::vector<std::string> ifaces;
460 
461     // Test empty stats.
462     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
463                                                     mFakeIfaceIndexNameMap));
464     ASSERT_EQ((size_t) 0, lines.size());
465     lines.clear();
466 
467     // Test 1 line stats.
468     populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
469     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
470                                                     mFakeIfaceIndexNameMap));
471     ASSERT_EQ((size_t) 1, lines.size());
472     expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[0]);
473     lines.clear();
474 
475     // These items should not be grouped.
476     populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, value2, mFakeStatsMap);
477     populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET1, value2, mFakeStatsMap);
478     populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, value2,
479                       mFakeStatsMap);
480     populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
481     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
482                                                     mFakeIfaceIndexNameMap));
483     ASSERT_EQ((size_t) 5, lines.size());
484     lines.clear();
485 
486     // These items should be grouped.
487     populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1, mFakeStatsMap);
488     populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1, mFakeStatsMap);
489 
490     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
491                                                     mFakeIfaceIndexNameMap));
492     ASSERT_EQ((size_t) 5, lines.size());
493 
494     // Verify Sorted & Grouped.
495     expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[0]);
496     expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET1, TEST_TAG, lines[1]);
497     expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG + 1, lines[2]);
498     expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, TEST_TAG, lines[3]);
499     expectStatsLineEqual(value2, IFACE_NAME2, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[4]);
500     lines.clear();
501 
502     // Perform test on IfaceStats.
503     uint32_t ifaceStatsKey = IFACE_INDEX2;
504     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY));
505     ifaceStatsKey = IFACE_INDEX1;
506     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
507 
508     // This should be grouped.
509     ifaceStatsKey = IFACE_INDEX3;
510     EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
511 
512     ASSERT_EQ(0,
513               parseBpfNetworkStatsDevInternal(&lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
514     ASSERT_EQ((size_t) 2, lines.size());
515 
516     expectStatsLineEqual(value3, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
517     expectStatsLineEqual(value2, IFACE_NAME2, UID_ALL, SET_ALL, TAG_NONE, lines[1]);
518     lines.clear();
519 }
520 
521 // Test to verify that subtract overflow will not be triggered by the compare function invoked from
522 // sorting. See http:/b/119193941.
TEST_F(BpfNetworkStatsHelperTest,TestGetStatsSortAndOverflow)523 TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortAndOverflow) {
524     updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
525 
526     StatsValue value1 = {
527             .rxPackets = TEST_PACKET0,
528             .rxBytes = TEST_BYTES0,
529             .txPackets = TEST_PACKET1,
530             .txBytes = TEST_BYTES1,
531     };
532 
533     // Mutate uid, 0 < TEST_UID1 < INT_MAX < INT_MIN < UINT_MAX.
534     populateFakeStats(0, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
535     populateFakeStats(UINT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
536     populateFakeStats(INT_MIN, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
537     populateFakeStats(INT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
538 
539     // Mutate tag, 0 < TEST_TAG < INT_MAX < INT_MIN < UINT_MAX.
540     populateFakeStats(TEST_UID1, INT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
541     populateFakeStats(TEST_UID1, INT_MIN, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
542     populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
543     populateFakeStats(TEST_UID1, UINT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
544 
545     // TODO: Mutate counterSet and enlarge TEST_MAP_SIZE if overflow on counterSet is possible.
546 
547     std::vector<stats_line> lines;
548     std::vector<std::string> ifaces;
549     ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
550                                                     mFakeIfaceIndexNameMap));
551     ASSERT_EQ((size_t) 8, lines.size());
552 
553     // Uid 0 first
554     expectStatsLineEqual(value1, IFACE_NAME1, 0, TEST_COUNTERSET0, TEST_TAG, lines[0]);
555 
556     // Test uid, mutate tag.
557     expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines[1]);
558     expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, INT_MAX, lines[2]);
559     expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, INT_MIN, lines[3]);
560     expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, UINT_MAX, lines[4]);
561 
562     // Mutate uid.
563     expectStatsLineEqual(value1, IFACE_NAME1, INT_MAX, TEST_COUNTERSET0, TEST_TAG, lines[5]);
564     expectStatsLineEqual(value1, IFACE_NAME1, INT_MIN, TEST_COUNTERSET0, TEST_TAG, lines[6]);
565     expectStatsLineEqual(value1, IFACE_NAME1, UINT_MAX, TEST_COUNTERSET0, TEST_TAG, lines[7]);
566     lines.clear();
567 }
568 }  // namespace bpf
569 }  // namespace android
570