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

Commit 804be4a3 authored by Chenbo Feng's avatar Chenbo Feng
Browse files

Use eBPF map data for per iface stats

After adding the xt_bpf module and ifaceStatsMap, eBPF tool can now
support reading per interface data. So networkStatsFactory should move
away from parsing proc/net/dev and use the eBPF map stats instead.

Bug: 72111305
Test: atest com.android.server.net.NetworkStatsServiceTest
Change-Id: Ibcc6150d00835b3bd33af22a72e4a86e172581cf
Merged-In: Ibcc6150d00835b3bd33af22a72e4a86e172581cf
(cherry picked from aosp commit dcc56783)
parent a6b7a6fb
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -178,6 +178,14 @@ public class NetworkStatsFactory {
        return stats;
    }

    public NetworkStats readBpfNetworkStatsDev() throws IOException {
        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
        if (nativeReadNetworkStatsDev(stats) != 0) {
            throw new IOException("Failed to parse bpf iface stats");
        }
        return stats;
    }

    /**
     * Parse and return interface-level summary {@link NetworkStats} measured
     * using {@code /proc/net/dev} style hooks, which may include non IP layer
@@ -188,9 +196,9 @@ public class NetworkStatsFactory {
     */
    public NetworkStats readNetworkStatsSummaryDev() throws IOException {

        // Return the stats get from /proc/net/dev if switched to bpf module.
        // Return xt_bpf stats if switched to bpf module.
        if (mUseBpfStats)
            return readNetworkStatsIfaceDev();
            return readBpfNetworkStatsDev();

        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();

@@ -244,9 +252,9 @@ public class NetworkStatsFactory {
     */
    public NetworkStats readNetworkStatsSummaryXt() throws IOException {

        // Return the stats get from /proc/net/dev if qtaguid  module is replaced.
        // Return xt_bpf stats if qtaguid  module is replaced.
        if (mUseBpfStats)
            return readNetworkStatsIfaceDev();
            return readBpfNetworkStatsDev();

        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();

@@ -408,4 +416,7 @@ public class NetworkStatsFactory {
    @VisibleForTesting
    public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
        int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);

    @VisibleForTesting
    public static native int nativeReadNetworkStatsDev(NetworkStats stats);
}
+48 −33
Original line number Diff line number Diff line
@@ -205,37 +205,8 @@ static int legacyReadNetworkStatsDetail(std::vector<stats_line>* lines,
    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;
    }

static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats,
                            std::vector<stats_line>& lines) {
    int size = lines.size();

    bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
@@ -308,14 +279,58 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstr
        env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray());
        env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray());
    }

    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;
    }

    return statsLinesToNetworkStats(env, clazz, stats, lines);
}

static int readNetworkStatsDev(JNIEnv* env, jclass clazz, jobject stats) {
    std::vector<stats_line> lines;

    if (parseBpfNetworkStatsDev(&lines) < 0)
            return -1;

    return statsLinesToNetworkStats(env, clazz, stats, lines);
}

static const JNINativeMethod gMethods[] = {
        { "nativeReadNetworkStatsDetail",
                "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
                (void*) readNetworkStatsDetail }
                (void*) readNetworkStatsDetail },
        { "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I",
                (void*) readNetworkStatsDev },
};

int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) {