From 07923dec2d94ae282608f3deda9bf7bc863ce62a Mon Sep 17 00:00:00 2001 From: Kevin Jeon Date: Fri, 4 Aug 2023 10:54:30 -0400 Subject: [PATCH] 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 --- ...android_server_net_NetworkStatsService.cpp | 11 +++++++++++ .../libs/libnetworkstats/BpfNetworkStats.cpp | 19 +++++++++++++++++++ .../libnetworkstats/BpfNetworkStatsTest.cpp | 14 ++++++++++++++ .../include/netdbpf/BpfNetworkStats.h | 4 ++++ .../server/net/NetworkStatsService.java | 1 + 5 files changed, 49 insertions(+) diff --git a/service-t/jni/com_android_server_net_NetworkStatsService.cpp b/service-t/jni/com_android_server_net_NetworkStatsService.cpp index dab9d07f09..8d8dc3236f 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 nativeGetIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint t } } +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 void nativeInitNetworkTracing(JNIEnv* env, jclass clazz) { 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 5579e43e95..2e6e3e5f71 100644 --- a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp +++ b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp @@ -105,6 +105,25 @@ int bpfGetIfaceStats(const char* iface, Stats* stats) { return bpfGetIfaceStatsInternal(iface, stats, ifaceStatsMap, ifaceIndexNameMap); } +int bpfGetIfIndexStatsInternal(uint32_t ifindex, Stats* stats, + const BpfMap& 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 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 ccd3f5e9f1..4f85d9b3ba 100644 --- a/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp +++ b/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp @@ -275,6 +275,20 @@ TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsInternal) { 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 133009f053..0a9c01271a 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 @@ int bpfGetIfaceStatsInternal(const char* iface, Stats* stats, const BpfMap& ifaceStatsMap, const BpfMap& ifaceNameMap); // For test only +int bpfGetIfIndexStatsInternal(uint32_t ifindex, Stats* stats, + const BpfMap& ifaceStatsMap); +// For test only int parseBpfNetworkStatsDetailInternal(std::vector& lines, const BpfMap& statsMap, const BpfMap& ifaceMap); @@ -112,6 +115,7 @@ int parseBpfNetworkStatsDevInternal(std::vector& lines, int bpfGetUidStats(uid_t uid, Stats* stats); int bpfGetIfaceStats(const char* iface, Stats* stats); +int bpfGetIfIndexStats(int ifindex, Stats* stats); int parseBpfNetworkStatsDetail(std::vector* lines); int parseBpfNetworkStatsDev(std::vector* lines); diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 6635fd3d6b..3f4113a458 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 @@ public class NetworkStatsService extends INetworkStatsService.Stub { 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 */