Add method for reading stats by iface index
This change adds the nativeGetIfIndexStat JNI method, which can be used
to read the traffic stats associated with a specific iface index.
Test: Included unit test.
Bug: 241098920
Change-Id: I7a4adcb9610562ff01fe5cd1234d6dfc57f9408d
diff --git a/service-t/jni/com_android_server_net_NetworkStatsService.cpp b/service-t/jni/com_android_server_net_NetworkStatsService.cpp
index dab9d07..8d8dc32 100644
--- a/service-t/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/service-t/jni/com_android_server_net_NetworkStatsService.cpp
@@ -34,6 +34,7 @@
using android::bpf::bpfGetUidStats;
using android::bpf::bpfGetIfaceStats;
+using android::bpf::bpfGetIfIndexStats;
using android::bpf::NetworkTraceHandler;
namespace android {
@@ -94,6 +95,15 @@
}
}
+static jlong nativeGetIfIndexStat(JNIEnv* env, jclass clazz, jint ifindex, jint type) {
+ Stats stats = {};
+ if (bpfGetIfIndexStats(ifindex, &stats) == 0) {
+ return getStatsType(&stats, (StatsType) type);
+ } else {
+ return UNKNOWN;
+ }
+}
+
static jlong nativeGetUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
Stats stats = {};
@@ -111,6 +121,7 @@
static const JNINativeMethod gMethods[] = {
{"nativeGetTotalStat", "(I)J", (void*)nativeGetTotalStat},
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)nativeGetIfaceStat},
+ {"nativeGetIfIndexStat", "(II)J", (void*)nativeGetIfIndexStat},
{"nativeGetUidStat", "(II)J", (void*)nativeGetUidStat},
{"nativeInitNetworkTracing", "()V", (void*)nativeInitNetworkTracing},
};
diff --git a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
index 5579e43..2e6e3e5 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
@@ -105,6 +105,25 @@
return bpfGetIfaceStatsInternal(iface, stats, ifaceStatsMap, ifaceIndexNameMap);
}
+int bpfGetIfIndexStatsInternal(uint32_t ifindex, Stats* stats,
+ const BpfMap<uint32_t, StatsValue>& ifaceStatsMap) {
+ InitStats(stats);
+ auto statsEntry = ifaceStatsMap.readValue(ifindex);
+ if (statsEntry.ok()) {
+ stats->rxPackets = statsEntry.value().rxPackets;
+ stats->txPackets = statsEntry.value().txPackets;
+ stats->rxBytes = statsEntry.value().rxBytes;
+ stats->txBytes = statsEntry.value().txBytes;
+ return 0;
+ }
+ return (statsEntry.error().code() == ENOENT) ? 0 : -statsEntry.error().code();
+}
+
+int bpfGetIfIndexStats(int ifindex, Stats* stats) {
+ static BpfMapRO<uint32_t, StatsValue> ifaceStatsMap(IFACE_STATS_MAP_PATH);
+ return bpfGetIfIndexStatsInternal(ifindex, stats, ifaceStatsMap);
+}
+
stats_line populateStatsEntry(const StatsKey& statsKey, const StatsValue& statsEntry,
const char* ifname) {
stats_line newLine;
diff --git a/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
index ccd3f5e..4f85d9b 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
@@ -275,6 +275,20 @@
expectStatsEqual(totalValue, totalResult);
}
+TEST_F(BpfNetworkStatsHelperTest, TestGetIfIndexStatsInternal) {
+ StatsValue value = {
+ .rxPackets = TEST_PACKET0,
+ .rxBytes = TEST_BYTES0,
+ .txPackets = TEST_PACKET1,
+ .txBytes = TEST_BYTES1,
+ };
+ EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(IFACE_INDEX1, value, BPF_ANY));
+
+ Stats result = {};
+ ASSERT_EQ(0, bpfGetIfIndexStatsInternal(IFACE_INDEX1, &result, mFakeIfaceStatsMap));
+ expectStatsEqual(value, result);
+}
+
TEST_F(BpfNetworkStatsHelperTest, TestGetStatsDetail) {
updateIfaceMap(IFACE_NAME1, IFACE_INDEX1);
updateIfaceMap(IFACE_NAME2, IFACE_INDEX2);
diff --git a/service-t/native/libs/libnetworkstats/include/netdbpf/BpfNetworkStats.h b/service-t/native/libs/libnetworkstats/include/netdbpf/BpfNetworkStats.h
index 133009f..0a9c012 100644
--- a/service-t/native/libs/libnetworkstats/include/netdbpf/BpfNetworkStats.h
+++ b/service-t/native/libs/libnetworkstats/include/netdbpf/BpfNetworkStats.h
@@ -63,6 +63,9 @@
const BpfMap<uint32_t, StatsValue>& ifaceStatsMap,
const BpfMap<uint32_t, IfaceValue>& ifaceNameMap);
// For test only
+int bpfGetIfIndexStatsInternal(uint32_t ifindex, Stats* stats,
+ const BpfMap<uint32_t, StatsValue>& ifaceStatsMap);
+// For test only
int parseBpfNetworkStatsDetailInternal(std::vector<stats_line>& lines,
const BpfMap<StatsKey, StatsValue>& statsMap,
const BpfMap<uint32_t, IfaceValue>& ifaceMap);
@@ -112,6 +115,7 @@
int bpfGetUidStats(uid_t uid, Stats* stats);
int bpfGetIfaceStats(const char* iface, Stats* stats);
+int bpfGetIfIndexStats(int ifindex, Stats* stats);
int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines);
int parseBpfNetworkStatsDev(std::vector<stats_line>* lines);
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 6635fd3..3f4113a 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -3303,6 +3303,7 @@
private static native long nativeGetTotalStat(int type);
private static native long nativeGetIfaceStat(String iface, int type);
+ private static native long nativeGetIfIndexStat(int ifindex, int type);
private static native long nativeGetUidStat(int uid, int type);
/** Initializes and registers the Perfetto Network Trace data source */