1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.ip; 18 19 import static android.net.INetd.IF_STATE_DOWN; 20 import static android.net.INetd.IF_STATE_UP; 21 import static android.net.RouteInfo.RTN_UNICAST; 22 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL; 23 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL; 24 import static android.net.TetheringManager.TETHERING_BLUETOOTH; 25 import static android.net.TetheringManager.TETHERING_NCM; 26 import static android.net.TetheringManager.TETHERING_USB; 27 import static android.net.TetheringManager.TETHERING_WIFI; 28 import static android.net.TetheringManager.TETHERING_WIFI_P2P; 29 import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR; 30 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; 31 import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL; 32 import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; 33 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; 34 import static android.net.ip.IpServer.STATE_AVAILABLE; 35 import static android.net.ip.IpServer.STATE_LOCAL_ONLY; 36 import static android.net.ip.IpServer.STATE_TETHERED; 37 import static android.net.ip.IpServer.STATE_UNAVAILABLE; 38 import static android.net.ip.IpServer.getTetherableIpv6Prefixes; 39 40 import static com.android.modules.utils.build.SdkLevel.isAtLeastT; 41 import static com.android.modules.utils.build.SdkLevel.isAtLeastV; 42 import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; 43 import static com.android.networkstack.tethering.TetheringConfiguration.TETHERING_LOCAL_NETWORK_AGENT; 44 45 import static org.junit.Assert.assertEquals; 46 import static org.junit.Assert.assertFalse; 47 import static org.junit.Assert.assertNotEquals; 48 import static org.junit.Assert.assertNotNull; 49 import static org.junit.Assert.assertTrue; 50 import static org.junit.Assert.fail; 51 import static org.mockito.ArgumentMatchers.anyInt; 52 import static org.mockito.ArgumentMatchers.argThat; 53 import static org.mockito.ArgumentMatchers.any; 54 import static org.mockito.ArgumentMatchers.anyString; 55 import static org.mockito.ArgumentMatchers.eq; 56 import static org.mockito.Mockito.clearInvocations; 57 import static org.mockito.Mockito.doAnswer; 58 import static org.mockito.Mockito.doNothing; 59 import static org.mockito.Mockito.doReturn; 60 import static org.mockito.Mockito.doThrow; 61 import static org.mockito.Mockito.inOrder; 62 import static org.mockito.Mockito.mock; 63 import static org.mockito.Mockito.never; 64 import static org.mockito.Mockito.reset; 65 import static org.mockito.Mockito.timeout; 66 import static org.mockito.Mockito.times; 67 import static org.mockito.Mockito.verify; 68 import static org.mockito.Mockito.verifyNoMoreInteractions; 69 import static org.mockito.Mockito.when; 70 71 import android.content.Context; 72 import android.net.INetd; 73 import android.net.InetAddresses; 74 import android.net.InterfaceConfigurationParcel; 75 import android.net.IpPrefix; 76 import android.net.LinkAddress; 77 import android.net.LinkProperties; 78 import android.net.MacAddress; 79 import android.net.Network; 80 import android.net.NetworkAgent; 81 import android.net.RouteInfo; 82 import android.net.TetheringManager.TetheringRequest; 83 import android.net.dhcp.DhcpServerCallbacks; 84 import android.net.dhcp.DhcpServingParamsParcel; 85 import android.net.dhcp.IDhcpEventCallbacks; 86 import android.net.dhcp.IDhcpServer; 87 import android.net.dhcp.IDhcpServerCallbacks; 88 import android.net.ip.RouterAdvertisementDaemon.RaParams; 89 import android.os.Build; 90 import android.os.Handler; 91 import android.os.RemoteException; 92 import android.os.ServiceSpecificException; 93 import android.os.test.TestLooper; 94 import android.text.TextUtils; 95 import android.util.ArrayMap; 96 97 import androidx.test.filters.SmallTest; 98 import androidx.test.runner.AndroidJUnit4; 99 100 import com.android.net.module.util.InterfaceParams; 101 import com.android.net.module.util.RoutingCoordinatorManager; 102 import com.android.net.module.util.SharedLog; 103 import com.android.networkstack.tethering.BpfCoordinator; 104 import com.android.networkstack.tethering.TetheringConfiguration; 105 import com.android.networkstack.tethering.metrics.TetheringMetrics; 106 import com.android.networkstack.tethering.util.InterfaceSet; 107 import com.android.networkstack.tethering.util.PrefixUtils; 108 import com.android.testutils.DevSdkIgnoreRule; 109 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; 110 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 111 import com.android.testutils.com.android.testutils.SetFeatureFlagsRule; 112 113 import org.junit.Before; 114 import org.junit.Rule; 115 import org.junit.Test; 116 import org.junit.runner.RunWith; 117 import org.mockito.ArgumentCaptor; 118 import org.mockito.Captor; 119 import org.mockito.InOrder; 120 import org.mockito.Mock; 121 import org.mockito.MockitoAnnotations; 122 123 import java.net.Inet4Address; 124 import java.net.InetAddress; 125 import java.util.List; 126 import java.util.Set; 127 128 @RunWith(AndroidJUnit4.class) 129 @SmallTest 130 public class IpServerTest { 131 @Rule 132 public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); 133 134 final ArrayMap<String, Boolean> mFeatureFlags = new ArrayMap<>(); 135 // This will set feature flags from @FeatureFlag annotations 136 // into the map before setUp() runs. 137 @Rule 138 public final SetFeatureFlagsRule mSetFeatureFlagsRule = 139 new SetFeatureFlagsRule((name, enabled) -> { 140 mFeatureFlags.put(name, enabled); 141 return null; 142 }, (name) -> mFeatureFlags.getOrDefault(name, false)); 143 144 private static final String IFACE_NAME = "testnet1"; 145 private static final String UPSTREAM_IFACE = "upstream0"; 146 private static final String UPSTREAM_IFACE2 = "upstream1"; 147 private static final String IPSEC_IFACE = "ipsec0"; 148 private static final int NO_UPSTREAM = 0; 149 private static final int UPSTREAM_IFINDEX = 101; 150 private static final int UPSTREAM_IFINDEX2 = 102; 151 private static final int IPSEC_IFINDEX = 103; 152 private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1"; 153 private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24; 154 private static final int DHCP_LEASE_TIME_SECS = 3600; 155 private static final boolean DEFAULT_USING_BPF_OFFLOAD = true; 156 private static final int DEFAULT_SUBNET_PREFIX_LENGTH = 0; 157 private static final int P2P_SUBNET_PREFIX_LENGTH = 25; 158 private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24"; 159 160 private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams( 161 IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); 162 private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams( 163 UPSTREAM_IFACE, UPSTREAM_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); 164 private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams( 165 UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.ALL_ZEROS_ADDRESS, 166 1500 /* defaultMtu */); 167 private static final InterfaceParams IPSEC_IFACE_PARAMS = new InterfaceParams( 168 IPSEC_IFACE, IPSEC_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); 169 170 private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000; 171 172 private final LinkAddress mTestAddress = new LinkAddress("192.168.42.5/24"); 173 private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24"); 174 175 private static final Set<LinkAddress> NO_ADDRESSES = Set.of(); 176 private static final Set<IpPrefix> NO_PREFIXES = Set.of(); 177 private static final Set<LinkAddress> UPSTREAM_ADDRESSES = 178 Set.of(new LinkAddress("2001:db8:0:1234::168/64")); 179 private static final Set<IpPrefix> UPSTREAM_PREFIXES = 180 Set.of(new IpPrefix("2001:db8:0:1234::/64")); 181 private static final Set<LinkAddress> UPSTREAM_ADDRESSES2 = Set.of( 182 new LinkAddress("2001:db8:0:1234::168/64"), 183 new LinkAddress("2001:db8:0:abcd::168/64")); 184 private static final Set<IpPrefix> UPSTREAM_PREFIXES2 = Set.of( 185 new IpPrefix("2001:db8:0:1234::/64"), new IpPrefix("2001:db8:0:abcd::/64")); 186 private static final int TEST_NET_ID = 123; 187 188 @Mock private INetd mNetd; 189 @Mock private IpServer.Callback mCallback; 190 @Mock private SharedLog mSharedLog; 191 @Mock private IDhcpServer mDhcpServer; 192 @Mock private DadProxy mDadProxy; 193 @Mock private RouterAdvertisementDaemon mRaDaemon; 194 @Mock private IpServer.Dependencies mDependencies; 195 @Mock private RoutingCoordinatorManager mRoutingCoordinatorManager; 196 @Mock private TetheringConfiguration mTetherConfig; 197 @Mock private TetheringMetrics mTetheringMetrics; 198 @Mock private BpfCoordinator mBpfCoordinator; 199 @Mock private Context mContext; 200 @Mock private NetworkAgent mNetworkAgent; 201 202 @Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor; 203 204 private TestLooper mLooper; 205 private Handler mHandler; 206 private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor = 207 ArgumentCaptor.forClass(LinkProperties.class); 208 private IpServer mIpServer; 209 private InterfaceConfigurationParcel mInterfaceConfiguration; 210 initStateMachine(int interfaceType)211 private void initStateMachine(int interfaceType) throws Exception { 212 initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD); 213 } 214 initStateMachine(int interfaceType, boolean usingLegacyDhcp, boolean usingBpfOffload)215 private void initStateMachine(int interfaceType, boolean usingLegacyDhcp, 216 boolean usingBpfOffload) throws Exception { 217 initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload, 218 false /* shouldEnableWifiP2pDedicatedIp */); 219 } 220 initStateMachine(int interfaceType, boolean usingLegacyDhcp, boolean usingBpfOffload, boolean shouldEnableWifiP2pDedicatedIp)221 private void initStateMachine(int interfaceType, boolean usingLegacyDhcp, 222 boolean usingBpfOffload, boolean shouldEnableWifiP2pDedicatedIp) throws Exception { 223 when(mDependencies.getDadProxy(any(), any())).thenReturn(mDadProxy); 224 when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon); 225 when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS); 226 when(mDependencies.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS); 227 when(mDependencies.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2); 228 when(mDependencies.getInterfaceParams(IPSEC_IFACE)).thenReturn(IPSEC_IFACE_PARAMS); 229 doAnswer( 230 invocation -> mFeatureFlags.getOrDefault((String) invocation.getArgument(1), false) 231 ).when(mDependencies).isFeatureEnabled(any(), anyString()); 232 if (isAtLeastV()) { 233 when(mDependencies.makeNetworkAgent(any(), any(), anyString(), anyInt(), any())) 234 .thenReturn(mNetworkAgent); 235 // Mock the returned network and modifying the status. 236 final Network network = mock(Network.class); 237 doReturn(TEST_NET_ID).when(network).getNetId(); 238 doReturn(network).when(mNetworkAgent).register(); 239 doReturn(network).when(mNetworkAgent).getNetwork(); 240 } 241 242 mInterfaceConfiguration = new InterfaceConfigurationParcel(); 243 mInterfaceConfiguration.flags = new String[0]; 244 if (interfaceType == TETHERING_BLUETOOTH) { 245 mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR; 246 mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH; 247 } 248 249 when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(usingBpfOffload); 250 when(mTetherConfig.useLegacyDhcpServer()).thenReturn(usingLegacyDhcp); 251 when(mTetherConfig.getP2pLeasesSubnetPrefixLength()).thenReturn(P2P_SUBNET_PREFIX_LENGTH); 252 when(mTetherConfig.shouldEnableWifiP2pDedicatedIp()) 253 .thenReturn(shouldEnableWifiP2pDedicatedIp); 254 when(mBpfCoordinator.isUsingBpfOffload()).thenReturn(usingBpfOffload); 255 mIpServer = createIpServer(interfaceType); 256 mIpServer.start(); 257 258 // Starting the state machine always puts us in a consistent state and notifies 259 // the rest of the world that we've changed from an unknown to available state. 260 mLooper.dispatchAll(); 261 reset(mNetd, mCallback); 262 263 when(mRaDaemon.start()).thenReturn(true); 264 } 265 initTetheredStateMachine(int interfaceType, String upstreamIface)266 private void initTetheredStateMachine(int interfaceType, String upstreamIface) 267 throws Exception { 268 initTetheredStateMachine(interfaceType, upstreamIface, NO_ADDRESSES, false, 269 DEFAULT_USING_BPF_OFFLOAD); 270 } 271 initTetheredStateMachine(int interfaceType, String upstreamIface, Set<LinkAddress> upstreamAddresses, boolean usingLegacyDhcp, boolean usingBpfOffload)272 private void initTetheredStateMachine(int interfaceType, String upstreamIface, 273 Set<LinkAddress> upstreamAddresses, boolean usingLegacyDhcp, boolean usingBpfOffload) 274 throws Exception { 275 initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload); 276 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 277 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL)); 278 verify(mBpfCoordinator).addIpServer(mIpServer); 279 if (upstreamIface != null) { 280 InterfaceParams interfaceParams = mDependencies.getInterfaceParams(upstreamIface); 281 assertNotNull("missing upstream interface: " + upstreamIface, interfaceParams); 282 LinkProperties lp = new LinkProperties(); 283 lp.setInterfaceName(upstreamIface); 284 lp.setLinkAddresses(upstreamAddresses); 285 dispatchTetherConnectionChanged(upstreamIface, lp, 0); 286 Set<IpPrefix> upstreamPrefixes = getTetherableIpv6Prefixes(lp.getLinkAddresses()); 287 // One is called when handling CMD_TETHER_CONNECTION_CHANGED and the other one is called 288 // when upstream's LinkProperties is updated (updateUpstreamIPv6LinkProperties) 289 verify(mBpfCoordinator, times(2)).maybeAddUpstreamToLookupTable( 290 interfaceParams.index, upstreamIface); 291 verify(mBpfCoordinator).updateIpv6UpstreamInterface( 292 mIpServer, interfaceParams.index, upstreamPrefixes); 293 } 294 reset(mNetd, mBpfCoordinator, mCallback, mRoutingCoordinatorManager); 295 when(mRoutingCoordinatorManager.requestStickyDownstreamAddress(anyInt(), anyInt(), 296 any())).thenReturn(mTestAddress); 297 } 298 299 @SuppressWarnings("DoNotCall") // Ignore warning for synchronous to call to Thread.run() setUpDhcpServer()300 private void setUpDhcpServer() throws Exception { 301 doAnswer(inv -> { 302 final IDhcpServerCallbacks cb = inv.getArgument(2); 303 new Thread(() -> { 304 try { 305 cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); 306 } catch (RemoteException e) { 307 fail(e.getMessage()); 308 } 309 }).run(); 310 return null; 311 }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any()); 312 } 313 setUp()314 @Before public void setUp() throws Exception { 315 MockitoAnnotations.initMocks(this); 316 when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog); 317 when(mRoutingCoordinatorManager.requestStickyDownstreamAddress(anyInt(), anyInt(), 318 any())).thenReturn(mTestAddress); 319 when(mRoutingCoordinatorManager.requestDownstreamAddress(any())).thenReturn(mTestAddress); 320 when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(DEFAULT_USING_BPF_OFFLOAD); 321 when(mTetherConfig.useLegacyDhcpServer()).thenReturn(false /* default value */); 322 323 setUpDhcpServer(); 324 } 325 326 // In order to interact with syncSM from the test, IpServer must be created in test thread. createIpServer(final int interfaceType)327 private IpServer createIpServer(final int interfaceType) { 328 mLooper = new TestLooper(); 329 mHandler = new Handler(mLooper.getLooper()); 330 return new IpServer(IFACE_NAME, mContext, mHandler, interfaceType, mSharedLog, mNetd, 331 mBpfCoordinator, mRoutingCoordinatorManager, mCallback, mTetherConfig, 332 mTetheringMetrics, mDependencies); 333 } 334 335 @Test startsOutAvailable()336 public void startsOutAvailable() throws Exception { 337 mIpServer = createIpServer(TETHERING_BLUETOOTH); 338 mIpServer.start(); 339 mLooper.dispatchAll(); 340 verify(mCallback).updateInterfaceState( 341 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); 342 verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class)); 343 verifyNoMoreInteractions(mCallback, mNetd); 344 } 345 346 @Test shouldDoNothingUntilRequested()347 public void shouldDoNothingUntilRequested() throws Exception { 348 initStateMachine(TETHERING_BLUETOOTH); 349 final int [] noOp_commands = { 350 IpServer.CMD_TETHER_UNREQUESTED, 351 IpServer.CMD_IP_FORWARDING_ENABLE_ERROR, 352 IpServer.CMD_IP_FORWARDING_DISABLE_ERROR, 353 IpServer.CMD_START_TETHERING_ERROR, 354 IpServer.CMD_STOP_TETHERING_ERROR, 355 IpServer.CMD_SET_DNS_FORWARDERS_ERROR, 356 IpServer.CMD_TETHER_CONNECTION_CHANGED 357 }; 358 for (int command : noOp_commands) { 359 // None of these commands should trigger us to request action from 360 // the rest of the system. 361 dispatchCommand(command); 362 verifyNoMoreInteractions(mNetd, mCallback); 363 } 364 } 365 366 @Test handlesImmediateInterfaceDown()367 public void handlesImmediateInterfaceDown() throws Exception { 368 initStateMachine(TETHERING_BLUETOOTH); 369 370 dispatchCommand(IpServer.CMD_INTERFACE_DOWN); 371 verify(mCallback).updateInterfaceState( 372 mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR); 373 verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class)); 374 verifyNoMoreInteractions(mNetd, mCallback); 375 } 376 isTetheringNetworkAgentFeatureEnabled()377 private boolean isTetheringNetworkAgentFeatureEnabled() { 378 return isAtLeastV() && mFeatureFlags.getOrDefault(TETHERING_LOCAL_NETWORK_AGENT, false); 379 } 380 381 @Test canBeTetheredAsBluetooth()382 public void canBeTetheredAsBluetooth() throws Exception { 383 initStateMachine(TETHERING_BLUETOOTH); 384 385 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 386 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL)); 387 InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager); 388 if (isAtLeastT()) { 389 inOrder.verify(mRoutingCoordinatorManager) 390 .requestStickyDownstreamAddress( 391 eq(TETHERING_BLUETOOTH), 392 eq(CONNECTIVITY_SCOPE_GLOBAL), 393 any()); 394 inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any()); 395 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> 396 IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP))); 397 } 398 inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 399 if (isTetheringNetworkAgentFeatureEnabled()) { 400 inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString()); 401 inOrder.verify(mNetd, never()) 402 .networkAddRoute(anyInt(), anyString(), anyString(), anyString()); 403 } else { 404 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 405 // One for ipv4 route, one for ipv6 link local route. 406 inOrder.verify(mNetd, times(2)) 407 .networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), any(), any()); 408 } 409 inOrder.verify(mCallback).updateInterfaceState( 410 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR); 411 inOrder.verify(mCallback).updateLinkProperties( 412 eq(mIpServer), any(LinkProperties.class)); 413 verifyNoMoreInteractions(mNetd, mCallback); 414 } 415 416 @Test canUnrequestTethering()417 public void canUnrequestTethering() throws Exception { 418 initTetheredStateMachine(TETHERING_BLUETOOTH, null); 419 420 dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); 421 InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager); 422 inOrder.verify(mNetd).tetherApplyDnsInterfaces(); 423 inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME); 424 if (isTetheringNetworkAgentFeatureEnabled()) { 425 inOrder.verify(mNetd, never()).networkRemoveInterface(anyInt(), anyString()); 426 } else { 427 inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 428 } 429 // One is ipv4 address clear (set to 0.0.0.0), another is set interface down which only 430 // happen after T. Before T, the interface configuration control in bluetooth side. 431 if (isAtLeastT()) { 432 inOrder.verify(mNetd).interfaceSetCfg( 433 argThat(cfg -> assertContainsFlag(cfg.flags, IF_STATE_DOWN))); 434 } 435 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> cfg.flags.length == 0)); 436 inOrder.verify(mRoutingCoordinatorManager).releaseDownstream(any()); 437 inOrder.verify(mCallback).updateInterfaceState( 438 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); 439 inOrder.verify(mCallback).updateLinkProperties( 440 eq(mIpServer), any(LinkProperties.class)); 441 verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_BLUETOOTH), 442 eq(TETHER_ERROR_NO_ERROR)); 443 verify(mTetheringMetrics).sendReport(eq(TETHERING_BLUETOOTH)); 444 verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager); 445 } 446 447 @Test canBeTetheredAsUsb()448 public void canBeTetheredAsUsb() throws Exception { 449 initStateMachine(TETHERING_USB); 450 451 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 452 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL)); 453 InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager); 454 inOrder.verify(mRoutingCoordinatorManager).requestStickyDownstreamAddress(anyInt(), 455 eq(CONNECTIVITY_SCOPE_GLOBAL), any()); 456 inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any()); 457 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> 458 IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP))); 459 inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 460 if (isTetheringNetworkAgentFeatureEnabled()) { 461 inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString()); 462 inOrder.verify(mNetd, never()) 463 .networkAddRoute(anyInt(), anyString(), anyString(), anyString()); 464 } else { 465 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 466 inOrder.verify(mNetd, times(2)) 467 .networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), any(), any()); 468 } 469 inOrder.verify(mCallback).updateInterfaceState( 470 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR); 471 inOrder.verify(mCallback).updateLinkProperties( 472 eq(mIpServer), mLinkPropertiesCaptor.capture()); 473 assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); 474 verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager); 475 } 476 477 @Test canBeTetheredAsWifiP2p_NotUsingDedicatedIp()478 public void canBeTetheredAsWifiP2p_NotUsingDedicatedIp() throws Exception { 479 initStateMachine(TETHERING_WIFI_P2P); 480 481 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 482 createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL)); 483 InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager); 484 inOrder.verify(mRoutingCoordinatorManager).requestStickyDownstreamAddress(anyInt(), 485 eq(CONNECTIVITY_SCOPE_LOCAL), any()); 486 inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any()); 487 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> 488 IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP))); 489 inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 490 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 491 inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), 492 any(), any()); 493 inOrder.verify(mCallback).updateInterfaceState( 494 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); 495 inOrder.verify(mCallback).updateLinkProperties( 496 eq(mIpServer), mLinkPropertiesCaptor.capture()); 497 assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); 498 verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager); 499 } 500 501 @Test canBeTetheredAsWifiP2p_UsingDedicatedIp()502 public void canBeTetheredAsWifiP2p_UsingDedicatedIp() throws Exception { 503 initStateMachine(TETHERING_WIFI_P2P, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD, 504 true /* shouldEnableWifiP2pDedicatedIp */); 505 506 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 507 createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL)); 508 InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager); 509 // When using WiFi P2p dedicated IP, the IpServer just picks the IP address without 510 // requesting for it at RoutingCoordinatorManager. 511 inOrder.verify(mRoutingCoordinatorManager, never()) 512 .requestStickyDownstreamAddress(anyInt(), anyInt(), any()); 513 inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any()); 514 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> 515 IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP))); 516 inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 517 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 518 inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), 519 any(), any()); 520 inOrder.verify(mCallback).updateInterfaceState( 521 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); 522 inOrder.verify(mCallback).updateLinkProperties( 523 eq(mIpServer), mLinkPropertiesCaptor.capture()); 524 assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); 525 assertEquals(List.of(new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS)), 526 mLinkPropertiesCaptor.getValue().getLinkAddresses()); 527 verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager); 528 } 529 530 @Test handlesFirstUpstreamChange()531 public void handlesFirstUpstreamChange() throws Exception { 532 initTetheredStateMachine(TETHERING_BLUETOOTH, null); 533 534 // Telling the state machine about its upstream interface triggers 535 // a little more configuration. 536 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 537 InOrder inOrder = inOrder(mBpfCoordinator, mRoutingCoordinatorManager); 538 539 // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>. 540 inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX, 541 UPSTREAM_IFACE); 542 inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE); 543 inOrder.verify(mRoutingCoordinatorManager).addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 544 545 verifyNoMoreInteractions(mCallback, mBpfCoordinator, mRoutingCoordinatorManager); 546 } 547 548 @Test handlesChangingUpstream()549 public void handlesChangingUpstream() throws Exception { 550 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); 551 552 clearInvocations(mBpfCoordinator, mRoutingCoordinatorManager); 553 dispatchTetherConnectionChanged(UPSTREAM_IFACE2); 554 InOrder inOrder = inOrder(mBpfCoordinator, mRoutingCoordinatorManager); 555 556 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>. 557 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE); 558 inOrder.verify(mRoutingCoordinatorManager) 559 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 560 561 // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2>. 562 inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2, 563 UPSTREAM_IFACE2); 564 inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2); 565 inOrder.verify(mRoutingCoordinatorManager).addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 566 567 verifyNoMoreInteractions(mCallback, mBpfCoordinator, mRoutingCoordinatorManager); 568 } 569 570 @Test handlesChangingUpstreamNatFailure()571 public void handlesChangingUpstreamNatFailure() throws Exception { 572 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 573 574 doThrow(RuntimeException.class) 575 .when(mRoutingCoordinatorManager) 576 .addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 577 578 dispatchTetherConnectionChanged(UPSTREAM_IFACE2); 579 InOrder inOrder = inOrder(mBpfCoordinator, mRoutingCoordinatorManager); 580 581 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>. 582 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE); 583 inOrder.verify(mRoutingCoordinatorManager) 584 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 585 586 // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on 587 // addInterfaceForward. 588 inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2, 589 UPSTREAM_IFACE2); 590 inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2); 591 inOrder.verify(mRoutingCoordinatorManager).addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 592 593 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback. 594 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2); 595 inOrder.verify(mRoutingCoordinatorManager) 596 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 597 } 598 599 @Test handlesChangingUpstreamInterfaceForwardingFailure()600 public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception { 601 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 602 603 doThrow(RuntimeException.class) 604 .when(mRoutingCoordinatorManager) 605 .addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 606 607 dispatchTetherConnectionChanged(UPSTREAM_IFACE2); 608 InOrder inOrder = inOrder(mBpfCoordinator, mRoutingCoordinatorManager); 609 610 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>. 611 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE); 612 inOrder.verify(mRoutingCoordinatorManager) 613 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 614 615 // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on 616 // ipfwdAddInterfaceForward. 617 inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2, 618 UPSTREAM_IFACE2); 619 inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2); 620 inOrder.verify(mRoutingCoordinatorManager).addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 621 622 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback. 623 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2); 624 inOrder.verify(mRoutingCoordinatorManager) 625 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 626 } 627 628 @Test canUnrequestTetheringWithUpstream()629 public void canUnrequestTetheringWithUpstream() throws Exception { 630 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); 631 632 clearInvocations( 633 mNetd, mCallback, mBpfCoordinator, mRoutingCoordinatorManager); 634 dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); 635 InOrder inOrder = inOrder(mNetd, mCallback, mBpfCoordinator, mRoutingCoordinatorManager); 636 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE); 637 inOrder.verify(mRoutingCoordinatorManager) 638 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 639 inOrder.verify(mBpfCoordinator).updateIpv6UpstreamInterface( 640 mIpServer, NO_UPSTREAM, NO_PREFIXES); 641 // When tethering stops, upstream interface is set to zero and thus clearing all upstream 642 // rules. Downstream rules are needed to be cleared explicitly by calling 643 // BpfCoordinator#clearAllIpv6Rules in TetheredState#exit. 644 inOrder.verify(mBpfCoordinator).clearAllIpv6Rules(mIpServer); 645 inOrder.verify(mNetd).tetherApplyDnsInterfaces(); 646 inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME); 647 if (isTetheringNetworkAgentFeatureEnabled()) { 648 inOrder.verify(mNetd, never()).networkRemoveInterface(anyInt(), anyString()); 649 } else { 650 inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 651 } 652 inOrder.verify(mNetd, times(isAtLeastT() ? 2 : 1)).interfaceSetCfg( 653 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 654 inOrder.verify(mRoutingCoordinatorManager).releaseDownstream(any()); 655 inOrder.verify(mBpfCoordinator).tetherOffloadClientClear(mIpServer); 656 inOrder.verify(mBpfCoordinator).removeIpServer(mIpServer); 657 inOrder.verify(mCallback).updateInterfaceState( 658 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); 659 inOrder.verify(mCallback).updateLinkProperties( 660 eq(mIpServer), any(LinkProperties.class)); 661 verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager, mBpfCoordinator); 662 } 663 664 @Test interfaceDownLeadsToUnavailable()665 public void interfaceDownLeadsToUnavailable() throws Exception { 666 for (boolean shouldThrow : new boolean[]{true, false}) { 667 initTetheredStateMachine(TETHERING_USB, null); 668 669 if (shouldThrow) { 670 doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME); 671 } 672 dispatchCommand(IpServer.CMD_INTERFACE_DOWN); 673 InOrder usbTeardownOrder = inOrder(mNetd, mCallback); 674 // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down 675 // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address. 676 usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( 677 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 678 usbTeardownOrder.verify(mCallback).updateInterfaceState( 679 mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR); 680 usbTeardownOrder.verify(mCallback).updateLinkProperties( 681 eq(mIpServer), mLinkPropertiesCaptor.capture()); 682 assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); 683 } 684 } 685 686 @Test usbShouldBeTornDownOnTetherError()687 public void usbShouldBeTornDownOnTetherError() throws Exception { 688 initStateMachine(TETHERING_USB); 689 690 doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME); 691 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 692 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL)); 693 InOrder usbTeardownOrder = inOrder(mNetd, mCallback); 694 usbTeardownOrder.verify(mNetd).interfaceSetCfg( 695 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 696 usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 697 698 usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( 699 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 700 usbTeardownOrder.verify(mCallback).updateInterfaceState( 701 mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR); 702 usbTeardownOrder.verify(mCallback).updateLinkProperties( 703 eq(mIpServer), mLinkPropertiesCaptor.capture()); 704 assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); 705 verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_USB), 706 eq(TETHER_ERROR_TETHER_IFACE_ERROR)); 707 verify(mTetheringMetrics).sendReport(eq(TETHERING_USB)); 708 } 709 710 @Test shouldTearDownUsbOnUpstreamError()711 public void shouldTearDownUsbOnUpstreamError() throws Exception { 712 initTetheredStateMachine(TETHERING_USB, null); 713 714 doThrow(RuntimeException.class) 715 .when(mRoutingCoordinatorManager) 716 .addInterfaceForward(anyString(), anyString()); 717 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 718 InOrder usbTeardownOrder = inOrder(mNetd, mCallback, mRoutingCoordinatorManager); 719 usbTeardownOrder 720 .verify(mRoutingCoordinatorManager) 721 .addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 722 723 usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( 724 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 725 usbTeardownOrder.verify(mCallback).updateInterfaceState( 726 mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_FORWARDING_ERROR); 727 usbTeardownOrder.verify(mCallback).updateLinkProperties( 728 eq(mIpServer), mLinkPropertiesCaptor.capture()); 729 assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); 730 verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_USB), 731 eq(TETHER_ERROR_ENABLE_FORWARDING_ERROR)); 732 verify(mTetheringMetrics).sendReport(eq(TETHERING_USB)); 733 } 734 735 @Test ignoresDuplicateUpstreamNotifications()736 public void ignoresDuplicateUpstreamNotifications() throws Exception { 737 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 738 739 verifyNoMoreInteractions(mNetd, mCallback); 740 741 for (int i = 0; i < 5; i++) { 742 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 743 verifyNoMoreInteractions(mNetd, mCallback); 744 } 745 } 746 747 @Test startsDhcpServer()748 public void startsDhcpServer() throws Exception { 749 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 750 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 751 752 assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress)); 753 } 754 755 @Test startsDhcpServerOnBluetooth()756 public void startsDhcpServerOnBluetooth() throws Exception { 757 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); 758 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 759 760 if (isAtLeastT()) { 761 assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress)); 762 } else { 763 assertDhcpStarted(mBluetoothPrefix); 764 } 765 } 766 767 @Test startsDhcpServerOnWifiP2p()768 public void startsDhcpServerOnWifiP2p() throws Exception { 769 initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE); 770 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 771 772 assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress)); 773 } 774 775 @Test startsDhcpServerOnNcm()776 public void startsDhcpServerOnNcm() throws Exception { 777 initStateMachine(TETHERING_NCM); 778 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 779 createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL)); 780 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 781 782 assertDhcpStarted(new IpPrefix("192.168.42.0/24")); 783 } 784 785 @Test testOnNewPrefixRequest()786 public void testOnNewPrefixRequest() throws Exception { 787 initStateMachine(TETHERING_NCM); 788 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 789 createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL)); 790 791 final IDhcpEventCallbacks eventCallbacks; 792 final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor = 793 ArgumentCaptor.forClass(IDhcpEventCallbacks.class); 794 verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks( 795 any(), dhcpEventCbsCaptor.capture()); 796 eventCallbacks = dhcpEventCbsCaptor.getValue(); 797 assertDhcpStarted(new IpPrefix("192.168.42.0/24")); 798 799 final ArgumentCaptor<LinkProperties> lpCaptor = 800 ArgumentCaptor.forClass(LinkProperties.class); 801 InOrder inOrder = inOrder(mNetd, mCallback, mRoutingCoordinatorManager); 802 inOrder.verify(mRoutingCoordinatorManager).requestStickyDownstreamAddress(anyInt(), 803 eq(CONNECTIVITY_SCOPE_LOCAL), any()); 804 inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any()); 805 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 806 // One for ipv4 route, one for ipv6 link local route. 807 inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), 808 any(), any()); 809 inOrder.verify(mCallback).updateInterfaceState( 810 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); 811 inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture()); 812 verifyNoMoreInteractions(mCallback, mRoutingCoordinatorManager); 813 814 // Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals 815 // onNewPrefixRequest callback. 816 final LinkAddress newAddress = new LinkAddress("192.168.100.125/24"); 817 when(mRoutingCoordinatorManager.requestDownstreamAddress(any())).thenReturn(newAddress); 818 eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24")); 819 mLooper.dispatchAll(); 820 821 inOrder.verify(mRoutingCoordinatorManager, never()) 822 .requestStickyDownstreamAddress(anyInt(), anyInt(), any()); 823 inOrder.verify(mRoutingCoordinatorManager).requestDownstreamAddress(any()); 824 inOrder.verify(mNetd).tetherApplyDnsInterfaces(); 825 inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture()); 826 verifyNoMoreInteractions(mCallback); 827 828 final LinkProperties linkProperties = lpCaptor.getValue(); 829 final List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses(); 830 assertEquals(1, linkProperties.getLinkAddresses().size()); 831 assertEquals(1, linkProperties.getRoutes().size()); 832 final IpPrefix prefix = new IpPrefix(linkAddresses.get(0).getAddress(), 833 linkAddresses.get(0).getPrefixLength()); 834 assertNotEquals(prefix, new IpPrefix("192.168.42.0/24")); 835 836 verify(mDhcpServer).updateParams(mDhcpParamsCaptor.capture(), any()); 837 assertDhcpServingParams(mDhcpParamsCaptor.getValue(), prefix); 838 } 839 840 @Test doesNotStartDhcpServerIfDisabled()841 public void doesNotStartDhcpServerIfDisabled() throws Exception { 842 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, NO_ADDRESSES, 843 true /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD); 844 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 845 846 verify(mDependencies, never()).makeDhcpServer(any(), any(), any()); 847 } 848 849 @Test ipv6UpstreamInterfaceChanges()850 public void ipv6UpstreamInterfaceChanges() throws Exception { 851 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, UPSTREAM_ADDRESSES, 852 false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD); 853 854 // Upstream interface changes result in updating the rules. 855 LinkProperties lp = new LinkProperties(); 856 lp.setInterfaceName(UPSTREAM_IFACE2); 857 lp.setLinkAddresses(UPSTREAM_ADDRESSES); 858 dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1); 859 verify(mBpfCoordinator).updateIpv6UpstreamInterface( 860 mIpServer, UPSTREAM_IFINDEX2, UPSTREAM_PREFIXES); 861 reset(mBpfCoordinator); 862 863 // Upstream link addresses change result in updating the rules. 864 LinkProperties lp2 = new LinkProperties(); 865 lp2.setInterfaceName(UPSTREAM_IFACE2); 866 lp2.setLinkAddresses(UPSTREAM_ADDRESSES2); 867 dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, -1); 868 verify(mBpfCoordinator).updateIpv6UpstreamInterface( 869 mIpServer, UPSTREAM_IFINDEX2, UPSTREAM_PREFIXES2); 870 reset(mBpfCoordinator); 871 872 // When the upstream is lost, rules are removed. 873 dispatchTetherConnectionChanged(null, null, 0); 874 // Upstream clear function is called two times by: 875 // - processMessage CMD_TETHER_CONNECTION_CHANGED for the upstream is lost. 876 // - processMessage CMD_IPV6_TETHER_UPDATE for the IPv6 upstream is lost. 877 // See dispatchTetherConnectionChanged. 878 verify(mBpfCoordinator, times(2)).updateIpv6UpstreamInterface( 879 mIpServer, NO_UPSTREAM, NO_PREFIXES); 880 reset(mBpfCoordinator); 881 882 // If the upstream is IPv4-only, no rules are added. 883 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 884 verify(mBpfCoordinator, never()).updateIpv6UpstreamInterface( 885 mIpServer, NO_UPSTREAM, NO_PREFIXES); 886 reset(mBpfCoordinator); 887 888 // Rules are added again once upstream IPv6 connectivity is available. 889 lp.setInterfaceName(UPSTREAM_IFACE); 890 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); 891 verify(mBpfCoordinator).updateIpv6UpstreamInterface( 892 mIpServer, UPSTREAM_IFINDEX, UPSTREAM_PREFIXES); 893 reset(mBpfCoordinator); 894 895 // If upstream IPv6 connectivity is lost, rules are removed. 896 dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); 897 verify(mBpfCoordinator).updateIpv6UpstreamInterface( 898 mIpServer, NO_UPSTREAM, NO_PREFIXES); 899 reset(mBpfCoordinator); 900 901 // When upstream IPv6 connectivity comes back, rules are added. 902 lp.setInterfaceName(UPSTREAM_IFACE); 903 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); 904 verify(mBpfCoordinator).updateIpv6UpstreamInterface( 905 mIpServer, UPSTREAM_IFINDEX, UPSTREAM_PREFIXES); 906 reset(mBpfCoordinator); 907 908 // When the downstream interface goes down, rules are removed. 909 mIpServer.stop(); 910 mLooper.dispatchAll(); 911 verify(mBpfCoordinator).clearAllIpv6Rules(mIpServer); 912 verify(mBpfCoordinator).removeIpServer(mIpServer); 913 verify(mBpfCoordinator).updateIpv6UpstreamInterface( 914 mIpServer, NO_UPSTREAM, NO_PREFIXES); 915 reset(mBpfCoordinator); 916 } 917 918 @Test removeIpServerWhenInterfaceDown()919 public void removeIpServerWhenInterfaceDown() throws Exception { 920 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, UPSTREAM_ADDRESSES, 921 false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD); 922 923 mIpServer.stop(); 924 mLooper.dispatchAll(); 925 verify(mBpfCoordinator).removeIpServer(mIpServer); 926 } 927 buildIpv6OnlyLinkProperties(final String iface)928 private LinkProperties buildIpv6OnlyLinkProperties(final String iface) { 929 final LinkProperties linkProp = new LinkProperties(); 930 linkProp.setInterfaceName(iface); 931 linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64")); 932 linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST)); 933 final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888"); 934 linkProp.addDnsServer(dns); 935 936 return linkProp; 937 } 938 939 @Test testAdjustTtlValue()940 public void testAdjustTtlValue() throws Exception { 941 final ArgumentCaptor<RaParams> raParamsCaptor = 942 ArgumentCaptor.forClass(RaParams.class); 943 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 944 verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); 945 final RaParams noV6Params = raParamsCaptor.getValue(); 946 assertEquals(65, noV6Params.hopLimit); 947 reset(mRaDaemon); 948 949 when(mNetd.getProcSysNet( 950 INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64"); 951 final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE); 952 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1); 953 verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); 954 final RaParams nonCellularParams = raParamsCaptor.getValue(); 955 assertEquals(65, nonCellularParams.hopLimit); 956 reset(mRaDaemon); 957 958 dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); 959 verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); 960 final RaParams noUpstream = raParamsCaptor.getValue(); 961 assertEquals(65, nonCellularParams.hopLimit); 962 reset(mRaDaemon); 963 964 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); 965 verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); 966 final RaParams cellularParams = raParamsCaptor.getValue(); 967 assertEquals(63, cellularParams.hopLimit); 968 reset(mRaDaemon); 969 } 970 971 @Test testStopObsoleteDhcpServer()972 public void testStopObsoleteDhcpServer() throws Exception { 973 final ArgumentCaptor<DhcpServerCallbacks> cbCaptor = 974 ArgumentCaptor.forClass(DhcpServerCallbacks.class); 975 doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), 976 cbCaptor.capture()); 977 initStateMachine(TETHERING_WIFI); 978 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0, 979 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL)); 980 verify(mDhcpServer, never()).startWithCallbacks(any(), any()); 981 982 // No stop dhcp server because dhcp server is not created yet. 983 dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); 984 verify(mDhcpServer, never()).stop(any()); 985 986 // Stop obsolete dhcp server. 987 try { 988 final DhcpServerCallbacks cb = cbCaptor.getValue(); 989 cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); 990 mLooper.dispatchAll(); 991 } catch (RemoteException e) { 992 fail(e.getMessage()); 993 } 994 verify(mDhcpServer).stop(any()); 995 } 996 assertDhcpServingParams(final DhcpServingParamsParcel params, final IpPrefix prefix)997 private void assertDhcpServingParams(final DhcpServingParamsParcel params, 998 final IpPrefix prefix) { 999 // Last address byte is random 1000 assertTrue(prefix.contains(intToInet4AddressHTH(params.serverAddr))); 1001 assertEquals(prefix.getPrefixLength(), params.serverAddrPrefixLength); 1002 assertEquals(1, params.defaultRouters.length); 1003 assertEquals(params.serverAddr, params.defaultRouters[0]); 1004 assertEquals(1, params.dnsServers.length); 1005 assertEquals(params.serverAddr, params.dnsServers[0]); 1006 assertEquals(DHCP_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs); 1007 if (mIpServer.interfaceType() == TETHERING_NCM) { 1008 assertTrue(params.changePrefixOnDecline); 1009 } 1010 1011 if (mIpServer.interfaceType() == TETHERING_WIFI_P2P) { 1012 assertEquals(P2P_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength); 1013 } else { 1014 assertEquals(DEFAULT_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength); 1015 } 1016 } 1017 assertDhcpStarted(IpPrefix expectedPrefix)1018 private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception { 1019 verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any()); 1020 verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks( 1021 any(), any()); 1022 assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix); 1023 } 1024 createMockTetheringRequest(int connectivityScope)1025 private TetheringRequest createMockTetheringRequest(int connectivityScope) { 1026 TetheringRequest request = mock(TetheringRequest.class); 1027 when(request.getConnectivityScope()).thenReturn(connectivityScope); 1028 return request; 1029 } 1030 1031 /** 1032 * Send a command to the state machine under test, and run the event loop to idle. 1033 * 1034 * @param command One of the IpServer.CMD_* constants. 1035 * @param arg1 An additional argument to pass. 1036 * @param arg2 An additional argument to pass. 1037 * @param obj An additional object to pass. 1038 */ dispatchCommand(int command, int arg1, int arg2, Object obj)1039 private void dispatchCommand(int command, int arg1, int arg2, Object obj) { 1040 mIpServer.sendMessage(command, arg1, arg2, obj); 1041 mLooper.dispatchAll(); 1042 } 1043 1044 /** 1045 * Send a command to the state machine under test, and run the event loop to idle. 1046 * 1047 * @param command One of the IpServer.CMD_* constants. 1048 */ dispatchCommand(int command)1049 private void dispatchCommand(int command) { 1050 mIpServer.sendMessage(command); 1051 mLooper.dispatchAll(); 1052 } 1053 1054 /** 1055 * Special override to tell the state machine that the upstream interface has changed. 1056 * 1057 * @see #dispatchCommand(int) 1058 * @param upstreamIface String name of upstream interface (or null) 1059 * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream. 1060 */ dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, int ttlAdjustment)1061 private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, 1062 int ttlAdjustment) { 1063 dispatchTetherConnectionChanged(upstreamIface); 1064 mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp); 1065 mLooper.dispatchAll(); 1066 } 1067 dispatchTetherConnectionChanged(String upstreamIface)1068 private void dispatchTetherConnectionChanged(String upstreamIface) { 1069 final InterfaceSet ifs = (upstreamIface != null) ? new InterfaceSet(upstreamIface) : null; 1070 mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifs); 1071 mLooper.dispatchAll(); 1072 } 1073 assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp)1074 private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) { 1075 // Find the first IPv4 LinkAddress. 1076 LinkAddress addr4 = null; 1077 for (LinkAddress addr : lp.getLinkAddresses()) { 1078 if (!(addr.getAddress() instanceof Inet4Address)) continue; 1079 addr4 = addr; 1080 break; 1081 } 1082 assertNotNull("missing IPv4 address", addr4); 1083 1084 final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength()); 1085 // Assert the presence of the associated directly connected route. 1086 final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(), 1087 RouteInfo.RTN_UNICAST); 1088 assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'", 1089 lp.getRoutes().contains(directlyConnected)); 1090 } 1091 assertNoAddressesNorRoutes(LinkProperties lp)1092 private void assertNoAddressesNorRoutes(LinkProperties lp) { 1093 assertTrue(lp.getLinkAddresses().isEmpty()); 1094 assertTrue(lp.getRoutes().isEmpty()); 1095 // We also check that interface name is non-empty, because we should 1096 // never see an empty interface name in any LinkProperties update. 1097 assertFalse(TextUtils.isEmpty(lp.getInterfaceName())); 1098 } 1099 assertContainsFlag(String[] flags, String match)1100 private boolean assertContainsFlag(String[] flags, String match) { 1101 for (String flag : flags) { 1102 if (flag.equals(match)) return true; 1103 } 1104 return false; 1105 } 1106 assertNotContainsFlag(String[] flags, String match)1107 private boolean assertNotContainsFlag(String[] flags, String match) { 1108 for (String flag : flags) { 1109 if (flag.equals(match)) { 1110 fail("Unexpected flag: " + match); 1111 return false; 1112 } 1113 } 1114 return true; 1115 } 1116 1117 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1118 @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) 1119 @Test testTetheringNetworkAgent_tetheringAgentEnabled()1120 public void testTetheringNetworkAgent_tetheringAgentEnabled() throws Exception { 1121 doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, true); 1122 } 1123 1124 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1125 @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT, enabled = false) 1126 @Test testTetheringNetworkAgent_tetheringAgentDisabled()1127 public void testTetheringNetworkAgent_tetheringAgentDisabled() throws Exception { 1128 doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, false); 1129 } 1130 1131 // Verify Tethering Network Agent feature doesn't affect Wi-fi P2P Group Owner although 1132 // the code is mostly shared. 1133 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1134 @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) 1135 @Test testTetheringNetworkAgent_p2pGroupOwnerAgentDisabled()1136 public void testTetheringNetworkAgent_p2pGroupOwnerAgentDisabled() throws Exception { 1137 doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false); 1138 } 1139 doTestTetheringNetworkAgent(int scope, boolean expectAgentEnabled)1140 private void doTestTetheringNetworkAgent(int scope, boolean expectAgentEnabled) 1141 throws Exception { 1142 initStateMachine(TETHERING_USB); 1143 1144 final InOrder inOrder = inOrder(mNetworkAgent, mNetd); 1145 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED, 1146 0, createMockTetheringRequest(scope)); 1147 1148 inOrder.verify(mNetworkAgent, expectAgentEnabled ? times(1) : never()).register(); 1149 inOrder.verify(mNetd, times(1)).tetherInterfaceAdd(anyString()); 1150 if (expectAgentEnabled) { 1151 inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString()); 1152 inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any()); 1153 inOrder.verify(mNetworkAgent, times(1)).sendLinkProperties(any()); 1154 inOrder.verify(mNetworkAgent, times(1)).markConnected(); 1155 } else { 1156 inOrder.verify(mNetd, times(1)).networkAddInterface(anyInt(), anyString()); 1157 inOrder.verify(mNetd, times(2)).networkAddRoute(anyInt(), anyString(), any(), any()); 1158 inOrder.verify(mNetworkAgent, never()).sendLinkProperties(any()); 1159 inOrder.verify(mNetworkAgent, never()).markConnected(); 1160 } 1161 1162 dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); 1163 if (expectAgentEnabled) { 1164 inOrder.verify(mNetworkAgent, times(1)).unregister(); 1165 inOrder.verify(mNetd, never()).networkRemoveInterface(anyInt(), anyString()); 1166 } else { 1167 inOrder.verify(mNetworkAgent, never()).unregister(); 1168 inOrder.verify(mNetd, times(1)).networkRemoveInterface(anyInt(), anyString()); 1169 } 1170 } 1171 1172 // Verify if the registration failed, tethering can be gracefully shutdown. 1173 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1174 @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) 1175 @Test testTetheringNetworkAgent_registerThrows()1176 public void testTetheringNetworkAgent_registerThrows() throws Exception { 1177 initStateMachine(TETHERING_USB); 1178 1179 final InOrder inOrder = inOrder(mNetworkAgent, mNetd, mCallback); 1180 doReturn(null).when(mNetworkAgent).getNetwork(); 1181 doThrow(IllegalStateException.class).when(mNetworkAgent).register(); 1182 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED, 1183 0, createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL)); 1184 1185 inOrder.verify(mNetworkAgent).register(); 1186 inOrder.verify(mNetd, never()).networkCreate(any()); 1187 inOrder.verify(mNetworkAgent, never()).sendLinkProperties(any()); 1188 inOrder.verify(mNetworkAgent, never()).markConnected(); 1189 inOrder.verify(mNetworkAgent, never()).unregister(); 1190 inOrder.verify(mNetd, never()).networkDestroy(anyInt()); 1191 inOrder.verify(mCallback).updateInterfaceState( 1192 mIpServer, STATE_AVAILABLE, TETHER_ERROR_SERVICE_UNAVAIL); 1193 } 1194 1195 // Verify if the network creation failed, tethering can be gracefully shutdown. 1196 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1197 @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) 1198 @Test testTetheringNetworkAgent_netdThrows()1199 public void testTetheringNetworkAgent_netdThrows() throws Exception { 1200 initStateMachine(TETHERING_USB); 1201 1202 final InOrder inOrder = inOrder(mNetworkAgent, mNetd, mCallback); 1203 doThrow(ServiceSpecificException.class).when(mNetd).tetherInterfaceAdd(any()); 1204 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED, 1205 0, createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL)); 1206 1207 inOrder.verify(mNetworkAgent).register(); 1208 inOrder.verify(mNetd, never()).networkCreate(any()); 1209 inOrder.verify(mNetworkAgent, never()).sendLinkProperties(any()); 1210 inOrder.verify(mNetworkAgent, never()).markConnected(); 1211 inOrder.verify(mNetworkAgent).unregister(); 1212 inOrder.verify(mNetd, never()).networkDestroy(anyInt()); 1213 inOrder.verify(mCallback).updateInterfaceState( 1214 mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR); 1215 } 1216 1217 // Verify when IPv6 address update, set routes accordingly. 1218 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1219 @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) 1220 @Test testTetheringNetworkAgent_ipv6AddressUpdate()1221 public void testTetheringNetworkAgent_ipv6AddressUpdate() throws Exception { 1222 initStateMachine(TETHERING_USB); 1223 1224 final InOrder inOrder = inOrder(mNetworkAgent, mNetd); 1225 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED, 1226 0, createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL)); 1227 1228 inOrder.verify(mNetworkAgent).register(); 1229 inOrder.verify(mNetd, never()).networkCreate(any()); 1230 inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any()); 1231 1232 // Ipv6 link local route won't show up in the LinkProperties, so just 1233 // verify ipv4 route. 1234 final ArgumentCaptor<LinkProperties> lpCaptor = 1235 ArgumentCaptor.forClass(LinkProperties.class); 1236 inOrder.verify(mNetworkAgent).sendLinkProperties(lpCaptor.capture()); 1237 final RouteInfo expectedIpv4Route = new RouteInfo(PrefixUtils.asIpPrefix(mTestAddress), 1238 null, IFACE_NAME, RouteInfo.RTN_UNICAST); 1239 assertRoutes(List.of(expectedIpv4Route), lpCaptor.getValue().getRoutes()); 1240 assertEquals(IFACE_NAME, lpCaptor.getValue().getInterfaceName()); 1241 1242 inOrder.verify(mNetworkAgent).markConnected(); 1243 1244 // Mock ipv4-only upstream show up. 1245 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 1246 inOrder.verifyNoMoreInteractions(); 1247 1248 // Verify LinkProperties is updated when IPv6 connectivity is available. 1249 final LinkProperties lp = new LinkProperties(); 1250 lp.setInterfaceName(UPSTREAM_IFACE); 1251 lp.setLinkAddresses(UPSTREAM_ADDRESSES); 1252 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); 1253 inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any()); 1254 inOrder.verify(mNetworkAgent).sendLinkProperties(lpCaptor.capture()); 1255 1256 // Expect one Ipv4 route, plus one Ipv6 route. 1257 final RouteInfo expectedIpv6Route = new RouteInfo(UPSTREAM_PREFIXES.toArray( 1258 new IpPrefix[0])[0], null, IFACE_NAME, RouteInfo.RTN_UNICAST); 1259 assertRoutes(List.of(expectedIpv4Route, expectedIpv6Route), 1260 lpCaptor.getValue().getRoutes()); 1261 assertEquals(IFACE_NAME, lpCaptor.getValue().getInterfaceName()); 1262 1263 dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); 1264 inOrder.verify(mNetworkAgent).unregister(); 1265 inOrder.verify(mNetd, never()).networkDestroy(anyInt()); 1266 } 1267 assertRoutes(List<RouteInfo> expectedRoutes, List<RouteInfo> actualRoutes)1268 private void assertRoutes(List<RouteInfo> expectedRoutes, List<RouteInfo> actualRoutes) { 1269 assertTrue("Expected Routes: " + expectedRoutes + ", but got: " + actualRoutes, 1270 expectedRoutes.equals(actualRoutes)); 1271 } 1272 1273 @Test @IgnoreUpTo(Build.VERSION_CODES.R) dadProxyUpdates()1274 public void dadProxyUpdates() throws Exception { 1275 InOrder inOrder = inOrder(mDadProxy); 1276 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 1277 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1278 1279 // Add an upstream without IPv6. 1280 dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); 1281 inOrder.verify(mDadProxy).setUpstreamIface(null); 1282 1283 // Add IPv6 to the upstream. 1284 LinkProperties lp = new LinkProperties(); 1285 lp.setInterfaceName(UPSTREAM_IFACE); 1286 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); 1287 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1288 1289 // Change upstream. 1290 // New linkproperties is needed, otherwise changing the iface has no impact. 1291 LinkProperties lp2 = new LinkProperties(); 1292 lp2.setInterfaceName(UPSTREAM_IFACE2); 1293 dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, 0); 1294 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS2); 1295 1296 // Lose IPv6 on the upstream... 1297 dispatchTetherConnectionChanged(UPSTREAM_IFACE2, null, 0); 1298 inOrder.verify(mDadProxy).setUpstreamIface(null); 1299 1300 // ... and regain it on a different upstream. 1301 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); 1302 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1303 1304 // Lose upstream. 1305 dispatchTetherConnectionChanged(null, null, 0); 1306 inOrder.verify(mDadProxy).setUpstreamIface(null); 1307 1308 // Regain upstream. 1309 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); 1310 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1311 1312 // Stop tethering. 1313 mIpServer.stop(); 1314 mLooper.dispatchAll(); 1315 } 1316 checkDadProxyEnabled(boolean expectEnabled)1317 private void checkDadProxyEnabled(boolean expectEnabled) throws Exception { 1318 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 1319 InOrder inOrder = inOrder(mDadProxy); 1320 // Add IPv6 to the upstream. 1321 LinkProperties lp = new LinkProperties(); 1322 lp.setInterfaceName(UPSTREAM_IFACE); 1323 if (expectEnabled) { 1324 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1325 } else { 1326 inOrder.verifyNoMoreInteractions(); 1327 } 1328 // Stop tethering. 1329 mIpServer.stop(); 1330 mLooper.dispatchAll(); 1331 if (expectEnabled) { 1332 inOrder.verify(mDadProxy).stop(); 1333 } 1334 else { 1335 verify(mDependencies, never()).getDadProxy(any(), any()); 1336 } 1337 } 1338 @Test @IgnoreAfter(Build.VERSION_CODES.R) testDadProxyUpdates_DisabledUpToR()1339 public void testDadProxyUpdates_DisabledUpToR() throws Exception { 1340 checkDadProxyEnabled(false); 1341 } 1342 @Test @IgnoreUpTo(Build.VERSION_CODES.R) testDadProxyUpdates_EnabledAfterR()1343 public void testDadProxyUpdates_EnabledAfterR() throws Exception { 1344 checkDadProxyEnabled(true); 1345 } 1346 } 1347