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