Use /proc/net/dev to get stats summary

If the qtaguid proc file is no longer exist, the device is running new
eBPF module to do traffic accounting. So the NetworkStatsFactory need to
use the proc/net/dev interface to get the per interface traffic stats
summary. Also, adding a test to verify the helper function work properly

Bug: 30950746
Test: run NetworkStatsFactoryTest
Change-Id: Ia36808bf02f1637dd41a3e7c50917b91b1a77524
This commit is contained in:
Chenbo Feng
2018-01-18 19:48:52 -08:00
parent adfda6945d
commit 75a1efb3f5

View File

@@ -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}. */
@@ -84,12 +90,51 @@ public class NetworkStatsFactory {
@VisibleForTesting
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;
}
/**
* Parse and return interface-level summary {@link NetworkStats} measured
* using {@code /proc/net/dev} style hooks, which may include non IP layer
@@ -99,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);
@@ -150,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