diff options
author | Chenbo Feng <fengc@google.com> | 2018-04-18 15:27:19 -0700 |
---|---|---|
committer | Chenbo Feng <fengc@google.com> | 2018-05-01 19:35:03 -0700 |
commit | b9c3fdb02c283724d8809771ab45096229fa8561 (patch) | |
tree | 48bde3fd5550ca33f96ef633d19ab26918a36473 | |
parent | b905757231225cd2d37cd10aeee1bb16e4a544d2 (diff) | |
download | netd-b9c3fdb02c283724d8809771ab45096229fa8561.tar.gz |
Support read iface stats detail
The networkStatsFactory need to parse the detail traffic stats of each
interface instead of the total number. This change added a helper
function to return a vector of stats_line contain stats for each iface.
Bug: 72111305
Test: ./libbpf_test
Change-Id: I9a9cda7ab90cf533c2f2cc81b37b4d520d442ce2
Merged-In: I9a9cda7ab90cf533c2f2cc81b37b4d520d442ce2
(cherry picked from aosp commit f4b812d9dc603d329217becb9e5568b8159b49b3)
-rw-r--r-- | libbpf/BpfNetworkStats.cpp | 47 | ||||
-rw-r--r-- | libbpf/BpfNetworkStatsTest.cpp | 33 | ||||
-rw-r--r-- | libbpf/include/bpf/BpfNetworkStats.h | 6 |
3 files changed, 83 insertions, 3 deletions
diff --git a/libbpf/BpfNetworkStats.cpp b/libbpf/BpfNetworkStats.cpp index bc9a932f..acde1e65 100644 --- a/libbpf/BpfNetworkStats.cpp +++ b/libbpf/BpfNetworkStats.cpp @@ -123,9 +123,9 @@ stats_line populateStatsEntry(const StatsKey& statsKey, const StatsValue& statsE const char* ifname) { stats_line newLine; strlcpy(newLine.iface, ifname, sizeof(newLine.iface)); - newLine.uid = statsKey.uid; - newLine.set = statsKey.counterSet; - newLine.tag = statsKey.tag; + newLine.uid = (int32_t)statsKey.uid; + newLine.set = (int32_t)statsKey.counterSet; + newLine.tag = (int32_t)statsKey.tag; newLine.rxPackets = statsEntry.rxPackets; newLine.txPackets = statsEntry.txPackets; newLine.rxBytes = statsEntry.rxBytes; @@ -240,6 +240,47 @@ int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines, return ret; } +int parseBpfNetworkStatsDevInternal(std::vector<stats_line>* lines, + const base::unique_fd& statsMapFd, + const base::unique_fd& ifaceMapFd) { + int64_t unknownIfaceBytesTotal = 0; + uint32_t nonExistentKey = NONEXISTENT_IFACE_STATS_KEY; + struct StatsValue dummyValue; + auto processDetailIfaceStats = [lines, &unknownIfaceBytesTotal, &ifaceMapFd]( + void* key, void* value, const base::unique_fd& statsMapFd) { + uint32_t ifIndex = *(uint32_t*)key; + char ifname[IFNAMSIZ]; + if (getIfaceNameFromMap(ifaceMapFd, statsMapFd, ifIndex, ifname, &ifIndex, + &unknownIfaceBytesTotal)) { + return BPF_CONTINUE; + } + StatsValue* statsEntry = (StatsValue*)value; + StatsKey fakeKey = { + .uid = (uint32_t)UID_ALL, .counterSet = (uint32_t)SET_ALL, .tag = (uint32_t)TAG_NONE}; + lines->push_back(populateStatsEntry(fakeKey, *statsEntry, ifname)); + return BPF_CONTINUE; + }; + return bpfIterateMapWithValue(nonExistentKey, dummyValue, statsMapFd, processDetailIfaceStats); +} + +int parseBpfNetworkStatsDev(std::vector<stats_line>* lines) { + int ret = 0; + base::unique_fd ifaceIndexNameMap(bpf::mapRetrieve(IFACE_INDEX_NAME_MAP_PATH, BPF_OPEN_FLAGS)); + if (ifaceIndexNameMap < 0) { + ret = -errno; + ALOGE("get ifaceIndexName map fd failed: %s", strerror(errno)); + return ret; + } + + base::unique_fd ifaceStatsMap(bpf::mapRetrieve(IFACE_STATS_MAP_PATH, BPF_OPEN_FLAGS)); + if (ifaceStatsMap < 0) { + ret = -errno; + ALOGE("get ifaceStats map fd failed: %s", strerror(errno)); + return ret; + } + return parseBpfNetworkStatsDevInternal(lines, ifaceStatsMap, ifaceIndexNameMap); +} + uint64_t combineUidTag(const uid_t uid, const uint32_t tag) { return (uint64_t)uid << 32 | tag; } diff --git a/libbpf/BpfNetworkStatsTest.cpp b/libbpf/BpfNetworkStatsTest.cpp index cd7a0660..33df0f20 100644 --- a/libbpf/BpfNetworkStatsTest.cpp +++ b/libbpf/BpfNetworkStatsTest.cpp @@ -378,5 +378,38 @@ TEST_F(BpfNetworkStatsHelperTest, TestUnkownIfaceError) { expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines.front()); } +TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsDetail) { + updateIfaceMap(IFACE_NAME1, IFACE_INDEX1); + updateIfaceMap(IFACE_NAME2, IFACE_INDEX2); + updateIfaceMap(IFACE_NAME3, IFACE_INDEX3); + StatsValue value1 = { + .rxBytes = TEST_BYTES0, + .rxPackets = TEST_PACKET0, + .txBytes = TEST_BYTES1, + .txPackets = TEST_PACKET1, + }; + StatsValue value2 = { + .rxBytes = TEST_BYTES1, + .rxPackets = TEST_PACKET1, + .txBytes = TEST_BYTES0, + .txPackets = TEST_PACKET0, + }; + uint32_t ifaceStatsKey = IFACE_INDEX1; + EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value1, BPF_ANY)); + ifaceStatsKey = IFACE_INDEX2; + EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value2, BPF_ANY)); + ifaceStatsKey = IFACE_INDEX3; + EXPECT_EQ(0, writeToMapEntry(mFakeIfaceStatsMap, &ifaceStatsKey, &value1, BPF_ANY)); + std::vector<stats_line> lines; + ASSERT_EQ(0, + parseBpfNetworkStatsDevInternal(&lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap)); + ASSERT_EQ((unsigned long)3, lines.size()); + std::sort(lines.begin(), lines.end(), [](const auto& line1, const auto& line2)-> bool { + return strcmp(line1.iface, line2.iface) < 0; + }); + expectStatsLineEqual(value1, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]); + expectStatsLineEqual(value1, IFACE_NAME3, UID_ALL, SET_ALL, TAG_NONE, lines[1]); + expectStatsLineEqual(value2, IFACE_NAME2, UID_ALL, SET_ALL, TAG_NONE, lines[2]); +} } // namespace bpf } // namespace android diff --git a/libbpf/include/bpf/BpfNetworkStats.h b/libbpf/include/bpf/BpfNetworkStats.h index db0c185f..63cf0bc8 100644 --- a/libbpf/include/bpf/BpfNetworkStats.h +++ b/libbpf/include/bpf/BpfNetworkStats.h @@ -53,12 +53,18 @@ int cleanStatsMapInternal(const base::unique_fd& cookieTagMap, const base::uniqu int getIfaceNameFromMap(const base::unique_fd& ifaceMapFd, const base::unique_fd& statsMapFd, uint32_t ifaceIndex, char* ifname, void* curKey, int64_t* unknownIfaceBytesTotal); +// For test only +int parseBpfNetworkStatsDevInternal(std::vector<stats_line>* lines, + const base::unique_fd& statsMapFd, + const base::unique_fd& ifaceMapFd); int bpfGetUidStats(uid_t uid, struct Stats* stats); int bpfGetIfaceStats(const char* iface, struct Stats* stats); int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines, const std::vector<std::string>& limitIfaces, int limitTag, int limitUid); + +int parseBpfNetworkStatsDev(std::vector<stats_line>* lines); int cleanStatsMap(); } // namespace bpf } // namespace android |