Dump counters in "dumpsys tethering bpf". am: 4e92da06fa am: e033a1e543
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1575051 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Ib449565583901259f0c21764d566637eace5f5f8
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
|
||||
#include "bpf_tethering.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
static jobjectArray getBpfCounterNames(JNIEnv *env) {
|
||||
size_t size = BPF_TETHER_ERR__MAX;
|
||||
jobjectArray ret = env->NewObjectArray(size, env->FindClass("java/lang/String"), nullptr);
|
||||
for (int i = 0; i < size; i++) {
|
||||
env->SetObjectArrayElement(ret, i, env->NewStringUTF(bpf_tether_errors[i]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* JNI registration.
|
||||
*/
|
||||
static const JNINativeMethod gMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "getBpfCounterNames", "()[Ljava/lang/String;", (void*) getBpfCounterNames },
|
||||
};
|
||||
|
||||
int register_com_android_networkstack_tethering_BpfCoordinator(JNIEnv* env) {
|
||||
return jniRegisterNativeMethods(env,
|
||||
"com/android/networkstack/tethering/BpfCoordinator",
|
||||
gMethods, NELEM(gMethods));
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
@@ -24,6 +24,7 @@ namespace android {
|
||||
|
||||
int register_android_net_util_TetheringUtils(JNIEnv* env);
|
||||
int register_com_android_networkstack_tethering_BpfMap(JNIEnv* env);
|
||||
int register_com_android_networkstack_tethering_BpfCoordinator(JNIEnv* env);
|
||||
|
||||
extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
|
||||
JNIEnv *env;
|
||||
@@ -36,6 +37,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
|
||||
|
||||
if (register_com_android_networkstack_tethering_BpfMap(env) < 0) return JNI_ERR;
|
||||
|
||||
if (register_com_android_networkstack_tethering_BpfCoordinator(env) < 0) return JNI_ERR;
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.module.util.NetworkStackConstants;
|
||||
import com.android.net.module.util.Struct;
|
||||
import com.android.networkstack.tethering.apishim.common.BpfCoordinatorShim;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
@@ -84,6 +85,13 @@ import java.util.Set;
|
||||
* @hide
|
||||
*/
|
||||
public class BpfCoordinator {
|
||||
// Ensure the JNI code is loaded. In production this will already have been loaded by
|
||||
// TetherService, but for tests it needs to be either loaded here or loaded by every test.
|
||||
// TODO: is there a better way?
|
||||
static {
|
||||
System.loadLibrary("tetherutilsjni");
|
||||
}
|
||||
|
||||
static final boolean DOWNSTREAM = true;
|
||||
static final boolean UPSTREAM = false;
|
||||
|
||||
@@ -97,6 +105,10 @@ public class BpfCoordinator {
|
||||
private static final String TETHER_UPSTREAM6_FS_PATH = makeMapPath(UPSTREAM, 6);
|
||||
private static final String TETHER_STATS_MAP_PATH = makeMapPath("stats");
|
||||
private static final String TETHER_LIMIT_MAP_PATH = makeMapPath("limit");
|
||||
private static final String TETHER_ERROR_MAP_PATH = makeMapPath("error");
|
||||
|
||||
/** The names of all the BPF counters defined in bpf_tethering.h. */
|
||||
public static final String[] sBpfCounterNames = getBpfCounterNames();
|
||||
|
||||
private static String makeMapPath(String which) {
|
||||
return "/sys/fs/bpf/tethering/map_offload_tether_" + which + "_map";
|
||||
@@ -717,6 +729,12 @@ public class BpfCoordinator {
|
||||
dumpIpv4ForwardingRules(pw);
|
||||
pw.decreaseIndent();
|
||||
|
||||
pw.println();
|
||||
pw.println("Forwarding counters:");
|
||||
pw.increaseIndent();
|
||||
dumpCounters(pw);
|
||||
pw.decreaseIndent();
|
||||
|
||||
dumpDone.open();
|
||||
});
|
||||
if (!dumpDone.block(DUMP_TIMEOUT_MS)) {
|
||||
@@ -814,6 +832,36 @@ public class BpfCoordinator {
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple struct that only contains a u32. Must be public because Struct needs access to it.
|
||||
* TODO: make this a public inner class of Struct so anyone can use it as, e.g., Struct.U32?
|
||||
*/
|
||||
public static class U32Struct extends Struct {
|
||||
@Struct.Field(order = 0, type = Struct.Type.U32)
|
||||
public long val;
|
||||
}
|
||||
|
||||
private void dumpCounters(@NonNull IndentingPrintWriter pw) {
|
||||
try (BpfMap<U32Struct, U32Struct> map = new BpfMap<>(TETHER_ERROR_MAP_PATH,
|
||||
BpfMap.BPF_F_RDONLY, U32Struct.class, U32Struct.class)) {
|
||||
|
||||
map.forEach((k, v) -> {
|
||||
String counterName;
|
||||
try {
|
||||
counterName = sBpfCounterNames[(int) k.val];
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// Should never happen because this code gets the counter name from the same
|
||||
// include file as the BPF program that increments the counter.
|
||||
Log.wtf(TAG, "Unknown tethering counter type " + k.val);
|
||||
counterName = Long.toString(k.val);
|
||||
}
|
||||
if (v.val > 0) pw.println(String.format("%s: %d", counterName, v.val));
|
||||
});
|
||||
} catch (ErrnoException e) {
|
||||
pw.println("Error dumping counter map: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/** IPv6 forwarding rule class. */
|
||||
public static class Ipv6ForwardingRule {
|
||||
public final int upstreamIfindex;
|
||||
@@ -1296,4 +1344,6 @@ public class BpfCoordinator {
|
||||
final SparseArray<String> getInterfaceNamesForTesting() {
|
||||
return mInterfaceNames;
|
||||
}
|
||||
|
||||
private static native String[] getBpfCounterNames();
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ java_defaults {
|
||||
// For mockito extended
|
||||
"libdexmakerjvmtiagent",
|
||||
"libstaticjvmtiagent",
|
||||
"libtetherutilsjni",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user