Merge "Removing interfaces from the InterfaceTracker when network is destroyed." into main

This commit is contained in:
Sarup Dalwani 2025-03-25 07:40:41 -07:00 • committed by Gerrit Code Review
commit 45a95e4b99
4 changed files with 104 additions and 0 deletions

View file

@ -5787,6 +5787,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mDeps.disableIngressRateLimit(nai.linkProperties.getInterfaceName());
}
// Removes the interfaces associated with the network being destroyed from the tracker.
for (String interfaceName : nai.linkProperties.getAllInterfaceNames()) {
mInterfaceTracker.removeInterface(interfaceName);
}
nai.setDestroyed();
nai.onNetworkDestroyed();
}

View file

@ -22,6 +22,7 @@ import android.system.Os;
import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.BpfNetMaps;
@ -39,6 +40,7 @@ public class InterfaceTracker {
}
private static final String TAG = "InterfaceTracker";
private final Dependencies mDeps;
@GuardedBy("mInterfaceMap")
private final Map<String, Integer> mInterfaceMap;
public InterfaceTracker(final Context context) {

View file

@ -0,0 +1,96 @@
/*
* Copyright (C) 2023 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.connectivityservice
import android.net.IpPrefix
import android.net.LinkAddress
import android.net.LinkProperties
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN
import android.net.NetworkCapabilities.TRANSPORT_VPN
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
import android.os.Build
import androidx.test.filters.SmallTest
import com.android.server.CSTest
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
import com.android.testutils.TestableNetworkCallback
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.verify
private const val WIFI_IFNAME = "wlan0"
private val wifiNc = NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_WIFI)
.addCapability(NET_CAPABILITY_INTERNET)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
.build()
private fun lp(iface: String, vararg linkAddresses: LinkAddress) = LinkProperties().apply {
interfaceName = iface
for (linkAddress in linkAddresses) {
addLinkAddress(linkAddress)
}
}
private fun nr(transport: Int) = NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(transport).apply {
if (transport != TRANSPORT_VPN) {
addCapability(NET_CAPABILITY_NOT_VPN)
}
}.build()
@DevSdkIgnoreRunner.MonitorThreadLeak
@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM)
class CSInterfaceTrackerTest : CSTest() {
private val LOCAL_IPV6_IP_ADDRESS_PREFIX = IpPrefix("fe80::1cf1:35ff:fe8c:db87/64")
private val LOCAL_IPV6_LINK_ADDRESS = LinkAddress(
LOCAL_IPV6_IP_ADDRESS_PREFIX.getAddress(),
LOCAL_IPV6_IP_ADDRESS_PREFIX.getPrefixLength()
)
@Test
fun testDisconnectingNetwork_InterfaceRemoved() {
val nr = nr(NetworkCapabilities.TRANSPORT_WIFI)
val cb = TestableNetworkCallback()
val interfaceTrackerInorder = inOrder(interfaceTracker)
cm.requestNetwork(nr, cb)
// Connecting to network with IPv6 local address in LinkProperties
val wifiLp = lp(WIFI_IFNAME, LOCAL_IPV6_LINK_ADDRESS)
val wifiAgent = Agent(nc = wifiNc, lp = wifiLp)
wifiAgent.connect()
cb.expectAvailableCallbacks(wifiAgent.network, validated = false)
interfaceTrackerInorder.verify(interfaceTracker).addInterface(WIFI_IFNAME)
wifiAgent.disconnect()
cb.expect<Lost>(timeoutMs = 500) { it.network == wifiAgent.network }
// onLost is fired before the network is destroyed.
waitForIdle()
interfaceTrackerInorder.verify(interfaceTracker).removeInterface(WIFI_IFNAME)
}
}

View file

@ -288,6 +288,8 @@ open class CSTest {
netd: INetd,
interfaceTracker: InterfaceTracker
) = this@CSTest.bpfNetMaps
override fun getInterfaceTracker(context: Context?) = this@CSTest.interfaceTracker
override fun getClatCoordinator(netd: INetd?) = this@CSTest.clatCoordinator
override fun getNetworkStack() = this@CSTest.networkStack