Dump counters in "dumpsys tethering bpf". am: 4e92da06fa
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1575051 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Ic0891b0982780186054e468541259f10c2b5ccf5
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_android_net_util_TetheringUtils(JNIEnv* env);
|
||||||
int register_com_android_networkstack_tethering_BpfMap(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*) {
|
extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
|
||||||
JNIEnv *env;
|
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_BpfMap(env) < 0) return JNI_ERR;
|
||||||
|
|
||||||
|
if (register_com_android_networkstack_tethering_BpfCoordinator(env) < 0) return JNI_ERR;
|
||||||
|
|
||||||
return JNI_VERSION_1_6;
|
return JNI_VERSION_1_6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
|||||||
import com.android.internal.util.IndentingPrintWriter;
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.modules.utils.build.SdkLevel;
|
import com.android.modules.utils.build.SdkLevel;
|
||||||
import com.android.net.module.util.NetworkStackConstants;
|
import com.android.net.module.util.NetworkStackConstants;
|
||||||
|
import com.android.net.module.util.Struct;
|
||||||
import com.android.networkstack.tethering.apishim.common.BpfCoordinatorShim;
|
import com.android.networkstack.tethering.apishim.common.BpfCoordinatorShim;
|
||||||
|
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
@@ -84,6 +85,13 @@ import java.util.Set;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class BpfCoordinator {
|
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 DOWNSTREAM = true;
|
||||||
static final boolean UPSTREAM = false;
|
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_UPSTREAM6_FS_PATH = makeMapPath(UPSTREAM, 6);
|
||||||
private static final String TETHER_STATS_MAP_PATH = makeMapPath("stats");
|
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_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) {
|
private static String makeMapPath(String which) {
|
||||||
return "/sys/fs/bpf/tethering/map_offload_tether_" + which + "_map";
|
return "/sys/fs/bpf/tethering/map_offload_tether_" + which + "_map";
|
||||||
@@ -717,6 +729,12 @@ public class BpfCoordinator {
|
|||||||
dumpIpv4ForwardingRules(pw);
|
dumpIpv4ForwardingRules(pw);
|
||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
|
|
||||||
|
pw.println();
|
||||||
|
pw.println("Forwarding counters:");
|
||||||
|
pw.increaseIndent();
|
||||||
|
dumpCounters(pw);
|
||||||
|
pw.decreaseIndent();
|
||||||
|
|
||||||
dumpDone.open();
|
dumpDone.open();
|
||||||
});
|
});
|
||||||
if (!dumpDone.block(DUMP_TIMEOUT_MS)) {
|
if (!dumpDone.block(DUMP_TIMEOUT_MS)) {
|
||||||
@@ -814,6 +832,36 @@ public class BpfCoordinator {
|
|||||||
pw.decreaseIndent();
|
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. */
|
/** IPv6 forwarding rule class. */
|
||||||
public static class Ipv6ForwardingRule {
|
public static class Ipv6ForwardingRule {
|
||||||
public final int upstreamIfindex;
|
public final int upstreamIfindex;
|
||||||
@@ -1296,4 +1344,6 @@ public class BpfCoordinator {
|
|||||||
final SparseArray<String> getInterfaceNamesForTesting() {
|
final SparseArray<String> getInterfaceNamesForTesting() {
|
||||||
return mInterfaceNames;
|
return mInterfaceNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native String[] getBpfCounterNames();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ java_defaults {
|
|||||||
// For mockito extended
|
// For mockito extended
|
||||||
"libdexmakerjvmtiagent",
|
"libdexmakerjvmtiagent",
|
||||||
"libstaticjvmtiagent",
|
"libstaticjvmtiagent",
|
||||||
|
"libtetherutilsjni",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user