Add BPF support for NetworkStatsService
Add the native implementation for NetworkStatsService to read the uidStatsMap and tagStatsMap to get the network traffic information. Currently the implementation only try to get the data from bpf for a reference but the final value returned is still from old xt_qtaguid module. So the result will not be effected. The bpf implementation is depending on libbpf inside netd. Bug: 30950746 Test: CtsNetTestCases -t android.net.cts.TrafficStatsTest Change-Id: Ia85e4d4d602f6bd536739d89085e6dc37ad82e15
This commit is contained in:
@@ -887,17 +887,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
|
||||
@Override
|
||||
public long getUidStats(int uid, int type) {
|
||||
return nativeGetUidStat(uid, type);
|
||||
return nativeGetUidStat(uid, type, checkBpfStatsEnable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getIfaceStats(String iface, int type) {
|
||||
return nativeGetIfaceStat(iface, type);
|
||||
return nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalStats(int type) {
|
||||
return nativeGetTotalStat(type);
|
||||
return nativeGetTotalStat(type, checkBpfStatsEnable());
|
||||
}
|
||||
|
||||
private boolean checkBpfStatsEnable() {
|
||||
return new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1668,7 +1672,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
private static int TYPE_TCP_RX_PACKETS;
|
||||
private static int TYPE_TCP_TX_PACKETS;
|
||||
|
||||
private static native long nativeGetTotalStat(int type);
|
||||
private static native long nativeGetIfaceStat(String iface, int type);
|
||||
private static native long nativeGetUidStat(int uid, int type);
|
||||
private static native long nativeGetTotalStat(int type, boolean useBpfStats);
|
||||
private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
|
||||
private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,15 @@
|
||||
#include <utils/misc.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "android-base/unique_fd.h"
|
||||
#include "bpf/BpfNetworkStats.h"
|
||||
#include "bpf/BpfUtils.h"
|
||||
|
||||
using android::bpf::Stats;
|
||||
using android::bpf::hasBpfSupport;
|
||||
using android::bpf::bpfGetUidStats;
|
||||
using android::bpf::bpfGetIfaceStats;
|
||||
|
||||
namespace android {
|
||||
|
||||
static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt";
|
||||
@@ -46,15 +55,6 @@ enum StatsType {
|
||||
TCP_TX_PACKETS = 5
|
||||
};
|
||||
|
||||
struct Stats {
|
||||
uint64_t rxBytes;
|
||||
uint64_t rxPackets;
|
||||
uint64_t txBytes;
|
||||
uint64_t txPackets;
|
||||
uint64_t tcpRxPackets;
|
||||
uint64_t tcpTxPackets;
|
||||
};
|
||||
|
||||
static uint64_t getStatsType(struct Stats* stats, StatsType type) {
|
||||
switch (type) {
|
||||
case RX_BYTES:
|
||||
@@ -150,9 +150,18 @@ static int parseUidStats(const uint32_t uid, struct Stats* stats) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
|
||||
static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
|
||||
struct Stats stats;
|
||||
memset(&stats, 0, sizeof(Stats));
|
||||
|
||||
if (useBpfStats) {
|
||||
if (bpfGetIfaceStats(NULL, &stats) == 0) {
|
||||
return getStatsType(&stats, (StatsType) type);
|
||||
} else {
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (parseIfaceStats(NULL, &stats) == 0) {
|
||||
return getStatsType(&stats, (StatsType) type);
|
||||
} else {
|
||||
@@ -160,7 +169,8 @@ static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
|
||||
}
|
||||
}
|
||||
|
||||
static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
|
||||
static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
|
||||
jboolean useBpfStats) {
|
||||
ScopedUtfChars iface8(env, iface);
|
||||
if (iface8.c_str() == NULL) {
|
||||
return UNKNOWN;
|
||||
@@ -168,6 +178,15 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
|
||||
|
||||
struct Stats stats;
|
||||
memset(&stats, 0, sizeof(Stats));
|
||||
|
||||
if (useBpfStats) {
|
||||
if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
|
||||
return getStatsType(&stats, (StatsType) type);
|
||||
} else {
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (parseIfaceStats(iface8.c_str(), &stats) == 0) {
|
||||
return getStatsType(&stats, (StatsType) type);
|
||||
} else {
|
||||
@@ -175,9 +194,18 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
|
||||
}
|
||||
}
|
||||
|
||||
static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
|
||||
static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
|
||||
struct Stats stats;
|
||||
memset(&stats, 0, sizeof(Stats));
|
||||
|
||||
if (useBpfStats) {
|
||||
if (bpfGetUidStats(uid, &stats) == 0) {
|
||||
return getStatsType(&stats, (StatsType) type);
|
||||
} else {
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (parseUidStats(uid, &stats) == 0) {
|
||||
return getStatsType(&stats, (StatsType) type);
|
||||
} else {
|
||||
@@ -186,9 +214,9 @@ static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
|
||||
}
|
||||
|
||||
static const JNINativeMethod gMethods[] = {
|
||||
{"nativeGetTotalStat", "(I)J", (void*) getTotalStat},
|
||||
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat},
|
||||
{"nativeGetUidStat", "(II)J", (void*) getUidStat},
|
||||
{"nativeGetTotalStat", "(IZ)J", (void*) getTotalStat},
|
||||
{"nativeGetIfaceStat", "(Ljava/lang/String;IZ)J", (void*) getIfaceStat},
|
||||
{"nativeGetUidStat", "(IIZ)J", (void*) getUidStat},
|
||||
};
|
||||
|
||||
int register_android_server_net_NetworkStatsService(JNIEnv* env) {
|
||||
|
||||
Reference in New Issue
Block a user