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