Take non-incremental network stats from bpf maps
Use two maps to record the details of network stats. Swap and clean up
after system server pulls the stats. The TAG_STATS_MAP is removed since
we don't need to worry about losing the stats for each uid if the eBPF map
is full. All the stats can be stored in the same map now and it is very
unlikely to overflow the map before system server scrapes the stats and
clean it up. Add a benchmark test to measure the performance of creating
and closing pf_key socket. A typical result is:
------------------------------------------------------------------------
Benchmark Time CPU Iterations
------------------------------------------------------------------------
BpfBenchMark/WaitForRcu/1 86615 ns 54858 ns 20209
Bug: 79171384
Test: dumpsys netd trafficcontroller
NetworkUsageStatsTest
Change-Id: Ic79e382f51bf21eee78c4cac5a8a97edaf3654cd
diff --git a/libnetdbpf/BpfNetworkStats.cpp b/libnetdbpf/BpfNetworkStats.cpp
index 907cdea..61ddea0 100644
--- a/libnetdbpf/BpfNetworkStats.cpp
+++ b/libnetdbpf/BpfNetworkStats.cpp
@@ -40,6 +40,8 @@
using netdutils::Status;
+static constexpr char const* STATS_MAP_PATH[] = {STATS_MAP_A_PATH, STATS_MAP_B_PATH};
+
static constexpr uint32_t BPF_OPEN_FLAGS = BPF_F_RDONLY;
int bpfGetUidStatsInternal(uid_t uid, Stats* stats,
@@ -60,7 +62,7 @@
if (!appUidStatsMap.isValid()) {
int ret = -errno;
- ALOGE("Opening appUidStatsMap(%s) failed: %s", UID_STATS_MAP_PATH, strerror(errno));
+ ALOGE("Opening appUidStatsMap(%s) failed: %s", APP_UID_STATS_MAP_PATH, strerror(errno));
return ret;
}
return bpfGetUidStatsInternal(uid, stats, appUidStatsMap);
@@ -179,41 +181,74 @@
int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines,
const std::vector<std::string>& limitIfaces, int limitTag,
int limitUid) {
- int ret = 0;
BpfMap<uint32_t, IfaceValue> ifaceIndexNameMap(
mapRetrieve(IFACE_INDEX_NAME_MAP_PATH, BPF_OPEN_FLAGS));
if (!ifaceIndexNameMap.isValid()) {
- ret = -errno;
+ int ret = -errno;
ALOGE("get ifaceIndexName map fd failed: %s", strerror(errno));
return ret;
}
- // If the caller did not pass in TAG_NONE, read tag data.
- if (limitTag != TAG_NONE) {
- BpfMap<StatsKey, StatsValue> tagStatsMap(mapRetrieve(TAG_STATS_MAP_PATH, BPF_OPEN_FLAGS));
- if (!tagStatsMap.isValid()) {
- ret = -errno;
- ALOGE("get tagStats map fd failed: %s", strerror(errno));
- return ret;
- }
- ret = parseBpfNetworkStatsDetailInternal(lines, limitIfaces, limitTag, limitUid,
- tagStatsMap, ifaceIndexNameMap);
- if (ret) return ret;
+ BpfMap<uint32_t, uint8_t> configurationMap(mapRetrieve(CONFIGURATION_MAP_PATH, 0));
+ if (!configurationMap.isValid()) {
+ int ret = -errno;
+ ALOGE("get configuration map fd failed: %s", strerror(errno));
+ return ret;
+ }
+ auto configuration = configurationMap.readValue(CURRENT_STATS_MAP_CONFIGURATION_KEY);
+ if (!isOk(configuration)) {
+ ALOGE("Cannot read the old configuration from map: %s",
+ configuration.status().msg().c_str());
+ return -configuration.status().code();
+ }
+ const char* statsMapPath = STATS_MAP_PATH[configuration.value()];
+ BpfMap<StatsKey, StatsValue> statsMap(mapRetrieve(statsMapPath, 0));
+ if (!statsMap.isValid()) {
+ int ret = -errno;
+ ALOGE("get stats map fd failed: %s, path: %s", strerror(errno), statsMapPath);
+ return ret;
}
- // If the caller did not pass in a specific tag (i.e., if limitTag is TAG_NONE(0) or
- // TAG_ALL(-1)) read UID data.
- if (limitTag == TAG_NONE || limitTag == TAG_ALL) {
- BpfMap<StatsKey, StatsValue> uidStatsMap(mapRetrieve(UID_STATS_MAP_PATH, BPF_OPEN_FLAGS));
- if (!uidStatsMap.isValid()) {
- ret = -errno;
- ALOGE("Opening map fd from %s failed: %s", UID_STATS_MAP_PATH, strerror(errno));
- return ret;
- }
- ret = parseBpfNetworkStatsDetailInternal(lines, limitIfaces, limitTag, limitUid,
- uidStatsMap, ifaceIndexNameMap);
+ // Write to the configuration map to inform the kernel eBPF program to switch
+ // from using one map to the other.
+ uint8_t newConfigure = (configuration.value() == SELECT_MAP_A) ? SELECT_MAP_B : SELECT_MAP_A;
+ Status res = configurationMap.writeValue(CURRENT_STATS_MAP_CONFIGURATION_KEY, newConfigure,
+ BPF_EXIST);
+ if (!isOk(res)) {
+ ALOGE("Failed to toggle the stats map: %s", strerror(res.code()));
+ return -res.code();
}
- return ret;
+
+ // After changing the config, we need to make sure all the current running
+ // eBPF programs are finished and all the CPUs are aware of this config change
+ // before we modify the old map. So we do a special hack here to wait for
+ // the kernel to do a synchronize_rcu(). Once the kernel called
+ // synchronize_rcu(), the config we just updated will be available to all cores
+ // and the next eBPF programs triggered inside the kernel will use the new
+ // map configuration. So once this function returns we can safely modify the
+ // old stats map without concerning about race between the kernel and
+ // userspace.
+ int ret = synchronizeKernelRCU();
+ if (ret) {
+ ALOGE("map swap synchronize_rcu() ended with failure: %s", strerror(-ret));
+ return ret;
+ }
+
+ // It is safe to read and clear the old map now.
+ ret = parseBpfNetworkStatsDetailInternal(lines, limitIfaces, limitTag, limitUid, statsMap,
+ ifaceIndexNameMap);
+ if (ret) {
+ ALOGE("parse detail network stats failed: %s", strerror(errno));
+ return ret;
+ }
+
+ res = statsMap.clear();
+ if (!isOk(res)) {
+ ALOGE("Clean up current stats map failed: %s", strerror(res.code()));
+ return -res.code();
+ }
+
+ return 0;
}
int parseBpfNetworkStatsDevInternal(std::vector<stats_line>* lines,
diff --git a/libnetdbpf/BpfNetworkStatsTest.cpp b/libnetdbpf/BpfNetworkStatsTest.cpp
index aa73144..0d17677 100644
--- a/libnetdbpf/BpfNetworkStatsTest.cpp
+++ b/libnetdbpf/BpfNetworkStatsTest.cpp
@@ -77,8 +77,7 @@
BpfNetworkStatsHelperTest() {}
BpfMap<uint64_t, UidTag> mFakeCookieTagMap;
BpfMap<uint32_t, StatsValue> mFakeAppUidStatsMap;
- BpfMap<StatsKey, StatsValue> mFakeUidStatsMap;
- BpfMap<StatsKey, StatsValue> mFakeTagStatsMap;
+ BpfMap<StatsKey, StatsValue> mFakeStatsMap;
BpfMap<uint32_t, IfaceValue> mFakeIfaceIndexNameMap;
BpfMap<uint32_t, StatsValue> mFakeIfaceStatsMap;
@@ -93,15 +92,10 @@
BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
ASSERT_LE(0, mFakeAppUidStatsMap.getMap());
- mFakeUidStatsMap =
- BpfMap<StatsKey, StatsValue>(createMap(BPF_MAP_TYPE_HASH, sizeof(struct StatsKey),
- sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
- ASSERT_LE(0, mFakeUidStatsMap.getMap());
-
- mFakeTagStatsMap =
- BpfMap<StatsKey, StatsValue>(createMap(BPF_MAP_TYPE_HASH, sizeof(struct StatsKey),
- sizeof(struct StatsValue), TEST_MAP_SIZE, 0));
- ASSERT_LE(0, mFakeTagStatsMap.getMap());
+ mFakeStatsMap = BpfMap<StatsKey, StatsValue>(
+ createMap(BPF_MAP_TYPE_HASH, sizeof(struct StatsKey), sizeof(struct StatsValue),
+ TEST_MAP_SIZE, 0));
+ ASSERT_LE(0, mFakeStatsMap.getMap());
mFakeIfaceIndexNameMap = BpfMap<uint32_t, IfaceValue>(
createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(IfaceValue), TEST_MAP_SIZE, 0));
@@ -234,15 +228,15 @@
expectStatsEqual(value2, result2);
std::vector<stats_line> lines;
std::vector<std::string> ifaces;
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET1, value1, mFakeUidStatsMap);
- populateFakeStats(TEST_UID2, 0, IFACE_INDEX3, TEST_COUNTERSET1, value1, mFakeUidStatsMap);
+ 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, ifaces, TAG_ALL, TEST_UID1,
- mFakeUidStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)2, lines.size());
lines.clear();
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
- mFakeUidStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)1, lines.size());
expectStatsLineEqual(value1, IFACE_NAME3, TEST_UID2, TEST_COUNTERSET1, 0, lines.front());
}
@@ -301,28 +295,28 @@
.rxPackets = TEST_PACKET0,
.txBytes = TEST_BYTES1,
.txPackets = TEST_PACKET1,};
- populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
- populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
+ populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeStatsMap);
populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, value1,
- mFakeTagStatsMap);
- populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
+ mFakeStatsMap);
+ populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
std::vector<stats_line> lines;
std::vector<std::string> ifaces;
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
+ mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)4, lines.size());
lines.clear();
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)3, lines.size());
lines.clear();
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)2, lines.size());
lines.clear();
ifaces.push_back(std::string(IFACE_NAME1));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)1, lines.size());
expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines.front());
}
@@ -336,29 +330,29 @@
.rxPackets = TEST_PACKET0,
.txBytes = TEST_BYTES1,
.txPackets = TEST_PACKET1,};
- populateFakeStats(0, 0, 0, OVERFLOW_COUNTERSET, value1, mFakeUidStatsMap);
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET1, value1, mFakeUidStatsMap);
- populateFakeStats(TEST_UID2, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
+ populateFakeStats(0, 0, 0, OVERFLOW_COUNTERSET, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ 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;
std::vector<std::string> ifaces;
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
- mFakeUidStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
+ mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)4, lines.size());
lines.clear();
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
- mFakeUidStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)3, lines.size());
lines.clear();
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
- mFakeUidStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)1, lines.size());
expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, 0, lines.front());
lines.clear();
ifaces.push_back(std::string(IFACE_NAME1));
ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
- mFakeUidStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)2, lines.size());
}
@@ -371,31 +365,31 @@
.txBytes = TEST_BYTES1 * 20,
.txPackets = TEST_PACKET1,};
uint32_t ifaceIndex = UNKNOWN_IFACE;
- populateFakeStats(TEST_UID1, 0, ifaceIndex, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeUidStatsMap);
+ populateFakeStats(TEST_UID1, 0, ifaceIndex, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
StatsValue value2 = {.rxBytes = TEST_BYTES0 * 40,
.rxPackets = TEST_PACKET0,
.txBytes = TEST_BYTES1 * 40,
.txPackets = TEST_PACKET1,};
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value2, mFakeUidStatsMap);
+ populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value2, mFakeStatsMap);
StatsKey curKey = {.uid = TEST_UID1,
.tag = 0,
.ifaceIndex = ifaceIndex,
.counterSet = TEST_COUNTERSET0};
char ifname[IFNAMSIZ];
int64_t unknownIfaceBytesTotal = 0;
- ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeUidStatsMap, ifaceIndex,
+ ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeStatsMap, ifaceIndex,
ifname, curKey, &unknownIfaceBytesTotal));
ASSERT_EQ(((int64_t)(TEST_BYTES0 * 20 + TEST_BYTES1 * 20)), unknownIfaceBytesTotal);
curKey.ifaceIndex = IFACE_INDEX2;
- ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeUidStatsMap, ifaceIndex,
+ ASSERT_EQ(-ENODEV, getIfaceNameFromMap(mFakeIfaceIndexNameMap, mFakeStatsMap, ifaceIndex,
ifname, curKey, &unknownIfaceBytesTotal));
ASSERT_EQ(-1, unknownIfaceBytesTotal);
std::vector<stats_line> lines;
std::vector<std::string> ifaces;
// TODO: find a way to test the total of unknown Iface Bytes go above limit.
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
- mFakeUidStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
+ mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)1, lines.size());
expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines.front());
}
@@ -470,42 +464,36 @@
std::vector<std::string> ifaces;
// Test empty stats.
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
+ mFakeIfaceIndexNameMap));
ASSERT_EQ((size_t) 0, lines.size());
lines.clear();
// Test 1 line stats.
- populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1,
- mFakeTagStatsMap);
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
+ mFakeIfaceIndexNameMap));
ASSERT_EQ((size_t) 1, lines.size());
expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[0]);
lines.clear();
// These items should not be grouped.
- populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, value2,
- mFakeTagStatsMap);
- populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET1, value2,
- mFakeTagStatsMap);
+ populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX2, TEST_COUNTERSET0, value2, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET1, value2, mFakeStatsMap);
populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, value2,
- mFakeTagStatsMap);
- populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1,
- mFakeTagStatsMap);
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ mFakeStatsMap);
+ populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
+ mFakeIfaceIndexNameMap));
ASSERT_EQ((size_t) 5, lines.size());
lines.clear();
// These items should be grouped.
- populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1,
- mFakeTagStatsMap);
- populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1,
- mFakeTagStatsMap);
+ 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, ifaces, TAG_ALL, UID_ALL,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
+ mFakeIfaceIndexNameMap));
ASSERT_EQ((size_t) 5, lines.size());
// Verify Sorted & Grouped.
@@ -550,24 +538,23 @@
};
// Mutate uid, 0 < TEST_UID1 < INT_MAX < INT_MIN < UINT_MAX.
- populateFakeStats(0, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
- populateFakeStats(UINT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
- populateFakeStats(INT_MIN, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
- populateFakeStats(INT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
+ populateFakeStats(0, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(UINT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(INT_MIN, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(INT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
// Mutate tag, 0 < TEST_TAG < INT_MAX < INT_MIN < UINT_MAX.
- populateFakeStats(TEST_UID1, INT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
- populateFakeStats(TEST_UID1, INT_MIN, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeTagStatsMap);
- populateFakeStats(TEST_UID1, UINT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1,
- mFakeTagStatsMap);
+ populateFakeStats(TEST_UID1, INT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, INT_MIN, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, UINT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
// TODO: Mutate counterSet and enlarge TEST_MAP_SIZE if overflow on counterSet is possible.
std::vector<stats_line> lines;
std::vector<std::string> ifaces;
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL,
- mFakeTagStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
+ mFakeIfaceIndexNameMap));
ASSERT_EQ((size_t) 8, lines.size());
// Uid 0 first
diff --git a/libnetdbpf/include/netdbpf/bpf_shared.h b/libnetdbpf/include/netdbpf/bpf_shared.h
index f824e08..127dd75 100644
--- a/libnetdbpf/include/netdbpf/bpf_shared.h
+++ b/libnetdbpf/include/netdbpf/bpf_shared.h
@@ -46,11 +46,11 @@
const int COOKIE_UID_MAP_SIZE = 10000;
const int UID_COUNTERSET_MAP_SIZE = 2000;
-const int UID_STATS_MAP_SIZE = 10000;
-const int TAG_STATS_MAP_SIZE = 10000;
+const int APP_STATS_MAP_SIZE = 10000;
+const int STATS_MAP_SIZE = 5000;
const int IFACE_INDEX_NAME_MAP_SIZE = 1000;
const int IFACE_STATS_MAP_SIZE = 1000;
-const int CONFIGURATION_MAP_SIZE = 1;
+const int CONFIGURATION_MAP_SIZE = 2;
const int UID_OWNER_MAP_SIZE = 2000;
#define BPF_PATH "/sys/fs/bpf"
@@ -65,8 +65,8 @@
#define COOKIE_TAG_MAP_PATH BPF_PATH "/map_netd_cookie_tag_map"
#define UID_COUNTERSET_MAP_PATH BPF_PATH "/map_netd_uid_counterset_map"
#define APP_UID_STATS_MAP_PATH BPF_PATH "/map_netd_app_uid_stats_map"
-#define UID_STATS_MAP_PATH BPF_PATH "/map_netd_uid_stats_map"
-#define TAG_STATS_MAP_PATH BPF_PATH "/map_netd_tag_stats_map"
+#define STATS_MAP_A_PATH BPF_PATH "/map_netd_stats_map_A"
+#define STATS_MAP_B_PATH BPF_PATH "/map_netd_stats_map_B"
#define IFACE_INDEX_NAME_MAP_PATH BPF_PATH "/map_netd_iface_index_name_map"
#define IFACE_STATS_MAP_PATH BPF_PATH "/map_netd_iface_stats_map"
#define CONFIGURATION_MAP_PATH BPF_PATH "/map_netd_configuration_map"
@@ -82,6 +82,14 @@
POWERSAVE_MATCH = (1 << 4),
};
+// In production we use two identical stats maps to record per uid stats and
+// do swap and clean based on the configuration specified here. The statsMapType
+// value in configuration map specified which map is currently in use.
+enum StatsMapType {
+ SELECT_MAP_A,
+ SELECT_MAP_B,
+};
+
// TODO: change the configuration object from an 8-bit bitmask to an object with clearer
// semantics, like a struct.
typedef uint8_t BpfConfig;
@@ -93,6 +101,7 @@
// NetdConstants.h can also include it from there.
#define MIN_SYSTEM_UID 0
#define MAX_SYSTEM_UID 9999
-#define CONFIGURATION_KEY 1
+#define UID_RULES_CONFIGURATION_KEY 1
+#define CURRENT_STATS_MAP_CONFIGURATION_KEY 2
#endif // NETDBPF_BPF_SHARED_H
diff --git a/server/TrafficController.cpp b/server/TrafficController.cpp
index b921c9a..93d0101 100644
--- a/server/TrafficController.cpp
+++ b/server/TrafficController.cpp
@@ -137,7 +137,7 @@
// chmod doesn't grant permission to all processes in that group to
// read/write the bpf map. They still need correct sepolicy to
// read/write the map.
- ret = chmod(path, S_IRWXU | S_IRGRP);
+ ret = chmod(path, S_IRWXU | S_IRGRP | S_IWGRP);
}
if (ret != 0) return statusFromErrno(errno, StringPrintf("change %s mode failed", debugName));
return netdutils::status::ok;
@@ -160,20 +160,16 @@
RETURN_IF_NOT_OK(changeOwnerAndMode(UID_COUNTERSET_MAP_PATH, AID_NET_BW_ACCT,
"UidCounterSetMap", false));
- RETURN_IF_NOT_OK(
- mAppUidStatsMap.getOrCreate(UID_STATS_MAP_SIZE, APP_UID_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
+ RETURN_IF_NOT_OK(mAppUidStatsMap.getOrCreate(APP_STATS_MAP_SIZE, APP_UID_STATS_MAP_PATH,
+ BPF_MAP_TYPE_HASH));
RETURN_IF_NOT_OK(
changeOwnerAndMode(APP_UID_STATS_MAP_PATH, AID_NET_BW_STATS, "AppUidStatsMap", false));
- RETURN_IF_NOT_OK(
- mUidStatsMap.getOrCreate(UID_STATS_MAP_SIZE, UID_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
- RETURN_IF_NOT_OK(changeOwnerAndMode(UID_STATS_MAP_PATH, AID_NET_BW_STATS, "UidStatsMap",
- false));
+ RETURN_IF_NOT_OK(mStatsMapA.getOrCreate(STATS_MAP_SIZE, STATS_MAP_A_PATH, BPF_MAP_TYPE_HASH));
+ RETURN_IF_NOT_OK(changeOwnerAndMode(STATS_MAP_A_PATH, AID_NET_BW_STATS, "StatsMapA", false));
- RETURN_IF_NOT_OK(
- mTagStatsMap.getOrCreate(TAG_STATS_MAP_SIZE, TAG_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
- RETURN_IF_NOT_OK(changeOwnerAndMode(TAG_STATS_MAP_PATH, AID_NET_BW_STATS, "TagStatsMap",
- false));
+ RETURN_IF_NOT_OK(mStatsMapB.getOrCreate(STATS_MAP_SIZE, STATS_MAP_B_PATH, BPF_MAP_TYPE_HASH));
+ RETURN_IF_NOT_OK(changeOwnerAndMode(STATS_MAP_B_PATH, AID_NET_BW_STATS, "StatsMapB", false));
RETURN_IF_NOT_OK(mIfaceIndexNameMap.getOrCreate(IFACE_INDEX_NAME_MAP_SIZE,
IFACE_INDEX_NAME_MAP_PATH, BPF_MAP_TYPE_HASH));
@@ -187,11 +183,12 @@
RETURN_IF_NOT_OK(mConfigurationMap.getOrCreate(CONFIGURATION_MAP_SIZE, CONFIGURATION_MAP_PATH,
BPF_MAP_TYPE_HASH));
+ RETURN_IF_NOT_OK(changeOwnerAndMode(CONFIGURATION_MAP_PATH, AID_NET_BW_STATS,
+ "ConfigurationMap", false));
RETURN_IF_NOT_OK(
- changeOwnerAndMode(CONFIGURATION_MAP_PATH, AID_ROOT, "ConfigurationMap", true));
- uint32_t key = CONFIGURATION_KEY;
- uint8_t initialConfiguration = DEFAULT_CONFIG;
- RETURN_IF_NOT_OK(mConfigurationMap.writeValue(key, initialConfiguration, BPF_ANY));
+ mConfigurationMap.writeValue(UID_RULES_CONFIGURATION_KEY, DEFAULT_CONFIG, BPF_ANY));
+ RETURN_IF_NOT_OK(mConfigurationMap.writeValue(CURRENT_STATS_MAP_CONFIGURATION_KEY, SELECT_MAP_A,
+ BPF_ANY));
RETURN_IF_NOT_OK(
mUidOwnerMap.getOrCreate(UID_OWNER_MAP_SIZE, UID_OWNER_MAP_PATH, BPF_MAP_TYPE_HASH));
@@ -357,6 +354,9 @@
return 0;
}
+// This method only get called by system_server when an app get uinstalled, it
+// is called inside removeUidsLocked() while holding mStatsLock. So it is safe
+// to iterate and modify the stats maps.
int TrafficController::deleteTagData(uint32_t tag, uid_t uid) {
if (!ebpfSupported) {
if (legacy_deleteTagData(tag, uid)) return -errno;
@@ -393,7 +393,8 @@
}
return netdutils::status::ok;
};
- mTagStatsMap.iterate(deleteMatchedUidTagEntries).ignoreError();
+ mStatsMapB.iterate(deleteMatchedUidTagEntries).ignoreError();
+ mStatsMapA.iterate(deleteMatchedUidTagEntries).ignoreError();
// If the tag is not zero, we already deleted all the data entry required. If tag is 0, we also
// need to delete the stats stored in uidStatsMap and counterSet map.
if (tag != 0) return 0;
@@ -403,7 +404,6 @@
ALOGE("Failed to delete counterSet data(uid=%u, tag=%u): %s\n", uid, tag,
strerror(res.code()));
}
- mUidStatsMap.iterate(deleteMatchedUidTagEntries).ignoreError();
auto deleteAppUidStatsEntry = [uid](const uint32_t& key, BpfMap<uint32_t, StatsValue>& map) {
if (key == uid) {
@@ -603,7 +603,7 @@
int TrafficController::toggleUidOwnerMap(ChildChain chain, bool enable) {
std::lock_guard guard(mOwnerMatchMutex);
- uint32_t key = CONFIGURATION_KEY;
+ uint32_t key = UID_RULES_CONFIGURATION_KEY;
auto oldConfiguration = mConfigurationMap.readValue(key);
if (!isOk(oldConfiguration)) {
ALOGE("Cannot read the old configuration from map: %s",
@@ -689,10 +689,10 @@
getMapStatus(mUidCounterSetMap.getMap(), UID_COUNTERSET_MAP_PATH).c_str());
dw.println("mAppUidStatsMap status: %s",
getMapStatus(mAppUidStatsMap.getMap(), APP_UID_STATS_MAP_PATH).c_str());
- dw.println("mUidStatsMap status: %s",
- getMapStatus(mUidStatsMap.getMap(), UID_STATS_MAP_PATH).c_str());
- dw.println("mTagStatsMap status: %s",
- getMapStatus(mTagStatsMap.getMap(), TAG_STATS_MAP_PATH).c_str());
+ dw.println("mStatsMapA status: %s",
+ getMapStatus(mStatsMapA.getMap(), STATS_MAP_A_PATH).c_str());
+ dw.println("mStatsMapB status: %s",
+ getMapStatus(mStatsMapB.getMap(), STATS_MAP_B_PATH).c_str());
dw.println("mIfaceIndexNameMap status: %s",
getMapStatus(mIfaceIndexNameMap.getMap(), IFACE_INDEX_NAME_MAP_PATH).c_str());
dw.println("mIfaceStatsMap status: %s",
@@ -765,7 +765,7 @@
// Print uidStatsMap content
std::string statsHeader = StringPrintf("ifaceIndex ifaceName tag_hex uid_int cnt_set rxBytes"
" rxPackets txBytes txPackets");
- dumpBpfMap("mUidStatsMap", dw, statsHeader);
+ dumpBpfMap("mStatsMapA", dw, statsHeader);
const auto printStatsInfo = [&dw, this](const StatsKey& key, const StatsValue& value,
const BpfMap<StatsKey, StatsValue>&) {
uint32_t ifIndex = key.ifaceIndex;
@@ -778,16 +778,16 @@
value.rxPackets, value.txBytes, value.txPackets);
return netdutils::status::ok;
};
- res = mUidStatsMap.iterateWithValue(printStatsInfo);
+ res = mStatsMapA.iterateWithValue(printStatsInfo);
if (!isOk(res)) {
- dw.println("mUidStatsMap print end with error: %s", res.msg().c_str());
+ dw.println("mStatsMapA print end with error: %s", res.msg().c_str());
}
// Print TagStatsMap content.
- dumpBpfMap("mTagStatsMap", dw, statsHeader);
- res = mTagStatsMap.iterateWithValue(printStatsInfo);
+ dumpBpfMap("mStatsMapB", dw, statsHeader);
+ res = mStatsMapB.iterateWithValue(printStatsInfo);
if (!isOk(res)) {
- dw.println("mTagStatsMap print end with error: %s", res.msg().c_str());
+ dw.println("mStatsMapB print end with error: %s", res.msg().c_str());
}
// Print ifaceIndexToNameMap content.
@@ -824,12 +824,21 @@
dw.blankline();
- uint32_t key = CONFIGURATION_KEY;
+ uint32_t key = UID_RULES_CONFIGURATION_KEY;
auto configuration = mConfigurationMap.readValue(key);
if (isOk(configuration)) {
- dw.println("current configuration: %d", configuration.value());
+ dw.println("current ownerMatch configuration: %d", configuration.value());
} else {
- dw.println("mConfigurationMap read with error: %s", configuration.status().msg().c_str());
+ dw.println("mConfigurationMap read ownerMatch configure failed with error: %s",
+ configuration.status().msg().c_str());
+ }
+ key = CURRENT_STATS_MAP_CONFIGURATION_KEY;
+ configuration = mConfigurationMap.readValue(key);
+ if (isOk(configuration)) {
+ dw.println("current statsMap configuration: %d", configuration.value());
+ } else {
+ dw.println("mConfigurationMap read stats map configure failed with error: %s",
+ configuration.status().msg().c_str());
}
dumpBpfMap("mUidOwnerMap", dw, "");
const auto printUidMatchInfo = [&dw](const uint32_t& key, const uint8_t& value,
diff --git a/server/TrafficController.h b/server/TrafficController.h
index f089351..c66bc36 100644
--- a/server/TrafficController.h
+++ b/server/TrafficController.h
@@ -145,27 +145,17 @@
BpfMap<uint32_t, StatsValue> mAppUidStatsMap;
/*
- * mUidStatsMap: Store the traffic statistics for a specific combination of
- * uid, iface and counterSet. We maintain this map in addition to
- * mTagStatsMap because we want to be able to track per-UID data usage even
- * if mTagStatsMap is full.
- * Map Key: Struct StatsKey contains the uid, counterSet and ifaceIndex
- * information. The Tag in the StatsKey should always be 0.
+ * mStatsMapA/mStatsMapB: Store the traffic statistics for a specific
+ * combination of uid, tag, iface and counterSet. These two maps contain
+ * both tagged and untagged traffic.
+ * Map Key: Struct StatsKey contains the uid, tag, counterSet and ifaceIndex
+ * information.
* Map Value: struct Stats, contains packet count and byte count of each
* transport protocol on egress and ingress direction.
*/
- BpfMap<StatsKey, StatsValue> mUidStatsMap;
+ BpfMap<StatsKey, StatsValue> mStatsMapA;
- /*
- * mTagStatsMap: Store the traffic statistics for a specific combination of
- * uid, tag, iface and counterSet. Only tagged socket stats should be stored
- * in this map.
- * Map Key: Struct StatsKey contains the uid, counterSet and ifaceIndex
- * information. The tag field should not be 0.
- * Map Value: struct Stats, contains packet count and byte count of each
- * transport protocol on egress and ingress direction.
- */
- BpfMap<StatsKey, StatsValue> mTagStatsMap;
+ BpfMap<StatsKey, StatsValue> mStatsMapB;
/*
* mIfaceIndexNameMap: Store the index name pair of each interface show up
@@ -181,8 +171,16 @@
BpfMap<uint32_t, StatsValue> mIfaceStatsMap;
/*
- * mPowerSaveUidMap: Store uids that have related rules in power save mode owner match
- * chain.
+ * mConfigurationMap: Store the current network policy about uid filtering
+ * and the current stats map in use. There are two configuration entries in
+ * the map right now:
+ * - Entry with UID_RULES_CONFIGURATION_KEY:
+ * Store the configuration for the current uid rules. It indicates the device
+ * is in doze/powersave/standby mode.
+ * - Entry with CURRENT_STATS_MAP_CONFIGURATION_KEY:
+ * Stores the current live stats map that kernel program is writing to.
+ * Userspace can do scraping and cleaning job on the other one depending on the
+ * current configs.
*/
BpfMap<uint32_t, uint8_t> mConfigurationMap GUARDED_BY(mOwnerMatchMutex);
diff --git a/server/TrafficControllerTest.cpp b/server/TrafficControllerTest.cpp
index 61622d8..2bc374c 100644
--- a/server/TrafficControllerTest.cpp
+++ b/server/TrafficControllerTest.cpp
@@ -115,8 +115,8 @@
mTc.mCookieTagMap.reset(mFakeCookieTagMap.getMap());
mTc.mUidCounterSetMap.reset(mFakeUidCounterSetMap.getMap());
mTc.mAppUidStatsMap.reset(mFakeAppUidStatsMap.getMap());
- mTc.mUidStatsMap.reset(mFakeUidStatsMap.getMap());
- mTc.mTagStatsMap.reset(mFakeTagStatsMap.getMap());
+ mTc.mStatsMapA.reset(mFakeUidStatsMap.getMap());
+ mTc.mStatsMapB.reset(mFakeTagStatsMap.getMap());
mTc.mConfigurationMap.reset(mFakeConfigurationMap.getMap());
mTc.mUidOwnerMap.reset(mFakeUidOwnerMap.getMap());
}
diff --git a/tests/benchmarks/bpf_benchmark.cpp b/tests/benchmarks/bpf_benchmark.cpp
index c7d518d..9146923 100644
--- a/tests/benchmarks/bpf_benchmark.cpp
+++ b/tests/benchmarks/bpf_benchmark.cpp
@@ -14,12 +14,15 @@
* limitations under the License.
*/
+#include <android-base/stringprintf.h>
#include <benchmark/benchmark.h>
#include "bpf/BpfMap.h"
#include "bpf/BpfUtils.h"
+
constexpr uint32_t TEST_MAP_SIZE = 10000;
+using android::base::StringPrintf;
using android::bpf::BpfMap;
class BpfBenchMark : public ::benchmark::Fixture {
@@ -51,7 +54,18 @@
}
}
+BENCHMARK_DEFINE_F(BpfBenchMark, WaitForRcu)(benchmark::State& state) {
+ for (auto _ : state) {
+ int ret = android::bpf::synchronizeKernelRCU();
+ if (ret) {
+ state.SkipWithError(
+ StringPrintf("synchronizeKernelRCU() failed with errno=%d", -ret).c_str());
+ }
+ }
+}
+
BENCHMARK_REGISTER_F(BpfBenchMark, MapUpdateEntry)->Arg(1);
BENCHMARK_REGISTER_F(BpfBenchMark, MapWriteNewEntry)->Arg(1);
BENCHMARK_REGISTER_F(BpfBenchMark, MapDeleteAddEntry)->Arg(1);
+BENCHMARK_REGISTER_F(BpfBenchMark, WaitForRcu)->Arg(1);
BENCHMARK_MAIN();
diff --git a/tests/bpf_base_test.cpp b/tests/bpf_base_test.cpp
index f62c324..0b32de7 100644
--- a/tests/bpf_base_test.cpp
+++ b/tests/bpf_base_test.cpp
@@ -72,8 +72,8 @@
ASSERT_EQ(0, access(XT_BPF_EGRESS_PROG_PATH, R_OK));
ASSERT_EQ(0, access(COOKIE_TAG_MAP_PATH, R_OK));
ASSERT_EQ(0, access(UID_COUNTERSET_MAP_PATH, R_OK));
- ASSERT_EQ(0, access(UID_STATS_MAP_PATH, R_OK));
- ASSERT_EQ(0, access(TAG_STATS_MAP_PATH, R_OK));
+ ASSERT_EQ(0, access(STATS_MAP_A_PATH, R_OK));
+ ASSERT_EQ(0, access(STATS_MAP_B_PATH, R_OK));
ASSERT_EQ(0, access(IFACE_INDEX_NAME_MAP_PATH, R_OK));
ASSERT_EQ(0, access(IFACE_STATS_MAP_PATH, R_OK));
ASSERT_EQ(0, access(CONFIGURATION_MAP_PATH, R_OK));
@@ -146,29 +146,29 @@
TEST_F(BpfBasicTest, TestDeleteTagData) {
SKIP_IF_BPF_NOT_SUPPORTED;
- BpfMap<StatsKey, StatsValue> uidStatsMap(mapRetrieve(UID_STATS_MAP_PATH, 0));
- ASSERT_LE(0, uidStatsMap.getMap());
- BpfMap<StatsKey, StatsValue> tagStatsMap(mapRetrieve(TAG_STATS_MAP_PATH, 0));
- ASSERT_LE(0, tagStatsMap.getMap());
+ BpfMap<StatsKey, StatsValue> statsMapA(mapRetrieve(STATS_MAP_A_PATH, 0));
+ ASSERT_LE(0, statsMapA.getMap());
+ BpfMap<StatsKey, StatsValue> statsMapB(mapRetrieve(STATS_MAP_B_PATH, 0));
+ ASSERT_LE(0, statsMapB.getMap());
BpfMap<uint32_t, StatsValue> appUidStatsMap(mapRetrieve(APP_UID_STATS_MAP_PATH, 0));
ASSERT_LE(0, appUidStatsMap.getMap());
StatsKey key = {.uid = TEST_UID, .tag = TEST_TAG, .counterSet = TEST_COUNTERSET,
.ifaceIndex = 1};
StatsValue statsMapValue = {.rxPackets = 1, .rxBytes = 100};
- EXPECT_TRUE(isOk(tagStatsMap.writeValue(key, statsMapValue, BPF_ANY)));
+ EXPECT_TRUE(isOk(statsMapB.writeValue(key, statsMapValue, BPF_ANY)));
key.tag = 0;
- EXPECT_TRUE(isOk(uidStatsMap.writeValue(key, statsMapValue, BPF_ANY)));
+ EXPECT_TRUE(isOk(statsMapA.writeValue(key, statsMapValue, BPF_ANY)));
EXPECT_TRUE(isOk(appUidStatsMap.writeValue(TEST_UID, statsMapValue, BPF_ANY)));
ASSERT_EQ(0, qtaguid_deleteTagData(0, TEST_UID));
- StatusOr<StatsValue> statsResult = uidStatsMap.readValue(key);
+ StatusOr<StatsValue> statsResult = statsMapA.readValue(key);
ASSERT_FALSE(isOk(statsResult));
ASSERT_EQ(ENOENT, statsResult.status().code());
statsResult = appUidStatsMap.readValue(TEST_UID);
ASSERT_FALSE(isOk(statsResult));
ASSERT_EQ(ENOENT, statsResult.status().code());
key.tag = TEST_TAG;
- statsResult = tagStatsMap.readValue(key);
+ statsResult = statsMapB.readValue(key);
ASSERT_FALSE(isOk(statsResult));
ASSERT_EQ(ENOENT, statsResult.status().code());
}