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: [
|
srcs: [
|
||||||
"src/com/android/server/net/NetworkIdentity*.java",
|
"src/com/android/server/net/NetworkIdentity*.java",
|
||||||
"src/com/android/server/net/NetworkStats*.java",
|
"src/com/android/server/net/NetworkStats*.java",
|
||||||
|
"src/com/android/server/net/BpfInterfaceMapUpdater.java",
|
||||||
|
"src/com/android/server/net/InterfaceMapValue.java",
|
||||||
],
|
],
|
||||||
path: "src",
|
path: "src",
|
||||||
visibility: [
|
visibility: [
|
||||||
@@ -97,3 +99,28 @@ filegroup {
|
|||||||
"//packages/modules/Connectivity:__subpackages__",
|
"//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
|
@NonNull
|
||||||
private final LocationPermissionChecker mLocationPermissionChecker;
|
private final LocationPermissionChecker mLocationPermissionChecker;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final BpfInterfaceMapUpdater mInterfaceMapUpdater;
|
||||||
|
|
||||||
private static @NonNull File getDefaultSystemDir() {
|
private static @NonNull File getDefaultSystemDir() {
|
||||||
return new File(Environment.getDataDirectory(), "system");
|
return new File(Environment.getDataDirectory(), "system");
|
||||||
}
|
}
|
||||||
@@ -453,6 +456,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
|
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
|
||||||
mNetworkStatsSubscriptionsMonitor);
|
mNetworkStatsSubscriptionsMonitor);
|
||||||
mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
|
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) {
|
public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
|
||||||
return new LocationPermissionChecker(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