Skip to content
Snippets Groups Projects
Commit 6db149aa authored by Maciej Żenczykowski's avatar Maciej Żenczykowski
Browse files

BpfNetworkStats: introduce IfIndexToNameFunc


Test: TreeHugger, atest libnetworkstats_test
Signed-off-by: default avatarMaciej Żenczykowski <maze@google.com>
Change-Id: I61edb3981c19718e177307c3df89de635598f2fd
parent 8f954453
No related branches found
No related tags found
No related merge requests found
......@@ -50,6 +50,10 @@ const BpfMapRO<uint32_t, StatsValue>& getIfaceStatsMap() {
return ifaceStatsMap;
}
Result<IfaceValue> ifindex2name(const uint32_t ifindex) {
return getIfaceIndexNameMap().readValue(ifindex);
}
void bpfRegisterIface(const char* iface) {
if (!iface) return;
if (strlen(iface) >= sizeof(IfaceValue)) return;
......@@ -78,14 +82,14 @@ int bpfGetUidStats(uid_t uid, StatsValue* stats) {
int bpfGetIfaceStatsInternal(const char* iface, StatsValue* stats,
const BpfMapRO<uint32_t, StatsValue>& ifaceStatsMap,
const BpfMapRO<uint32_t, IfaceValue>& ifaceNameMap) {
const IfIndexToNameFunc ifindex2name) {
*stats = {};
int64_t unknownIfaceBytesTotal = 0;
const auto processIfaceStats =
[iface, stats, &ifaceNameMap, &unknownIfaceBytesTotal](
[iface, stats, ifindex2name, &unknownIfaceBytesTotal](
const uint32_t& key,
const BpfMapRO<uint32_t, StatsValue>& ifaceStatsMap) -> Result<void> {
Result<IfaceValue> ifname = ifaceNameMap.readValue(key);
Result<IfaceValue> ifname = ifindex2name(key);
if (!ifname.ok()) {
maybeLogUnknownIface(key, ifaceStatsMap, key, &unknownIfaceBytesTotal);
return Result<void>();
......@@ -104,7 +108,7 @@ int bpfGetIfaceStatsInternal(const char* iface, StatsValue* stats,
}
int bpfGetIfaceStats(const char* iface, StatsValue* stats) {
return bpfGetIfaceStatsInternal(iface, stats, getIfaceStatsMap(), getIfaceIndexNameMap());
return bpfGetIfaceStatsInternal(iface, stats, getIfaceStatsMap(), ifindex2name);
}
int bpfGetIfIndexStatsInternal(uint32_t ifindex, StatsValue* stats,
......@@ -138,13 +142,13 @@ stats_line populateStatsEntry(const StatsKey& statsKey, const StatsValue& statsE
int parseBpfNetworkStatsDetailInternal(std::vector<stats_line>& lines,
const BpfMapRO<StatsKey, StatsValue>& statsMap,
const BpfMapRO<uint32_t, IfaceValue>& ifaceMap) {
const IfIndexToNameFunc ifindex2name) {
int64_t unknownIfaceBytesTotal = 0;
const auto processDetailUidStats =
[&lines, &unknownIfaceBytesTotal, &ifaceMap](
[&lines, &unknownIfaceBytesTotal, &ifindex2name](
const StatsKey& key,
const BpfMapRO<StatsKey, StatsValue>& statsMap) -> Result<void> {
Result<IfaceValue> ifname = ifaceMap.readValue(key.ifaceIndex);
Result<IfaceValue> ifname = ifindex2name(key.ifaceIndex);
if (!ifname.ok()) {
maybeLogUnknownIface(key.ifaceIndex, statsMap, key, &unknownIfaceBytesTotal);
return Result<void>();
......@@ -212,7 +216,7 @@ int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines) {
// TODO: the above comment feels like it may be obsolete / out of date,
// since we no longer swap the map via netd binder rpc - though we do
// still swap it.
int ret = parseBpfNetworkStatsDetailInternal(*lines, *inactiveStatsMap, getIfaceIndexNameMap());
int ret = parseBpfNetworkStatsDetailInternal(*lines, *inactiveStatsMap, ifindex2name);
if (ret) {
ALOGE("parse detail network stats failed: %s", strerror(errno));
return ret;
......@@ -229,12 +233,12 @@ int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines) {
int parseBpfNetworkStatsDevInternal(std::vector<stats_line>& lines,
const BpfMapRO<uint32_t, StatsValue>& statsMap,
const BpfMapRO<uint32_t, IfaceValue>& ifaceMap) {
const IfIndexToNameFunc ifindex2name) {
int64_t unknownIfaceBytesTotal = 0;
const auto processDetailIfaceStats = [&lines, &unknownIfaceBytesTotal, &ifaceMap, &statsMap](
const auto processDetailIfaceStats = [&lines, &unknownIfaceBytesTotal, ifindex2name, &statsMap](
const uint32_t& key, const StatsValue& value,
const BpfMapRO<uint32_t, StatsValue>&) {
Result<IfaceValue> ifname = ifaceMap.readValue(key);
Result<IfaceValue> ifname = ifindex2name(key);
if (!ifname.ok()) {
maybeLogUnknownIface(key, statsMap, key, &unknownIfaceBytesTotal);
return Result<void>();
......@@ -259,7 +263,7 @@ int parseBpfNetworkStatsDevInternal(std::vector<stats_line>& lines,
}
int parseBpfNetworkStatsDev(std::vector<stats_line>* lines) {
return parseBpfNetworkStatsDevInternal(*lines, getIfaceStatsMap(), getIfaceIndexNameMap());
return parseBpfNetworkStatsDevInternal(*lines, getIfaceStatsMap(), ifindex2name);
}
void groupNetworkStats(std::vector<stats_line>& lines) {
......
......@@ -77,6 +77,10 @@ class BpfNetworkStatsHelperTest : public testing::Test {
BpfMap<uint32_t, IfaceValue> mFakeIfaceIndexNameMap;
BpfMap<uint32_t, StatsValue> mFakeIfaceStatsMap;
IfIndexToNameFunc mIfIndex2Name = [this](const uint32_t ifindex){
return mFakeIfaceIndexNameMap.readValue(ifindex);
};
void SetUp() {
ASSERT_EQ(0, setrlimitForTest());
......@@ -228,7 +232,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetUidStatsTotal) {
populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET1, value1, mFakeStatsMap);
populateFakeStats(TEST_UID2, 0, IFACE_INDEX3, TEST_COUNTERSET1, value1, mFakeStatsMap);
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((unsigned long)3, lines.size());
}
......@@ -256,16 +260,15 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsInternal) {
EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
StatsValue result1 = {};
ASSERT_EQ(0, bpfGetIfaceStatsInternal(IFACE_NAME1, &result1, mFakeIfaceStatsMap,
mFakeIfaceIndexNameMap));
ASSERT_EQ(0,
bpfGetIfaceStatsInternal(IFACE_NAME1, &result1, mFakeIfaceStatsMap, mIfIndex2Name));
expectStatsEqual(value1, result1);
StatsValue result2 = {};
ASSERT_EQ(0, bpfGetIfaceStatsInternal(IFACE_NAME2, &result2, mFakeIfaceStatsMap,
mFakeIfaceIndexNameMap));
ASSERT_EQ(0,
bpfGetIfaceStatsInternal(IFACE_NAME2, &result2, mFakeIfaceStatsMap, mIfIndex2Name));
expectStatsEqual(value2, result2);
StatsValue totalResult = {};
ASSERT_EQ(0, bpfGetIfaceStatsInternal(NULL, &totalResult, mFakeIfaceStatsMap,
mFakeIfaceIndexNameMap));
ASSERT_EQ(0, bpfGetIfaceStatsInternal(NULL, &totalResult, mFakeIfaceStatsMap, mIfIndex2Name));
StatsValue totalValue = {
.rxPackets = TEST_PACKET0 * 2 + TEST_PACKET1,
.rxBytes = TEST_BYTES0 * 2 + TEST_BYTES1,
......@@ -304,7 +307,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetStatsDetail) {
mFakeStatsMap);
populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
std::vector<stats_line> lines;
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((unsigned long)7, lines.size());
}
......@@ -324,7 +327,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetStatsWithSkippedIface) {
populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET1, value1, mFakeStatsMap);
populateFakeStats(TEST_UID2, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
std::vector<stats_line> lines;
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((unsigned long)4, lines.size());
}
......@@ -365,7 +368,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestUnknownIfaceError) {
ASSERT_EQ(-1, unknownIfaceBytesTotal);
std::vector<stats_line> lines;
// TODO: find a way to test the total of unknown Iface Bytes go above limit.
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((unsigned long)1, lines.size());
expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines.front());
}
......@@ -396,8 +399,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsDetail) {
ifaceStatsKey = IFACE_INDEX4;
EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY));
std::vector<stats_line> lines;
ASSERT_EQ(0,
parseBpfNetworkStatsDevInternal(lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDevInternal(lines, mFakeIfaceStatsMap, mIfIndex2Name));
ASSERT_EQ((unsigned long)4, lines.size());
expectStatsLineEqual(value1, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
......@@ -441,13 +443,13 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortedAndGrouped) {
std::vector<stats_line> lines;
// Test empty stats.
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((size_t) 0, lines.size());
lines.clear();
// Test 1 line stats.
populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((size_t) 2, lines.size()); // TEST_TAG != 0 -> 1 entry becomes 2 lines
expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines[0]);
expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[1]);
......@@ -459,7 +461,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortedAndGrouped) {
populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, value2,
mFakeStatsMap);
populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((size_t) 9, lines.size());
lines.clear();
......@@ -467,7 +469,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortedAndGrouped) {
populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1, mFakeStatsMap);
populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1, mFakeStatsMap);
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((size_t) 9, lines.size());
// Verify Sorted & Grouped.
......@@ -492,8 +494,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortedAndGrouped) {
ifaceStatsKey = IFACE_INDEX3;
EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
ASSERT_EQ(0,
parseBpfNetworkStatsDevInternal(lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDevInternal(lines, mFakeIfaceStatsMap, mIfIndex2Name));
ASSERT_EQ((size_t) 2, lines.size());
expectStatsLineEqual(value3, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
......@@ -534,7 +535,7 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetStatsSortAndOverflow) {
// TODO: Mutate counterSet and enlarge TEST_MAP_SIZE if overflow on counterSet is possible.
std::vector<stats_line> lines;
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mIfIndex2Name));
ASSERT_EQ((size_t) 12, lines.size());
// Uid 0 first
......
......@@ -55,20 +55,25 @@ struct stats_line {
bool operator==(const stats_line& lhs, const stats_line& rhs);
bool operator<(const stats_line& lhs, const stats_line& rhs);
// This mirrors BpfMap.h's:
// Result<Value> readValue(const Key key) const
// for a BpfMap<uint32_t, IfaceValue>
using IfIndexToNameFunc = std::function<Result<IfaceValue>(const uint32_t)>;
// For test only
int bpfGetUidStatsInternal(uid_t uid, StatsValue* stats,
const BpfMapRO<uint32_t, StatsValue>& appUidStatsMap);
// For test only
int bpfGetIfaceStatsInternal(const char* iface, StatsValue* stats,
const BpfMapRO<uint32_t, StatsValue>& ifaceStatsMap,
const BpfMapRO<uint32_t, IfaceValue>& ifaceNameMap);
const IfIndexToNameFunc ifindex2name);
// For test only
int bpfGetIfIndexStatsInternal(uint32_t ifindex, StatsValue* stats,
const BpfMapRO<uint32_t, StatsValue>& ifaceStatsMap);
// For test only
int parseBpfNetworkStatsDetailInternal(std::vector<stats_line>& lines,
const BpfMapRO<StatsKey, StatsValue>& statsMap,
const BpfMapRO<uint32_t, IfaceValue>& ifaceMap);
const IfIndexToNameFunc ifindex2name);
// For test only
int cleanStatsMapInternal(const base::unique_fd& cookieTagMap, const base::unique_fd& tagStatsMap);
......@@ -98,7 +103,7 @@ void maybeLogUnknownIface(int ifaceIndex, const BpfMapRO<Key, StatsValue>& stats
// For test only
int parseBpfNetworkStatsDevInternal(std::vector<stats_line>& lines,
const BpfMapRO<uint32_t, StatsValue>& statsMap,
const BpfMapRO<uint32_t, IfaceValue>& ifaceMap);
const IfIndexToNameFunc ifindex2name);
void bpfRegisterIface(const char* iface);
int bpfGetUidStats(uid_t uid, StatsValue* stats);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment