summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chenbo Feng <fengc@google.com> 2018-01-24 05:39:54 +0000
committer android-build-merger <android-build-merger@google.com> 2018-01-24 05:39:54 +0000
commitcf4b551fb76a3dd5bfa8f5c3e9fd6ef890f84d3b (patch)
treeee0fe3b1dd9ab2b6e97bef64e7fd436a5d5647f3
parent9d5d23b69ae172c39f9056723c4fd2425a8abcc8 (diff)
parente041f38289a5d31bcb52cba013e21704dcf30948 (diff)
Merge changes from topic "bpfStats" am: 6e03224697
am: e041f38289 Change-Id: Ib4790159fd331858ce9f3343a44ccec66fae638c
-rw-r--r--core/java/com/android/internal/net/NetworkStatsFactory.java68
-rw-r--r--core/jni/Android.bp2
-rw-r--r--core/jni/com_android_internal_net_NetworkStatsFactory.cpp85
-rw-r--r--core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java16
-rw-r--r--services/core/jni/Android.bp2
-rw-r--r--services/core/jni/com_android_server_net_NetworkStatsService.cpp58
-rw-r--r--tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java16
-rw-r--r--tests/net/res/raw/net_dev_typical8
9 files changed, 192 insertions, 65 deletions
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index b576a20db53a..902bd120e811 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -31,13 +31,17 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ProcFileReader;
+import com.google.android.collect.Lists;
import libcore.io.IoUtils;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.net.ProtocolException;
+import java.util.ArrayList;
import java.util.Objects;
/**
@@ -55,6 +59,8 @@ public class NetworkStatsFactory {
// Used for correct stats accounting on clatd interfaces.
private static final int IPV4V6_HEADER_DELTA = 20;
+ /** Path to {@code /proc/net/dev}. */
+ private final File mStatsIfaceDev;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
private final File mStatsXtIfaceAll;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
@@ -62,6 +68,8 @@ public class NetworkStatsFactory {
/** Path to {@code /proc/net/xt_qtaguid/stats}. */
private final File mStatsXtUid;
+ private boolean mUseBpfStats;
+
// TODO: to improve testability and avoid global state, do not use a static variable.
@GuardedBy("sStackedIfaces")
private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>();
@@ -77,14 +85,54 @@ public class NetworkStatsFactory {
}
public NetworkStatsFactory() {
- this(new File("/proc/"));
+ this(new File("/proc/"), new File("/sys/fs/bpf/traffic_uid_stats_map").exists());
}
@VisibleForTesting
- public NetworkStatsFactory(File procRoot) {
+ public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
+ mStatsIfaceDev = new File(procRoot, "net/dev");
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
+ mUseBpfStats = useBpfStats;
+ }
+
+ @VisibleForTesting
+ public NetworkStats readNetworkStatsIfaceDev() throws IOException {
+ final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
+
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(mStatsIfaceDev));
+
+ // skip first two header lines
+ reader.readLine();
+ reader.readLine();
+
+ // parse remaining lines
+ String line;
+ while ((line = reader.readLine()) != null) {
+ String[] values = line.trim().split("\\:?\\s+");
+ entry.iface = values[0];
+ entry.uid = UID_ALL;
+ entry.set = SET_ALL;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = Long.parseLong(values[1]);
+ entry.rxPackets = Long.parseLong(values[2]);
+ entry.txBytes = Long.parseLong(values[9]);
+ entry.txPackets = Long.parseLong(values[10]);
+ stats.addValues(entry);
+ }
+ } catch (NullPointerException|NumberFormatException e) {
+ throw new ProtocolException("problem parsing stats", e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ StrictMode.setThreadPolicy(savedPolicy);
+ }
+ return stats;
}
/**
@@ -96,6 +144,11 @@ public class NetworkStatsFactory {
* @throws IllegalStateException when problem parsing stats.
*/
public NetworkStats readNetworkStatsSummaryDev() throws IOException {
+
+ // Return the stats get from /proc/net/dev if switched to bpf module.
+ if (mUseBpfStats)
+ return readNetworkStatsIfaceDev();
+
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
@@ -147,6 +200,11 @@ public class NetworkStatsFactory {
* @throws IllegalStateException when problem parsing stats.
*/
public NetworkStats readNetworkStatsSummaryXt() throws IOException {
+
+ // Return the stats get from /proc/net/dev if qtaguid module is replaced.
+ if (mUseBpfStats)
+ return readNetworkStatsIfaceDev();
+
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
// return null when kernel doesn't support
@@ -252,7 +310,7 @@ public class NetworkStatsFactory {
stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
}
if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid,
- limitIfaces, limitTag) != 0) {
+ limitIfaces, limitTag, mUseBpfStats) != 0) {
throw new IOException("Failed to parse network stats");
}
if (SANITY_CHECK_NATIVE) {
@@ -346,6 +404,6 @@ public class NetworkStatsFactory {
* are expected to monotonically increase since device boot.
*/
@VisibleForTesting
- public static native int nativeReadNetworkStatsDetail(
- NetworkStats stats, String path, int limitUid, String[] limitIfaces, int limitTag);
+ public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
+ int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index bc98716ebc9c..b3fb43d58656 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -215,6 +215,8 @@ cc_library_shared {
],
shared_libs: [
+ "libbpf",
+ "libnetdutils",
"libmemtrack",
"libandroidfw",
"libappfuse",
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index d254de65f765..99d983957075 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -30,7 +30,14 @@
#include <utils/Log.h>
#include <utils/misc.h>
-#include <utils/Vector.h>
+
+#include "android-base/unique_fd.h"
+#include "bpf/BpfNetworkStats.h"
+#include "bpf/BpfUtils.h"
+
+using android::bpf::hasBpfSupport;
+using android::bpf::parseBpfNetworkStatsDetail;
+using android::bpf::stats_line;
namespace android {
@@ -53,17 +60,6 @@ static struct {
jfieldID operations;
} gNetworkStatsClassInfo;
-struct stats_line {
- char iface[32];
- int32_t uid;
- int32_t set;
- int32_t tag;
- int64_t rxBytes;
- int64_t rxPackets;
- int64_t txBytes;
- int64_t txPackets;
-};
-
static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
{
if (!grow) {
@@ -97,33 +93,14 @@ static jlongArray get_long_array(JNIEnv* env, jobject obj, jfieldID field, int s
return env->NewLongArray(size);
}
-static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
- jstring path, jint limitUid, jobjectArray limitIfacesObj, jint limitTag) {
- ScopedUtfChars path8(env, path);
- if (path8.c_str() == NULL) {
- return -1;
- }
-
- FILE *fp = fopen(path8.c_str(), "r");
+static int legacyReadNetworkStatsDetail(std::vector<stats_line>* lines,
+ const std::vector<std::string>& limitIfaces,
+ int limitTag, int limitUid, const char* path) {
+ FILE* fp = fopen(path, "r");
if (fp == NULL) {
return -1;
}
- Vector<String8> limitIfaces;
- if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
- int num = env->GetArrayLength(limitIfacesObj);
- limitIfaces.setCapacity(num);
- for (int i=0; i<num; i++) {
- jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
- ScopedUtfChars string8(env, string);
- if (string8.c_str() != NULL) {
- limitIfaces.add(String8(string8.c_str()));
- }
- }
- }
-
- Vector<stats_line> lines;
-
int lastIdx = 1;
int idx;
char buffer[384];
@@ -215,7 +192,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
//ALOGI("skipping due to uid: %s", buffer);
continue;
}
- lines.push_back(s);
+ lines->push_back(s);
} else {
//ALOGI("skipping due to bad remaining fields: %s", pos);
}
@@ -225,8 +202,42 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
ALOGE("Failed to close netstats file");
return -1;
}
+ return 0;
+}
+
+static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
+ jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
+ jboolean useBpfStats) {
+ ScopedUtfChars path8(env, path);
+ if (path8.c_str() == NULL) {
+ return -1;
+ }
+
+ std::vector<std::string> limitIfaces;
+ if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
+ int num = env->GetArrayLength(limitIfacesObj);
+ for (int i = 0; i < num; i++) {
+ jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
+ ScopedUtfChars string8(env, string);
+ if (string8.c_str() != NULL) {
+ limitIfaces.push_back(std::string(string8.c_str()));
+ }
+ }
+ }
+ std::vector<stats_line> lines;
+
+
+ if (useBpfStats) {
+ if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
+ return -1;
+ } else {
+ if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
+ limitUid, path8.c_str()) < 0)
+ return -1;
+ }
int size = lines.size();
+
bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
ScopedLocalRef<jobjectArray> iface(env, get_string_array(env, stats,
@@ -303,7 +314,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
static const JNINativeMethod gMethods[] = {
{ "nativeReadNetworkStatsDetail",
- "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;I)I",
+ "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
(void*) readNetworkStatsDetail }
};
diff --git a/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java b/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java
index e62fbd6568f7..c2134649655a 100644
--- a/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java
+++ b/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java
@@ -53,7 +53,7 @@ public class NetworkStatsFactoryBenchmark {
stats, mStats.getAbsolutePath(), NetworkStats.UID_ALL,
// Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70
// Fixed compilation problem but needs addressing properly.
- new String[0], 999);
+ new String[0], 999, false);
}
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 78fd4b49237a..bfc150e1a9b0 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -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);
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 04fd3e35b5e9..fc2ea60fd15e 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -95,6 +95,8 @@ cc_defaults {
"libhwbinder",
"libutils",
"libhwui",
+ "libbpf",
+ "libnetdutils",
"android.hardware.audio.common@2.0",
"android.hardware.broadcastradio@1.0",
"android.hardware.broadcastradio@1.1",
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 8de24e556511..3302dea53506 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -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) {
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index 56b8e608dad1..b14f5509b709 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -67,7 +67,7 @@ public class NetworkStatsFactoryTest {
IoUtils.deleteContents(mTestProc);
}
- mFactory = new NetworkStatsFactory(mTestProc);
+ mFactory = new NetworkStatsFactory(mTestProc, false);
}
@After
@@ -116,6 +116,20 @@ public class NetworkStatsFactoryTest {
}
@Test
+ public void testNetworkStatsSummary() throws Exception {
+ stageFile(R.raw.net_dev_typical, file("net/dev"));
+
+ final NetworkStats stats = mFactory.readNetworkStatsIfaceDev();
+ assertEquals(6, stats.size());
+ assertStatsEntry(stats, "lo", UID_ALL, SET_ALL, TAG_NONE, 8308L, 8308L);
+ assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 1507570L, 489339L);
+ assertStatsEntry(stats, "ifb0", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
+ assertStatsEntry(stats, "ifb1", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
+ assertStatsEntry(stats, "sit0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
+ assertStatsEntry(stats, "ip6tnl0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
+ }
+
+ @Test
public void testNetworkStatsSingle() throws Exception {
stageFile(R.raw.xt_qtaguid_iface_typical, file("net/xt_qtaguid/iface_stat_all"));
diff --git a/tests/net/res/raw/net_dev_typical b/tests/net/res/raw/net_dev_typical
new file mode 100644
index 000000000000..290bf03eb9b4
--- /dev/null
+++ b/tests/net/res/raw/net_dev_typical
@@ -0,0 +1,8 @@
+Inter-| Receive | Transmit
+ face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
+ lo: 8308 116 0 0 0 0 0 0 8308 116 0 0 0 0 0 0
+rmnet0: 1507570 2205 0 0 0 0 0 0 489339 2237 0 0 0 0 0 0
+ ifb0: 52454 151 0 151 0 0 0 0 0 0 0 0 0 0 0 0
+ ifb1: 52454 151 0 151 0 0 0 0 0 0 0 0 0 0 0 0
+ sit0: 0 0 0 0 0 0 0 0 0 0 148 0 0 0 0 0
+ip6tnl0: 0 0 0 0 0 0 0 0 0 0 151 151 0 0 0 0