Creating interface name to index tracking for Bpf Maps.
Adding mechanism to track interaface name to interface index, this map would be used by BpfNetMaps for storing interface index. Bug: 400681214 Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.connectivity.InterfaceTrackerTest Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.BpfNetMapsTest Change-Id: I2a65cac908d9c4d10714e3fe26be20322d4a1db3
This commit is contained in:
parent
a4b6164304
commit
53ecd95072
9 changed files with 357 additions and 45 deletions
|
|
@ -21,7 +21,6 @@ import static android.net.NetworkStats.TAG_ALL;
|
|||
import static android.net.NetworkStats.UID_ALL;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.net.NetworkStats;
|
||||
import android.net.UnderlyingNetworkInfo;
|
||||
|
|
@ -31,6 +30,7 @@ import android.os.SystemClock;
|
|||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.BpfNetMaps;
|
||||
import com.android.server.connectivity.InterfaceTracker;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
|
|
@ -108,7 +108,7 @@ public class NetworkStatsFactory {
|
|||
|
||||
/** Create a new {@link BpfNetMaps}. */
|
||||
public BpfNetMaps createBpfNetMaps(@NonNull Context ctx) {
|
||||
return new BpfNetMaps(ctx);
|
||||
return new BpfNetMaps(ctx, new InterfaceTracker(ctx));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ import static com.android.server.connectivity.NetworkPermissions.TRAFFIC_PERMISS
|
|||
import static com.android.server.connectivity.NetworkPermissions.TRAFFIC_PERMISSION_UNINSTALLED;
|
||||
import static com.android.server.connectivity.NetworkPermissions.TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.StatsManager;
|
||||
import android.content.Context;
|
||||
import android.net.BpfNetMapsUtils;
|
||||
|
|
@ -85,12 +87,14 @@ import com.android.net.module.util.bpf.CookieTagMapValue;
|
|||
import com.android.net.module.util.bpf.IngressDiscardKey;
|
||||
import com.android.net.module.util.bpf.IngressDiscardValue;
|
||||
import com.android.net.module.util.bpf.LocalNetAccessKey;
|
||||
import com.android.server.connectivity.InterfaceTracker;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
|
|
@ -142,6 +146,7 @@ public class BpfNetMaps {
|
|||
Pair.create(TRAFFIC_PERMISSION_INTERNET, "PERMISSION_INTERNET"),
|
||||
Pair.create(TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS, "PERMISSION_UPDATE_DEVICE_STATS")
|
||||
);
|
||||
private final InterfaceTracker mInterfaceTracker;
|
||||
|
||||
/**
|
||||
* Set configurationMap for test.
|
||||
|
|
@ -423,23 +428,27 @@ public class BpfNetMaps {
|
|||
|
||||
/** Constructor used after T that doesn't need to use netd anymore. */
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
public BpfNetMaps(final Context context) {
|
||||
this(context, null);
|
||||
public BpfNetMaps(final Context context, @NonNull final InterfaceTracker interfaceTracker) {
|
||||
this(context, null, interfaceTracker);
|
||||
|
||||
if (!SdkLevel.isAtLeastT()) throw new IllegalArgumentException("BpfNetMaps need to use netd before T");
|
||||
}
|
||||
|
||||
public BpfNetMaps(final Context context, final INetd netd) {
|
||||
this(context, netd, new Dependencies());
|
||||
public BpfNetMaps(final Context context, final INetd netd, @NonNull final InterfaceTracker
|
||||
interfaceTracker) {
|
||||
this(context, netd, new Dependencies(), interfaceTracker);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public BpfNetMaps(final Context context, final INetd netd, final Dependencies deps) {
|
||||
public BpfNetMaps(final Context context, final INetd netd, final Dependencies deps,
|
||||
@NonNull final InterfaceTracker interfaceTracker) {
|
||||
Objects.requireNonNull(interfaceTracker);
|
||||
if (SdkLevel.isAtLeastT()) {
|
||||
ensureInitialized(context);
|
||||
}
|
||||
mNetd = netd;
|
||||
mDeps = deps;
|
||||
mInterfaceTracker = interfaceTracker;
|
||||
}
|
||||
|
||||
private void maybeThrow(final int err, final String msg) {
|
||||
|
|
@ -902,7 +911,7 @@ public class BpfNetMaps {
|
|||
* @param isAllowed is the local network call allowed or blocked.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.CUR_DEVELOPMENT)
|
||||
public void addLocalNetAccess(final int lpmBitlen, final String iface,
|
||||
public void addLocalNetAccess(final int lpmBitlen, @Nullable final String iface,
|
||||
final InetAddress address, final int protocol, final int remotePort,
|
||||
final boolean isAllowed) {
|
||||
throwIfPre25Q2("addLocalNetAccess is not available on pre-B devices");
|
||||
|
|
@ -910,7 +919,7 @@ public class BpfNetMaps {
|
|||
if (iface == null) {
|
||||
ifIndex = 0;
|
||||
} else {
|
||||
ifIndex = mDeps.getIfIndex(iface);
|
||||
ifIndex = mInterfaceTracker.getInterfaceIndex(iface);
|
||||
}
|
||||
if (ifIndex == 0) {
|
||||
Log.e(TAG, "Failed to get if index, skip addLocalNetAccess for " + address
|
||||
|
|
@ -937,14 +946,14 @@ public class BpfNetMaps {
|
|||
* @param remotePort src/dst port for ingress/egress
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.CUR_DEVELOPMENT)
|
||||
public void removeLocalNetAccess(final int lpmBitlen, final String iface,
|
||||
public void removeLocalNetAccess(final int lpmBitlen, @Nullable final String iface,
|
||||
final InetAddress address, final int protocol, final int remotePort) {
|
||||
throwIfPre25Q2("removeLocalNetAccess is not available on pre-B devices");
|
||||
final int ifIndex;
|
||||
if (iface == null) {
|
||||
ifIndex = 0;
|
||||
} else {
|
||||
ifIndex = mDeps.getIfIndex(iface);
|
||||
ifIndex = mInterfaceTracker.getInterfaceIndex(iface);
|
||||
}
|
||||
if (ifIndex == 0) {
|
||||
Log.e(TAG, "Failed to get if index, skip removeLocalNetAccess for " + address
|
||||
|
|
@ -973,14 +982,14 @@ public class BpfNetMaps {
|
|||
* is not local network or if configuration is allowed like local dns servers.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.CUR_DEVELOPMENT)
|
||||
public boolean getLocalNetAccess(final int lpmBitlen, final String iface,
|
||||
public boolean getLocalNetAccess(final int lpmBitlen, @Nullable final String iface,
|
||||
final InetAddress address, final int protocol, final int remotePort) {
|
||||
throwIfPre25Q2("getLocalNetAccess is not available on pre-B devices");
|
||||
final int ifIndex;
|
||||
if (iface == null) {
|
||||
ifIndex = 0;
|
||||
} else {
|
||||
ifIndex = mDeps.getIfIndex(iface);
|
||||
ifIndex = mInterfaceTracker.getInterfaceIndex(iface);
|
||||
}
|
||||
if (ifIndex == 0) {
|
||||
Log.e(TAG, "Failed to get if index, returning default from getLocalNetAccess for "
|
||||
|
|
|
|||
|
|
@ -365,6 +365,7 @@ import com.android.server.connectivity.DnsManager;
|
|||
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
|
||||
import com.android.server.connectivity.DscpPolicyTracker;
|
||||
import com.android.server.connectivity.FullScore;
|
||||
import com.android.server.connectivity.InterfaceTracker;
|
||||
import com.android.server.connectivity.InvalidTagException;
|
||||
import com.android.server.connectivity.KeepaliveResourceUtil;
|
||||
import com.android.server.connectivity.KeepaliveTracker;
|
||||
|
|
@ -577,6 +578,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
private final NetworkStatsManager mStatsManager;
|
||||
private final NetworkPolicyManager mPolicyManager;
|
||||
private final BpfNetMaps mBpfNetMaps;
|
||||
private final InterfaceTracker mInterfaceTracker;
|
||||
|
||||
/**
|
||||
* TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple
|
||||
|
|
@ -1662,8 +1664,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
* @param netd a netd binder
|
||||
* @return BpfNetMaps implementation.
|
||||
*/
|
||||
public BpfNetMaps getBpfNetMaps(Context context, INetd netd) {
|
||||
return new BpfNetMaps(context, netd);
|
||||
public BpfNetMaps getBpfNetMaps(Context context, INetd netd,
|
||||
InterfaceTracker interfaceTracker) {
|
||||
return new BpfNetMaps(context, netd, interfaceTracker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the InterfaceTracker implementation to use in ConnectivityService.
|
||||
* @return InterfaceTracker implementation.
|
||||
*/
|
||||
public InterfaceTracker getInterfaceTracker(Context context) {
|
||||
return new InterfaceTracker(context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1886,7 +1897,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
mWakeUpMask = mask;
|
||||
|
||||
mNetd = netd;
|
||||
mBpfNetMaps = mDeps.getBpfNetMaps(mContext, netd);
|
||||
mInterfaceTracker = mDeps.getInterfaceTracker(mContext);
|
||||
mBpfNetMaps = mDeps.getBpfNetMaps(mContext, netd, mInterfaceTracker);
|
||||
mHandlerThread = mDeps.makeHandlerThread("ConnectivityServiceThread");
|
||||
mPermissionMonitorDeps = mPermDeps;
|
||||
mPermissionMonitor =
|
||||
|
|
@ -9605,8 +9617,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
|
||||
updateIngressToVpnAddressFiltering(newLp, oldLp, networkAgent);
|
||||
|
||||
updateLocalNetworkAddresses(newLp, oldLp);
|
||||
|
||||
updateMtu(newLp, oldLp);
|
||||
// TODO - figure out what to do for clat
|
||||
// for (LinkProperties lp : newLp.getStackedLinks()) {
|
||||
|
|
@ -9769,16 +9779,23 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
wakeupModifyInterface(iface, nai, true);
|
||||
mDeps.reportNetworkInterfaceForTransports(mContext, iface,
|
||||
nai.networkCapabilities.getTransportTypes());
|
||||
mInterfaceTracker.addInterface(iface);
|
||||
} catch (Exception e) {
|
||||
logw("Exception adding interface: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The local network addresses needs to be updated before interfaces are removed because
|
||||
// modifying bpf map local_net_access requires mapping interface name to index.
|
||||
updateLocalNetworkAddresses(newLp, oldLp);
|
||||
|
||||
for (final String iface : interfaceDiff.removed) {
|
||||
try {
|
||||
if (DBG) log("Removing iface " + iface + " from network " + netId);
|
||||
wakeupModifyInterface(iface, nai, false);
|
||||
mRoutingCoordinatorService.removeInterfaceFromNetwork(netId, iface);
|
||||
mInterfaceTracker.removeInterface(iface);
|
||||
} catch (Exception e) {
|
||||
loge("Exception removing interface: " + e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.connectivity;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.system.Os;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.BpfNetMaps;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* InterfaceTracker is responsible for providing interface mapping and tracking.
|
||||
* @hide
|
||||
*/
|
||||
public class InterfaceTracker {
|
||||
static {
|
||||
if (BpfNetMaps.isAtLeast25Q2()) {
|
||||
System.loadLibrary("service-connectivity");
|
||||
}
|
||||
}
|
||||
private static final String TAG = "InterfaceTracker";
|
||||
private final Dependencies mDeps;
|
||||
private final Map<String, Integer> mInterfaceMap;
|
||||
|
||||
public InterfaceTracker(final Context context) {
|
||||
this(context, new Dependencies());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public InterfaceTracker(final Context context, final Dependencies deps) {
|
||||
this.mInterfaceMap = new ArrayMap<>();
|
||||
this.mDeps = deps;
|
||||
}
|
||||
|
||||
/**
|
||||
* To add interface to tracking
|
||||
* @param interfaceName name of interface added.
|
||||
*/
|
||||
public void addInterface(@Nullable final String interfaceName) {
|
||||
final int interfaceIndex;
|
||||
if (interfaceName == null) {
|
||||
interfaceIndex = 0;
|
||||
} else {
|
||||
interfaceIndex = mDeps.getIfIndex(interfaceName);
|
||||
}
|
||||
if (interfaceIndex == 0) {
|
||||
Log.e(TAG, "Failed to get interface index for " + interfaceName);
|
||||
return;
|
||||
}
|
||||
synchronized (mInterfaceMap) {
|
||||
mInterfaceMap.put(interfaceName, interfaceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To remove interface from tracking
|
||||
* @param interfaceName name of interface removed.
|
||||
* @return true if the value was present and now removed.
|
||||
*/
|
||||
public boolean removeInterface(@Nullable final String interfaceName) {
|
||||
if (interfaceName == null) return false;
|
||||
synchronized (mInterfaceMap) {
|
||||
return mInterfaceMap.remove(interfaceName) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get interface index from interface name.
|
||||
* @param interfaceName name of interface
|
||||
* @return interface index for given interface name or 0 if interface is not found.
|
||||
*/
|
||||
public int getInterfaceIndex(@Nullable final String interfaceName) {
|
||||
final int interfaceIndex;
|
||||
if (interfaceName != null) {
|
||||
synchronized (mInterfaceMap) {
|
||||
interfaceIndex = mInterfaceMap.getOrDefault(interfaceName, 0);
|
||||
}
|
||||
} else {
|
||||
interfaceIndex = 0;
|
||||
}
|
||||
return interfaceIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependencies of InterfaceTracker, for injection in tests.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static class Dependencies {
|
||||
/**
|
||||
* Get interface index.
|
||||
*/
|
||||
public int getIfIndex(final String ifName) {
|
||||
return Os.if_nametoindex(ifName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get interface name
|
||||
*/
|
||||
public String getIfName(final int ifIndex) {
|
||||
return Os.if_indextoname(ifIndex);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -55,11 +55,11 @@ import com.android.net.module.util.BpfUtils
|
|||
import com.android.networkstack.apishim.TelephonyManagerShimImpl
|
||||
import com.android.server.BpfNetMaps
|
||||
import com.android.server.ConnectivityService
|
||||
import com.android.server.L2capNetworkProvider
|
||||
import com.android.server.NetworkAgentWrapper
|
||||
import com.android.server.TestNetIdManager
|
||||
import com.android.server.connectivity.CarrierPrivilegeAuthenticator
|
||||
import com.android.server.connectivity.ConnectivityResources
|
||||
import com.android.server.connectivity.InterfaceTracker
|
||||
import com.android.server.connectivity.MockableSystemProperties
|
||||
import com.android.server.connectivity.MultinetworkPolicyTracker
|
||||
import com.android.server.connectivity.PermissionMonitor
|
||||
|
|
@ -114,6 +114,8 @@ class ConnectivityServiceIntegrationTest {
|
|||
@Mock
|
||||
private lateinit var netd: INetd
|
||||
@Mock
|
||||
private lateinit var interfaceTracker: InterfaceTracker
|
||||
@Mock
|
||||
private lateinit var dnsResolver: IDnsResolver
|
||||
@Mock
|
||||
private lateinit var systemConfigManager: SystemConfigManager
|
||||
|
|
@ -140,11 +142,15 @@ class ConnectivityServiceIntegrationTest {
|
|||
|
||||
private val realContext get() = InstrumentationRegistry.getInstrumentation().context
|
||||
private val httpProbeUrl get() =
|
||||
realContext.getResources().getString(com.android.server.net.integrationtests.R.string
|
||||
.config_captive_portal_http_url)
|
||||
realContext.getResources().getString(
|
||||
com.android.server.net.integrationtests.R.string
|
||||
.config_captive_portal_http_url
|
||||
)
|
||||
private val httpsProbeUrl get() =
|
||||
realContext.getResources().getString(com.android.server.net.integrationtests.R.string
|
||||
.config_captive_portal_https_url)
|
||||
realContext.getResources().getString(
|
||||
com.android.server.net.integrationtests.R.string
|
||||
.config_captive_portal_https_url
|
||||
)
|
||||
|
||||
private class InstrumentationServiceConnection : ServiceConnection {
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
|
|
@ -166,12 +172,19 @@ class ConnectivityServiceIntegrationTest {
|
|||
fun setUpClass() {
|
||||
val intent = Intent(realContext, NetworkStackInstrumentationService::class.java)
|
||||
intent.action = INetworkStackInstrumentation::class.qualifiedName
|
||||
assertTrue(realContext.bindService(intent, InstrumentationServiceConnection(),
|
||||
BIND_AUTO_CREATE or BIND_IMPORTANT),
|
||||
"Error binding to instrumentation service")
|
||||
assertTrue(bindingCondition.block(SERVICE_BIND_TIMEOUT_MS),
|
||||
assertTrue(
|
||||
realContext.bindService(
|
||||
intent,
|
||||
InstrumentationServiceConnection(),
|
||||
BIND_AUTO_CREATE or BIND_IMPORTANT
|
||||
),
|
||||
"Error binding to instrumentation service"
|
||||
)
|
||||
assertTrue(
|
||||
bindingCondition.block(SERVICE_BIND_TIMEOUT_MS),
|
||||
"Timed out binding to instrumentation service " +
|
||||
"after $SERVICE_BIND_TIMEOUT_MS ms")
|
||||
"after $SERVICE_BIND_TIMEOUT_MS ms"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,7 +214,8 @@ class ConnectivityServiceIntegrationTest {
|
|||
// We don't test the actual notification value strings, so just return an empty array.
|
||||
// It doesn't matter what the values are as long as it's not null.
|
||||
doReturn(emptyArray<String>()).`when`(resources).getStringArray(
|
||||
R.array.network_switch_type_name)
|
||||
R.array.network_switch_type_name
|
||||
)
|
||||
doReturn(1).`when`(resources).getInteger(R.integer.config_networkAvoidBadWifi)
|
||||
doReturn(R.array.config_networkSupportedKeepaliveCount).`when`(resources)
|
||||
.getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any())
|
||||
|
|
@ -223,7 +237,13 @@ class ConnectivityServiceIntegrationTest {
|
|||
}
|
||||
|
||||
private inner class TestConnectivityService(deps: Dependencies) : ConnectivityService(
|
||||
context, dnsResolver, log, netd, deps, PermissionMonitorDependencies())
|
||||
context,
|
||||
dnsResolver,
|
||||
log,
|
||||
netd,
|
||||
deps,
|
||||
PermissionMonitorDependencies()
|
||||
)
|
||||
|
||||
private inner class TestDependencies : ConnectivityService.Dependencies() {
|
||||
override fun getNetworkStack() = networkStackClient
|
||||
|
|
@ -231,7 +251,11 @@ class ConnectivityServiceIntegrationTest {
|
|||
mock(ProxyTracker::class.java)
|
||||
override fun getSystemProperties() = mock(MockableSystemProperties::class.java)
|
||||
override fun makeNetIdManager() = TestNetIdManager()
|
||||
override fun getBpfNetMaps(context: Context?, netd: INetd?) = mock(BpfNetMaps::class.java)
|
||||
override fun getBpfNetMaps(
|
||||
context: Context?,
|
||||
netd: INetd?,
|
||||
interfaceTracker: InterfaceTracker?
|
||||
) = mock(BpfNetMaps::class.java)
|
||||
.also {
|
||||
doReturn(PERMISSION_INTERNET).`when`(it).getNetPermForUid(anyInt())
|
||||
}
|
||||
|
|
@ -241,13 +265,17 @@ class ConnectivityServiceIntegrationTest {
|
|||
c: Context,
|
||||
h: Handler,
|
||||
r: Runnable
|
||||
) = MultinetworkPolicyTracker(c, h, r,
|
||||
) = MultinetworkPolicyTracker(
|
||||
c,
|
||||
h,
|
||||
r,
|
||||
object : MultinetworkPolicyTracker.Dependencies() {
|
||||
override fun getResourcesForActiveSubId(
|
||||
connResources: ConnectivityResources,
|
||||
activeSubId: Int
|
||||
) = resources
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
override fun makeHandlerThread(tag: String): HandlerThread =
|
||||
super.makeHandlerThread(tag).also { handlerThreads.add(it) }
|
||||
|
|
@ -259,13 +287,18 @@ class ConnectivityServiceIntegrationTest {
|
|||
listener: BiConsumer<Int, Int>,
|
||||
handler: Handler
|
||||
): CarrierPrivilegeAuthenticator {
|
||||
return CarrierPrivilegeAuthenticator(context,
|
||||
return CarrierPrivilegeAuthenticator(
|
||||
context,
|
||||
object : CarrierPrivilegeAuthenticator.Dependencies() {
|
||||
override fun makeHandlerThread(): HandlerThread =
|
||||
super.makeHandlerThread().also { handlerThreads.add(it) }
|
||||
},
|
||||
tm, TelephonyManagerShimImpl.newInstance(tm),
|
||||
requestRestrictedWifiEnabled, listener, handler)
|
||||
tm,
|
||||
TelephonyManagerShimImpl.newInstance(tm),
|
||||
requestRestrictedWifiEnabled,
|
||||
listener,
|
||||
handler
|
||||
)
|
||||
}
|
||||
|
||||
override fun makeSatelliteAccessController(
|
||||
|
|
@ -273,7 +306,8 @@ class ConnectivityServiceIntegrationTest {
|
|||
updateSatellitePreferredUid: Consumer<MutableSet<Int>>?,
|
||||
connectivityServiceInternalHandler: Handler
|
||||
): SatelliteAccessController? = mock(
|
||||
SatelliteAccessController::class.java)
|
||||
SatelliteAccessController::class.java
|
||||
)
|
||||
|
||||
override fun makeL2capNetworkProvider(context: Context) = null
|
||||
}
|
||||
|
|
@ -305,8 +339,12 @@ class ConnectivityServiceIntegrationTest {
|
|||
nsInstrumentation.addHttpResponse(HttpResponse(httpProbeUrl, responseCode = 204))
|
||||
nsInstrumentation.addHttpResponse(HttpResponse(httpsProbeUrl, responseCode = 204))
|
||||
|
||||
val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, LinkProperties(), null /* ncTemplate */,
|
||||
context)
|
||||
val na = NetworkAgentWrapper(
|
||||
TRANSPORT_CELLULAR,
|
||||
LinkProperties(),
|
||||
null /* ncTemplate */,
|
||||
context
|
||||
)
|
||||
networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS)
|
||||
|
||||
na.addCapability(NET_CAPABILITY_INTERNET)
|
||||
|
|
@ -344,7 +382,8 @@ class ConnectivityServiceIntegrationTest {
|
|||
| "user-portal-url": "https://login.capport.android.com",
|
||||
| "venue-info-url": "https://venueinfo.capport.android.com"
|
||||
|}
|
||||
""".trimMargin()))
|
||||
""".trimMargin()
|
||||
))
|
||||
|
||||
// Tests will fail if a non-mocked query is received: mock the HTTPS probe, but not the
|
||||
// HTTP probe as it should not be sent.
|
||||
|
|
@ -398,8 +437,10 @@ class ConnectivityServiceIntegrationTest {
|
|||
BpfUtils.BPF_CGROUP_INET_EGRESS,
|
||||
BpfUtils.BPF_CGROUP_INET_SOCK_CREATE
|
||||
).forEach {
|
||||
val ret = SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
|
||||
"cmd connectivity bpf-get-cgroup-program-id $it").trim()
|
||||
val ret = SystemUtil.runShellCommand(
|
||||
InstrumentationRegistry.getInstrumentation(),
|
||||
"cmd connectivity bpf-get-cgroup-program-id $it"
|
||||
).trim()
|
||||
|
||||
assertTrue(Integer.parseInt(ret) > 0, "Unexpected output $ret for type $it")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ import com.android.net.module.util.bpf.CookieTagMapValue;
|
|||
import com.android.net.module.util.bpf.IngressDiscardKey;
|
||||
import com.android.net.module.util.bpf.IngressDiscardValue;
|
||||
import com.android.net.module.util.bpf.LocalNetAccessKey;
|
||||
import com.android.server.connectivity.InterfaceTracker;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
||||
|
|
@ -170,6 +171,8 @@ public final class BpfNetMapsTest {
|
|||
@Mock INetd mNetd;
|
||||
@Mock BpfNetMaps.Dependencies mDeps;
|
||||
@Mock Context mContext;
|
||||
|
||||
@Mock InterfaceTracker mInterfaceTracker;
|
||||
private final IBpfMap<S32, U32> mConfigurationMap = new TestBpfMap<>(S32.class, U32.class);
|
||||
private final IBpfMap<S32, UidOwnerValue> mUidOwnerMap =
|
||||
new TestBpfMap<>(S32.class, UidOwnerValue.class);
|
||||
|
|
@ -188,6 +191,7 @@ public final class BpfNetMapsTest {
|
|||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
doReturn(TEST_IF_INDEX).when(mDeps).getIfIndex(TEST_IF_NAME);
|
||||
doReturn(TEST_IF_INDEX).when(mInterfaceTracker).getInterfaceIndex(TEST_IF_NAME);
|
||||
doReturn(TEST_IF_NAME).when(mDeps).getIfName(TEST_IF_INDEX);
|
||||
doReturn(0).when(mDeps).synchronizeKernelRCU();
|
||||
BpfNetMaps.setConfigurationMapForTest(mConfigurationMap);
|
||||
|
|
@ -202,7 +206,7 @@ public final class BpfNetMapsTest {
|
|||
BpfNetMaps.setDataSaverEnabledMapForTest(mDataSaverEnabledMap);
|
||||
mDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(DATA_SAVER_DISABLED));
|
||||
BpfNetMaps.setIngressDiscardMapForTest(mIngressDiscardMap);
|
||||
mBpfNetMaps = new BpfNetMaps(mContext, mNetd, mDeps);
|
||||
mBpfNetMaps = new BpfNetMaps(mContext, mNetd, mDeps, mInterfaceTracker);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -413,6 +413,7 @@ import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
|
|||
import com.android.server.connectivity.ClatCoordinator;
|
||||
import com.android.server.connectivity.ConnectivityFlags;
|
||||
import com.android.server.connectivity.ConnectivityResources;
|
||||
import com.android.server.connectivity.InterfaceTracker;
|
||||
import com.android.server.connectivity.KeepaliveTracker;
|
||||
import com.android.server.connectivity.MultinetworkPolicyTracker;
|
||||
import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies;
|
||||
|
|
@ -2262,7 +2263,8 @@ public class ConnectivityServiceTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public BpfNetMaps getBpfNetMaps(Context context, INetd netd) {
|
||||
public BpfNetMaps getBpfNetMaps(Context context, INetd netd,
|
||||
InterfaceTracker interfaceTracker) {
|
||||
return mBpfNetMaps;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.connectivity;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.testutils.ConnectivityModuleTest;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
||||
import com.android.testutils.DevSdkIgnoreRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner.class)
|
||||
@SmallTest
|
||||
@ConnectivityModuleTest
|
||||
public class InterfaceTrackerTest {
|
||||
private static final String TAG = "InterfaceTrackerTest";
|
||||
private static final String TEST_IF_NAME = "wlan10";
|
||||
private static final String TEST_INCORRECT_IF_NAME = "wlan20";
|
||||
private static final int TEST_IF_INDEX = 7;
|
||||
|
||||
@Rule
|
||||
public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
|
||||
|
||||
private InterfaceTracker mInterfaceTracker;
|
||||
|
||||
@Mock Context mContext;
|
||||
@Mock InterfaceTracker.Dependencies mDeps;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
doReturn(TEST_IF_INDEX).when(mDeps).getIfIndex(TEST_IF_NAME);
|
||||
mInterfaceTracker = new InterfaceTracker(mContext, mDeps);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
public void testAddingInterface_InterfaceNameIndexMappingAdded() {
|
||||
mInterfaceTracker.addInterface(TEST_IF_NAME);
|
||||
assertEquals(TEST_IF_INDEX, mInterfaceTracker.getInterfaceIndex(TEST_IF_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
public void testAddingNullInterface_InterfaceNameIndexMappingNotAdded() {
|
||||
mInterfaceTracker.addInterface(null);
|
||||
assertEquals(0, mInterfaceTracker.getInterfaceIndex(TEST_IF_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
public void testAddingIncorrectInterface_InterfaceNameIndexMappingNotAdded() {
|
||||
mInterfaceTracker.addInterface(TEST_INCORRECT_IF_NAME);
|
||||
|
||||
assertEquals(0, mInterfaceTracker.getInterfaceIndex(TEST_INCORRECT_IF_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
public void testRemovingInterface_InterfaceNameIndexMappingRemoved() {
|
||||
mInterfaceTracker.addInterface(TEST_IF_NAME);
|
||||
assertEquals(TEST_IF_INDEX, mInterfaceTracker.getInterfaceIndex(TEST_IF_NAME));
|
||||
mInterfaceTracker.removeInterface(TEST_IF_NAME);
|
||||
assertEquals(0, mInterfaceTracker.getInterfaceIndex(TEST_IF_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
public void testRemovingNullInterface_InterfaceNameIndexMappingNotRemoved() {
|
||||
mInterfaceTracker.addInterface(TEST_IF_NAME);
|
||||
mInterfaceTracker.removeInterface(null);
|
||||
assertEquals(TEST_IF_INDEX, mInterfaceTracker.getInterfaceIndex(TEST_IF_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
public void testRemovingIncorrectInterface_InterfaceNameIndexMappingNotRemoved() {
|
||||
mInterfaceTracker.addInterface(TEST_IF_NAME);
|
||||
mInterfaceTracker.removeInterface(TEST_INCORRECT_IF_NAME);
|
||||
assertEquals(TEST_IF_INDEX, mInterfaceTracker.getInterfaceIndex(TEST_IF_NAME));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -68,6 +68,7 @@ import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker
|
|||
import com.android.server.connectivity.CarrierPrivilegeAuthenticator
|
||||
import com.android.server.connectivity.ClatCoordinator
|
||||
import com.android.server.connectivity.ConnectivityFlags
|
||||
import com.android.server.connectivity.InterfaceTracker
|
||||
import com.android.server.connectivity.MulticastRoutingCoordinatorService
|
||||
import com.android.server.connectivity.MultinetworkPolicyTracker
|
||||
import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies
|
||||
|
|
@ -193,6 +194,7 @@ open class CSTest {
|
|||
val connResources = makeMockConnResources(sysResources, packageManager)
|
||||
|
||||
val netd = mock<INetd>()
|
||||
val interfaceTracker = mock<InterfaceTracker>()
|
||||
val bpfNetMaps = mock<BpfNetMaps>().also {
|
||||
doReturn(PERMISSION_INTERNET).`when`(it).getNetPermForUid(anyInt())
|
||||
}
|
||||
|
|
@ -279,7 +281,11 @@ open class CSTest {
|
|||
|
||||
inner class CSDeps : ConnectivityService.Dependencies() {
|
||||
override fun getResources(ctx: Context) = connResources
|
||||
override fun getBpfNetMaps(context: Context, netd: INetd) = this@CSTest.bpfNetMaps
|
||||
override fun getBpfNetMaps(
|
||||
context: Context,
|
||||
netd: INetd,
|
||||
interfaceTracker: InterfaceTracker
|
||||
) = this@CSTest.bpfNetMaps
|
||||
override fun getClatCoordinator(netd: INetd?) = this@CSTest.clatCoordinator
|
||||
override fun getNetworkStack() = this@CSTest.networkStack
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue