Monitor interface added and update bpf interface map
Have BpfInterfaceMapUpdater to update bpf interface map: adding the interface and index mapping to bpf interface map when interface added. Bug: 215095957 Test: atest FrameworkNetTests Change-Id: I2189a50c4869cfc0c33fc6f0228f40ee9f3ac1d4
This commit is contained in:
@@ -26,6 +26,8 @@ filegroup {
|
||||
srcs: [
|
||||
"src/com/android/server/net/NetworkIdentity*.java",
|
||||
"src/com/android/server/net/NetworkStats*.java",
|
||||
"src/com/android/server/net/BpfInterfaceMapUpdater.java",
|
||||
"src/com/android/server/net/InterfaceMapValue.java",
|
||||
],
|
||||
path: "src",
|
||||
visibility: [
|
||||
@@ -97,3 +99,28 @@ filegroup {
|
||||
"//packages/modules/Connectivity:__subpackages__",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libcom_android_net_module_util_jni",
|
||||
min_sdk_version: "30",
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wthread-safety",
|
||||
],
|
||||
srcs: [
|
||||
"jni/onload.cpp",
|
||||
],
|
||||
stl: "libc++_static",
|
||||
static_libs: [
|
||||
"libnet_utils_device_common_bpfjni",
|
||||
],
|
||||
shared_libs: [
|
||||
"liblog",
|
||||
"libnativehelper",
|
||||
],
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
38
service-t/jni/onload.cpp
Normal file
38
service-t/jni/onload.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 <nativehelper/JNIHelp.h>
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
|
||||
|
||||
extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
|
||||
JNIEnv *env;
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
ALOGE("GetEnv failed");
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
if (register_com_android_net_module_util_BpfMap(env,
|
||||
"com/android/net/module/util/BpfMap") < 0) return JNI_ERR;
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
139
service-t/src/com/android/server/net/BpfInterfaceMapUpdater.java
Normal file
139
service-t/src/com/android/server/net/BpfInterfaceMapUpdater.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
package com.android.server.net;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.INetd;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.system.ErrnoException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
|
||||
import com.android.net.module.util.BpfMap;
|
||||
import com.android.net.module.util.IBpfMap;
|
||||
import com.android.net.module.util.InterfaceParams;
|
||||
import com.android.net.module.util.Struct.U32;
|
||||
|
||||
/**
|
||||
* Monitor interface added (without removed) and right interface name and its index to bpf map.
|
||||
*/
|
||||
public class BpfInterfaceMapUpdater {
|
||||
private static final String TAG = BpfInterfaceMapUpdater.class.getSimpleName();
|
||||
// This is current path but may be changed soon.
|
||||
private static final String IFACE_INDEX_NAME_MAP_PATH =
|
||||
"/sys/fs/bpf/map_netd_iface_index_name_map";
|
||||
private final IBpfMap<U32, InterfaceMapValue> mBpfMap;
|
||||
private final INetd mNetd;
|
||||
private final Handler mHandler;
|
||||
private final Dependencies mDeps;
|
||||
|
||||
public BpfInterfaceMapUpdater(Context ctx, Handler handler) {
|
||||
this(ctx, handler, new Dependencies());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public BpfInterfaceMapUpdater(Context ctx, Handler handler, Dependencies deps) {
|
||||
mDeps = deps;
|
||||
mBpfMap = deps.getInterfaceMap();
|
||||
mNetd = deps.getINetd(ctx);
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependencies of BpfInerfaceMapUpdater, for injection in tests.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static class Dependencies {
|
||||
/** Create BpfMap for updating interface and index mapping. */
|
||||
public IBpfMap<U32, InterfaceMapValue> getInterfaceMap() {
|
||||
try {
|
||||
return new BpfMap<>(IFACE_INDEX_NAME_MAP_PATH, BpfMap.BPF_F_RDWR,
|
||||
U32.class, InterfaceMapValue.class);
|
||||
} catch (ErrnoException e) {
|
||||
Log.e(TAG, "Cannot create interface map: " + e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get InterfaceParams for giving interface name. */
|
||||
public InterfaceParams getInterfaceParams(String ifaceName) {
|
||||
return InterfaceParams.getByName(ifaceName);
|
||||
}
|
||||
|
||||
/** Get INetd binder object. */
|
||||
public INetd getINetd(Context ctx) {
|
||||
return INetd.Stub.asInterface((IBinder) ctx.getSystemService(Context.NETD_SERVICE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start listening interface update event.
|
||||
* Query current interface names before listening.
|
||||
*/
|
||||
public void start() {
|
||||
mHandler.post(() -> {
|
||||
if (mBpfMap == null) {
|
||||
Log.wtf(TAG, "Fail to start: Null bpf map");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO: use a NetlinkMonitor and listen for RTM_NEWLINK messages instead.
|
||||
mNetd.registerUnsolicitedEventListener(new InterfaceChangeObserver());
|
||||
} catch (RemoteException e) {
|
||||
Log.wtf(TAG, "Unable to register netd UnsolicitedEventListener, " + e);
|
||||
}
|
||||
|
||||
final String[] ifaces;
|
||||
try {
|
||||
// TODO: use a netlink dump to get the current interface list.
|
||||
ifaces = mNetd.interfaceGetList();
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
Log.wtf(TAG, "Unable to query interface names by netd, " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
for (String ifaceName : ifaces) {
|
||||
addInterface(ifaceName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addInterface(String ifaceName) {
|
||||
final InterfaceParams iface = mDeps.getInterfaceParams(ifaceName);
|
||||
if (iface == null) {
|
||||
Log.e(TAG, "Unable to get InterfaceParams for " + ifaceName);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mBpfMap.updateEntry(new U32(iface.index), new InterfaceMapValue(ifaceName));
|
||||
} catch (ErrnoException e) {
|
||||
Log.e(TAG, "Unable to update entry for " + ifaceName + ", " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private class InterfaceChangeObserver extends BaseNetdUnsolicitedEventListener {
|
||||
@Override
|
||||
public void onInterfaceAdded(String ifName) {
|
||||
mHandler.post(() -> addInterface(ifName));
|
||||
}
|
||||
}
|
||||
}
|
||||
35
service-t/src/com/android/server/net/InterfaceMapValue.java
Normal file
35
service-t/src/com/android/server/net/InterfaceMapValue.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
package com.android.server.net;
|
||||
|
||||
import com.android.net.module.util.Struct;
|
||||
import com.android.net.module.util.Struct.Field;
|
||||
import com.android.net.module.util.Struct.Type;
|
||||
|
||||
/**
|
||||
* The value of bpf interface index map which is used for NetworkStatsService.
|
||||
*/
|
||||
public class InterfaceMapValue extends Struct {
|
||||
@Field(order = 0, type = Type.ByteArray, arraysize = 16)
|
||||
public final byte[] interfaceName;
|
||||
|
||||
public InterfaceMapValue(String iface) {
|
||||
final byte[] ifaceArray = iface.getBytes();
|
||||
interfaceName = new byte[16];
|
||||
// All array bytes after the interface name, if any, must be 0.
|
||||
System.arraycopy(ifaceArray, 0, interfaceName, 0, ifaceArray.length);
|
||||
}
|
||||
}
|
||||
@@ -356,6 +356,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
@NonNull
|
||||
private final LocationPermissionChecker mLocationPermissionChecker;
|
||||
|
||||
@NonNull
|
||||
private final BpfInterfaceMapUpdater mInterfaceMapUpdater;
|
||||
|
||||
private static @NonNull File getDefaultSystemDir() {
|
||||
return new File(Environment.getDataDirectory(), "system");
|
||||
}
|
||||
@@ -453,6 +456,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
|
||||
mNetworkStatsSubscriptionsMonitor);
|
||||
mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
|
||||
mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler);
|
||||
mInterfaceMapUpdater.start();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -507,6 +512,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
|
||||
return new LocationPermissionChecker(context);
|
||||
}
|
||||
|
||||
/** Create BpfInterfaceMapUpdater to update bpf interface map. */
|
||||
@NonNull
|
||||
public BpfInterfaceMapUpdater makeBpfInterfaceMapUpdater(
|
||||
@NonNull Context ctx, @NonNull Handler handler) {
|
||||
return new BpfInterfaceMapUpdater(ctx, handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user