Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e041f382 authored by Chenbo Feng's avatar Chenbo Feng Committed by android-build-merger
Browse files

Merge changes from topic "bpfStats"

am: 6e032246

Change-Id: I488be110cca66990f44f6e45d5489ce23f36432e
parents 50b8d3ef 6e032246
Loading
Loading
Loading
Loading
+63 −5
Original line number Diff line number Diff line
@@ -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);
}
+2 −0
Original line number Diff line number Diff line
@@ -215,6 +215,8 @@ cc_library_shared {
    ],

    shared_libs: [
        "libbpf",
        "libnetdutils",
        "libmemtrack",
        "libandroidfw",
        "libappfuse",
+48 −37
Original line number Diff line number Diff line
@@ -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 }
};

+1 −1
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+10 −6
Original line number Diff line number Diff line
@@ -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);
}
Loading