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.TETHERING_BLUETOOTH; 23 import static android.net.TetheringManager.TETHERING_NCM; 24 import static android.net.TetheringManager.TETHERING_USB; 25 import static android.net.TetheringManager.TETHERING_WIFI; 26 import static android.net.TetheringManager.TETHERING_WIFI_P2P; 27 import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR; 28 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; 29 import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; 30 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; 31 import static android.net.ip.IpServer.STATE_AVAILABLE; 32 import static android.net.ip.IpServer.STATE_LOCAL_ONLY; 33 import static android.net.ip.IpServer.STATE_TETHERED; 34 import static android.net.ip.IpServer.STATE_UNAVAILABLE; 35 import static android.system.OsConstants.ETH_P_IPV6; 36 37 import static com.android.modules.utils.build.SdkLevel.isAtLeastT; 38 import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; 39 import static com.android.net.module.util.netlink.NetlinkConstants.RTM_DELNEIGH; 40 import static com.android.net.module.util.netlink.NetlinkConstants.RTM_NEWNEIGH; 41 import static com.android.net.module.util.netlink.StructNdMsg.NUD_FAILED; 42 import static com.android.net.module.util.netlink.StructNdMsg.NUD_REACHABLE; 43 import static com.android.net.module.util.netlink.StructNdMsg.NUD_STALE; 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.argThat; 52 import static org.mockito.Matchers.any; 53 import static org.mockito.Matchers.anyBoolean; 54 import static org.mockito.Matchers.anyString; 55 import static org.mockito.Matchers.eq; 56 import static org.mockito.Mockito.doAnswer; 57 import static org.mockito.Mockito.doNothing; 58 import static org.mockito.Mockito.doReturn; 59 import static org.mockito.Mockito.doThrow; 60 import static org.mockito.Mockito.inOrder; 61 import static org.mockito.Mockito.never; 62 import static org.mockito.Mockito.reset; 63 import static org.mockito.Mockito.spy; 64 import static org.mockito.Mockito.timeout; 65 import static org.mockito.Mockito.times; 66 import static org.mockito.Mockito.verify; 67 import static org.mockito.Mockito.verifyNoMoreInteractions; 68 import static org.mockito.Mockito.when; 69 70 import android.app.usage.NetworkStatsManager; 71 import android.net.INetd; 72 import android.net.InetAddresses; 73 import android.net.InterfaceConfigurationParcel; 74 import android.net.IpPrefix; 75 import android.net.LinkAddress; 76 import android.net.LinkProperties; 77 import android.net.MacAddress; 78 import android.net.RouteInfo; 79 import android.net.TetherOffloadRuleParcel; 80 import android.net.TetherStatsParcel; 81 import android.net.dhcp.DhcpServerCallbacks; 82 import android.net.dhcp.DhcpServingParamsParcel; 83 import android.net.dhcp.IDhcpEventCallbacks; 84 import android.net.dhcp.IDhcpServer; 85 import android.net.dhcp.IDhcpServerCallbacks; 86 import android.net.ip.IpNeighborMonitor.NeighborEvent; 87 import android.net.ip.IpNeighborMonitor.NeighborEventConsumer; 88 import android.net.ip.RouterAdvertisementDaemon.RaParams; 89 import android.net.util.SharedLog; 90 import android.os.Build; 91 import android.os.Handler; 92 import android.os.RemoteException; 93 import android.os.test.TestLooper; 94 import android.text.TextUtils; 95 96 import androidx.annotation.NonNull; 97 import androidx.annotation.Nullable; 98 import androidx.test.filters.SmallTest; 99 import androidx.test.runner.AndroidJUnit4; 100 101 import com.android.net.module.util.BpfMap; 102 import com.android.net.module.util.InterfaceParams; 103 import com.android.net.module.util.NetworkStackConstants; 104 import com.android.net.module.util.bpf.Tether4Key; 105 import com.android.net.module.util.bpf.Tether4Value; 106 import com.android.net.module.util.bpf.TetherStatsKey; 107 import com.android.net.module.util.bpf.TetherStatsValue; 108 import com.android.networkstack.tethering.BpfCoordinator; 109 import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule; 110 import com.android.networkstack.tethering.PrivateAddressCoordinator; 111 import com.android.networkstack.tethering.Tether6Value; 112 import com.android.networkstack.tethering.TetherDevKey; 113 import com.android.networkstack.tethering.TetherDevValue; 114 import com.android.networkstack.tethering.TetherDownstream6Key; 115 import com.android.networkstack.tethering.TetherLimitKey; 116 import com.android.networkstack.tethering.TetherLimitValue; 117 import com.android.networkstack.tethering.TetherUpstream6Key; 118 import com.android.networkstack.tethering.TetheringConfiguration; 119 import com.android.networkstack.tethering.util.InterfaceSet; 120 import com.android.networkstack.tethering.util.PrefixUtils; 121 import com.android.testutils.DevSdkIgnoreRule; 122 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; 123 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 124 125 import org.junit.Before; 126 import org.junit.Rule; 127 import org.junit.Test; 128 import org.junit.runner.RunWith; 129 import org.mockito.ArgumentCaptor; 130 import org.mockito.ArgumentMatcher; 131 import org.mockito.Captor; 132 import org.mockito.InOrder; 133 import org.mockito.Mock; 134 import org.mockito.MockitoAnnotations; 135 136 import java.net.Inet4Address; 137 import java.net.Inet6Address; 138 import java.net.InetAddress; 139 import java.util.Arrays; 140 import java.util.List; 141 142 @RunWith(AndroidJUnit4.class) 143 @SmallTest 144 public class IpServerTest { 145 @Rule 146 public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); 147 148 private static final String IFACE_NAME = "testnet1"; 149 private static final String UPSTREAM_IFACE = "upstream0"; 150 private static final String UPSTREAM_IFACE2 = "upstream1"; 151 private static final String IPSEC_IFACE = "ipsec0"; 152 private static final int UPSTREAM_IFINDEX = 101; 153 private static final int UPSTREAM_IFINDEX2 = 102; 154 private static final int IPSEC_IFINDEX = 103; 155 private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1"; 156 private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24; 157 private static final int DHCP_LEASE_TIME_SECS = 3600; 158 private static final boolean DEFAULT_USING_BPF_OFFLOAD = true; 159 private static final int DEFAULT_SUBNET_PREFIX_LENGTH = 0; 160 private static final int P2P_SUBNET_PREFIX_LENGTH = 25; 161 162 private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams( 163 IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); 164 private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams( 165 UPSTREAM_IFACE, UPSTREAM_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); 166 private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams( 167 UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.ALL_ZEROS_ADDRESS, 168 1500 /* defaultMtu */); 169 private static final InterfaceParams IPSEC_IFACE_PARAMS = new InterfaceParams( 170 IPSEC_IFACE, IPSEC_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); 171 172 private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000; 173 174 private final LinkAddress mTestAddress = new LinkAddress("192.168.42.5/24"); 175 private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24"); 176 177 @Mock private INetd mNetd; 178 @Mock private IpServer.Callback mCallback; 179 @Mock private SharedLog mSharedLog; 180 @Mock private IDhcpServer mDhcpServer; 181 @Mock private DadProxy mDadProxy; 182 @Mock private RouterAdvertisementDaemon mRaDaemon; 183 @Mock private IpNeighborMonitor mIpNeighborMonitor; 184 @Mock private IpServer.Dependencies mDependencies; 185 @Mock private PrivateAddressCoordinator mAddressCoordinator; 186 @Mock private NetworkStatsManager mStatsManager; 187 @Mock private TetheringConfiguration mTetherConfig; 188 @Mock private ConntrackMonitor mConntrackMonitor; 189 @Mock private BpfMap<Tether4Key, Tether4Value> mBpfDownstream4Map; 190 @Mock private BpfMap<Tether4Key, Tether4Value> mBpfUpstream4Map; 191 @Mock private BpfMap<TetherDownstream6Key, Tether6Value> mBpfDownstream6Map; 192 @Mock private BpfMap<TetherUpstream6Key, Tether6Value> mBpfUpstream6Map; 193 @Mock private BpfMap<TetherStatsKey, TetherStatsValue> mBpfStatsMap; 194 @Mock private BpfMap<TetherLimitKey, TetherLimitValue> mBpfLimitMap; 195 @Mock private BpfMap<TetherDevKey, TetherDevValue> mBpfDevMap; 196 197 @Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor; 198 199 private final TestLooper mLooper = new TestLooper(); 200 private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor = 201 ArgumentCaptor.forClass(LinkProperties.class); 202 private IpServer mIpServer; 203 private InterfaceConfigurationParcel mInterfaceConfiguration; 204 private NeighborEventConsumer mNeighborEventConsumer; 205 private BpfCoordinator mBpfCoordinator; 206 private BpfCoordinator.Dependencies mBpfDeps; 207 initStateMachine(int interfaceType)208 private void initStateMachine(int interfaceType) throws Exception { 209 initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD); 210 } 211 initStateMachine(int interfaceType, boolean usingLegacyDhcp, boolean usingBpfOffload)212 private void initStateMachine(int interfaceType, boolean usingLegacyDhcp, 213 boolean usingBpfOffload) throws Exception { 214 when(mDependencies.getDadProxy(any(), any())).thenReturn(mDadProxy); 215 when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon); 216 when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS); 217 when(mDependencies.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS); 218 when(mDependencies.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2); 219 when(mDependencies.getInterfaceParams(IPSEC_IFACE)).thenReturn(IPSEC_IFACE_PARAMS); 220 221 mInterfaceConfiguration = new InterfaceConfigurationParcel(); 222 mInterfaceConfiguration.flags = new String[0]; 223 if (interfaceType == TETHERING_BLUETOOTH) { 224 mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR; 225 mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH; 226 } 227 228 ArgumentCaptor<NeighborEventConsumer> neighborCaptor = 229 ArgumentCaptor.forClass(NeighborEventConsumer.class); 230 doReturn(mIpNeighborMonitor).when(mDependencies).getIpNeighborMonitor(any(), any(), 231 neighborCaptor.capture()); 232 233 when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(usingBpfOffload); 234 when(mTetherConfig.useLegacyDhcpServer()).thenReturn(usingLegacyDhcp); 235 when(mTetherConfig.getP2pLeasesSubnetPrefixLength()).thenReturn(P2P_SUBNET_PREFIX_LENGTH); 236 mIpServer = new IpServer( 237 IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mBpfCoordinator, 238 mCallback, mTetherConfig, mAddressCoordinator, mDependencies); 239 mIpServer.start(); 240 mNeighborEventConsumer = neighborCaptor.getValue(); 241 242 // Starting the state machine always puts us in a consistent state and notifies 243 // the rest of the world that we've changed from an unknown to available state. 244 mLooper.dispatchAll(); 245 reset(mNetd, mCallback); 246 247 when(mRaDaemon.start()).thenReturn(true); 248 } 249 initTetheredStateMachine(int interfaceType, String upstreamIface)250 private void initTetheredStateMachine(int interfaceType, String upstreamIface) 251 throws Exception { 252 initTetheredStateMachine(interfaceType, upstreamIface, false, 253 DEFAULT_USING_BPF_OFFLOAD); 254 } 255 initTetheredStateMachine(int interfaceType, String upstreamIface, boolean usingLegacyDhcp, boolean usingBpfOffload)256 private void initTetheredStateMachine(int interfaceType, String upstreamIface, 257 boolean usingLegacyDhcp, boolean usingBpfOffload) throws Exception { 258 initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload); 259 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); 260 if (upstreamIface != null) { 261 LinkProperties lp = new LinkProperties(); 262 lp.setInterfaceName(upstreamIface); 263 dispatchTetherConnectionChanged(upstreamIface, lp, 0); 264 } 265 reset(mNetd, mCallback, mAddressCoordinator, mBpfCoordinator); 266 when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn( 267 mTestAddress); 268 } 269 setUpDhcpServer()270 private void setUpDhcpServer() throws Exception { 271 doAnswer(inv -> { 272 final IDhcpServerCallbacks cb = inv.getArgument(2); 273 new Thread(() -> { 274 try { 275 cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); 276 } catch (RemoteException e) { 277 fail(e.getMessage()); 278 } 279 }).run(); 280 return null; 281 }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any()); 282 } 283 setUp()284 @Before public void setUp() throws Exception { 285 MockitoAnnotations.initMocks(this); 286 when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog); 287 when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn( 288 mTestAddress); 289 when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(DEFAULT_USING_BPF_OFFLOAD); 290 when(mTetherConfig.useLegacyDhcpServer()).thenReturn(false /* default value */); 291 292 mBpfDeps = new BpfCoordinator.Dependencies() { 293 @NonNull 294 public Handler getHandler() { 295 return new Handler(mLooper.getLooper()); 296 } 297 298 @NonNull 299 public INetd getNetd() { 300 return mNetd; 301 } 302 303 @NonNull 304 public NetworkStatsManager getNetworkStatsManager() { 305 return mStatsManager; 306 } 307 308 @NonNull 309 public SharedLog getSharedLog() { 310 return mSharedLog; 311 } 312 313 @Nullable 314 public TetheringConfiguration getTetherConfig() { 315 return mTetherConfig; 316 } 317 318 @NonNull 319 public ConntrackMonitor getConntrackMonitor( 320 ConntrackMonitor.ConntrackEventConsumer consumer) { 321 return mConntrackMonitor; 322 } 323 324 @Nullable 325 public BpfMap<Tether4Key, Tether4Value> getBpfDownstream4Map() { 326 return mBpfDownstream4Map; 327 } 328 329 @Nullable 330 public BpfMap<Tether4Key, Tether4Value> getBpfUpstream4Map() { 331 return mBpfUpstream4Map; 332 } 333 334 @Nullable 335 public BpfMap<TetherDownstream6Key, Tether6Value> getBpfDownstream6Map() { 336 return mBpfDownstream6Map; 337 } 338 339 @Nullable 340 public BpfMap<TetherUpstream6Key, Tether6Value> getBpfUpstream6Map() { 341 return mBpfUpstream6Map; 342 } 343 344 @Nullable 345 public BpfMap<TetherStatsKey, TetherStatsValue> getBpfStatsMap() { 346 return mBpfStatsMap; 347 } 348 349 @Nullable 350 public BpfMap<TetherLimitKey, TetherLimitValue> getBpfLimitMap() { 351 return mBpfLimitMap; 352 } 353 354 @Nullable 355 public BpfMap<TetherDevKey, TetherDevValue> getBpfDevMap() { 356 return mBpfDevMap; 357 } 358 }; 359 mBpfCoordinator = spy(new BpfCoordinator(mBpfDeps)); 360 361 setUpDhcpServer(); 362 } 363 364 @Test startsOutAvailable()365 public void startsOutAvailable() { 366 when(mDependencies.getIpNeighborMonitor(any(), any(), any())) 367 .thenReturn(mIpNeighborMonitor); 368 mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog, 369 mNetd, mBpfCoordinator, mCallback, mTetherConfig, mAddressCoordinator, 370 mDependencies); 371 mIpServer.start(); 372 mLooper.dispatchAll(); 373 verify(mCallback).updateInterfaceState( 374 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); 375 verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class)); 376 verifyNoMoreInteractions(mCallback, mNetd); 377 } 378 379 @Test shouldDoNothingUntilRequested()380 public void shouldDoNothingUntilRequested() throws Exception { 381 initStateMachine(TETHERING_BLUETOOTH); 382 final int [] noOp_commands = { 383 IpServer.CMD_TETHER_UNREQUESTED, 384 IpServer.CMD_IP_FORWARDING_ENABLE_ERROR, 385 IpServer.CMD_IP_FORWARDING_DISABLE_ERROR, 386 IpServer.CMD_START_TETHERING_ERROR, 387 IpServer.CMD_STOP_TETHERING_ERROR, 388 IpServer.CMD_SET_DNS_FORWARDERS_ERROR, 389 IpServer.CMD_TETHER_CONNECTION_CHANGED 390 }; 391 for (int command : noOp_commands) { 392 // None of these commands should trigger us to request action from 393 // the rest of the system. 394 dispatchCommand(command); 395 verifyNoMoreInteractions(mNetd, mCallback); 396 } 397 } 398 399 @Test handlesImmediateInterfaceDown()400 public void handlesImmediateInterfaceDown() throws Exception { 401 initStateMachine(TETHERING_BLUETOOTH); 402 403 dispatchCommand(IpServer.CMD_INTERFACE_DOWN); 404 verify(mCallback).updateInterfaceState( 405 mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR); 406 verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class)); 407 verifyNoMoreInteractions(mNetd, mCallback); 408 } 409 410 @Test canBeTetheredAsBluetooth()411 public void canBeTetheredAsBluetooth() throws Exception { 412 initStateMachine(TETHERING_BLUETOOTH); 413 414 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); 415 InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator); 416 if (isAtLeastT()) { 417 inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true)); 418 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> 419 IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP))); 420 } 421 inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 422 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 423 // One for ipv4 route, one for ipv6 link local route. 424 inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), 425 any(), any()); 426 inOrder.verify(mCallback).updateInterfaceState( 427 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR); 428 inOrder.verify(mCallback).updateLinkProperties( 429 eq(mIpServer), any(LinkProperties.class)); 430 verifyNoMoreInteractions(mNetd, mCallback); 431 } 432 433 @Test canUnrequestTethering()434 public void canUnrequestTethering() throws Exception { 435 initTetheredStateMachine(TETHERING_BLUETOOTH, null); 436 437 dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); 438 InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator); 439 inOrder.verify(mNetd).tetherApplyDnsInterfaces(); 440 inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME); 441 inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 442 // One is ipv4 address clear (set to 0.0.0.0), another is set interface down which only 443 // happen after T. Before T, the interface configuration control in bluetooth side. 444 if (isAtLeastT()) { 445 inOrder.verify(mNetd).interfaceSetCfg( 446 argThat(cfg -> assertContainsFlag(cfg.flags, IF_STATE_DOWN))); 447 } 448 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> cfg.flags.length == 0)); 449 inOrder.verify(mAddressCoordinator).releaseDownstream(any()); 450 inOrder.verify(mCallback).updateInterfaceState( 451 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); 452 inOrder.verify(mCallback).updateLinkProperties( 453 eq(mIpServer), any(LinkProperties.class)); 454 verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator); 455 } 456 457 @Test canBeTetheredAsUsb()458 public void canBeTetheredAsUsb() throws Exception { 459 initStateMachine(TETHERING_USB); 460 461 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); 462 InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator); 463 inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true)); 464 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> 465 IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP))); 466 inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 467 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 468 inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), 469 any(), any()); 470 inOrder.verify(mCallback).updateInterfaceState( 471 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR); 472 inOrder.verify(mCallback).updateLinkProperties( 473 eq(mIpServer), mLinkPropertiesCaptor.capture()); 474 assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); 475 verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator); 476 } 477 478 @Test canBeTetheredAsWifiP2p()479 public void canBeTetheredAsWifiP2p() throws Exception { 480 initStateMachine(TETHERING_WIFI_P2P); 481 482 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY); 483 InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator); 484 inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true)); 485 inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> 486 IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP))); 487 inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 488 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 489 inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), 490 any(), any()); 491 inOrder.verify(mCallback).updateInterfaceState( 492 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); 493 inOrder.verify(mCallback).updateLinkProperties( 494 eq(mIpServer), mLinkPropertiesCaptor.capture()); 495 assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); 496 verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator); 497 } 498 499 @Test handlesFirstUpstreamChange()500 public void handlesFirstUpstreamChange() throws Exception { 501 initTetheredStateMachine(TETHERING_BLUETOOTH, null); 502 503 // Telling the state machine about its upstream interface triggers 504 // a little more configuration. 505 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 506 InOrder inOrder = inOrder(mNetd, mBpfCoordinator); 507 508 // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>. 509 inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX, 510 UPSTREAM_IFACE); 511 inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE); 512 inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE); 513 inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 514 515 verifyNoMoreInteractions(mNetd, mCallback, mBpfCoordinator); 516 } 517 518 @Test handlesChangingUpstream()519 public void handlesChangingUpstream() throws Exception { 520 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); 521 522 dispatchTetherConnectionChanged(UPSTREAM_IFACE2); 523 InOrder inOrder = inOrder(mNetd, mBpfCoordinator); 524 525 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>. 526 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE); 527 inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 528 inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE); 529 530 // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2>. 531 inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2, 532 UPSTREAM_IFACE2); 533 inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2); 534 inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2); 535 inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 536 537 verifyNoMoreInteractions(mNetd, mCallback, mBpfCoordinator); 538 } 539 540 @Test handlesChangingUpstreamNatFailure()541 public void handlesChangingUpstreamNatFailure() throws Exception { 542 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 543 544 doThrow(RemoteException.class).when(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2); 545 546 dispatchTetherConnectionChanged(UPSTREAM_IFACE2); 547 InOrder inOrder = inOrder(mNetd, mBpfCoordinator); 548 549 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>. 550 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE); 551 inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 552 inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE); 553 554 // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on 555 // tetherAddForward. 556 inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2, 557 UPSTREAM_IFACE2); 558 inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2); 559 inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2); 560 561 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback. 562 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2); 563 inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 564 inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2); 565 } 566 567 @Test handlesChangingUpstreamInterfaceForwardingFailure()568 public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception { 569 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 570 571 doThrow(RemoteException.class).when(mNetd).ipfwdAddInterfaceForward( 572 IFACE_NAME, UPSTREAM_IFACE2); 573 574 dispatchTetherConnectionChanged(UPSTREAM_IFACE2); 575 InOrder inOrder = inOrder(mNetd, mBpfCoordinator); 576 577 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>. 578 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE); 579 inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 580 inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE); 581 582 // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on 583 // ipfwdAddInterfaceForward. 584 inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2, 585 UPSTREAM_IFACE2); 586 inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2); 587 inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2); 588 inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 589 590 // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback. 591 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2); 592 inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2); 593 inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2); 594 } 595 596 @Test canUnrequestTetheringWithUpstream()597 public void canUnrequestTetheringWithUpstream() throws Exception { 598 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); 599 600 dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); 601 InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator, mBpfCoordinator); 602 inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE); 603 inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE); 604 inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE); 605 inOrder.verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer); 606 inOrder.verify(mNetd).tetherApplyDnsInterfaces(); 607 inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME); 608 inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 609 inOrder.verify(mNetd, times(isAtLeastT() ? 2 : 1)).interfaceSetCfg( 610 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 611 inOrder.verify(mAddressCoordinator).releaseDownstream(any()); 612 inOrder.verify(mBpfCoordinator).tetherOffloadClientClear(mIpServer); 613 inOrder.verify(mBpfCoordinator).stopMonitoring(mIpServer); 614 inOrder.verify(mCallback).updateInterfaceState( 615 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); 616 inOrder.verify(mCallback).updateLinkProperties( 617 eq(mIpServer), any(LinkProperties.class)); 618 verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator, mBpfCoordinator); 619 } 620 621 @Test interfaceDownLeadsToUnavailable()622 public void interfaceDownLeadsToUnavailable() throws Exception { 623 for (boolean shouldThrow : new boolean[]{true, false}) { 624 initTetheredStateMachine(TETHERING_USB, null); 625 626 if (shouldThrow) { 627 doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME); 628 } 629 dispatchCommand(IpServer.CMD_INTERFACE_DOWN); 630 InOrder usbTeardownOrder = inOrder(mNetd, mCallback); 631 // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down 632 // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address. 633 usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( 634 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 635 usbTeardownOrder.verify(mCallback).updateInterfaceState( 636 mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR); 637 usbTeardownOrder.verify(mCallback).updateLinkProperties( 638 eq(mIpServer), mLinkPropertiesCaptor.capture()); 639 assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); 640 } 641 } 642 643 @Test usbShouldBeTornDownOnTetherError()644 public void usbShouldBeTornDownOnTetherError() throws Exception { 645 initStateMachine(TETHERING_USB); 646 647 doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME); 648 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); 649 InOrder usbTeardownOrder = inOrder(mNetd, mCallback); 650 usbTeardownOrder.verify(mNetd).interfaceSetCfg( 651 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 652 usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME); 653 654 usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( 655 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 656 usbTeardownOrder.verify(mCallback).updateInterfaceState( 657 mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR); 658 usbTeardownOrder.verify(mCallback).updateLinkProperties( 659 eq(mIpServer), mLinkPropertiesCaptor.capture()); 660 assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); 661 } 662 663 @Test shouldTearDownUsbOnUpstreamError()664 public void shouldTearDownUsbOnUpstreamError() throws Exception { 665 initTetheredStateMachine(TETHERING_USB, null); 666 667 doThrow(RemoteException.class).when(mNetd).tetherAddForward(anyString(), anyString()); 668 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 669 InOrder usbTeardownOrder = inOrder(mNetd, mCallback); 670 usbTeardownOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE); 671 672 usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg( 673 argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); 674 usbTeardownOrder.verify(mCallback).updateInterfaceState( 675 mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_FORWARDING_ERROR); 676 usbTeardownOrder.verify(mCallback).updateLinkProperties( 677 eq(mIpServer), mLinkPropertiesCaptor.capture()); 678 assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue()); 679 } 680 681 @Test ignoresDuplicateUpstreamNotifications()682 public void ignoresDuplicateUpstreamNotifications() throws Exception { 683 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 684 685 verifyNoMoreInteractions(mNetd, mCallback); 686 687 for (int i = 0; i < 5; i++) { 688 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 689 verifyNoMoreInteractions(mNetd, mCallback); 690 } 691 } 692 693 @Test startsDhcpServer()694 public void startsDhcpServer() throws Exception { 695 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 696 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 697 698 assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress)); 699 } 700 701 @Test startsDhcpServerOnBluetooth()702 public void startsDhcpServerOnBluetooth() throws Exception { 703 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); 704 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 705 706 if (isAtLeastT()) { 707 assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress)); 708 } else { 709 assertDhcpStarted(mBluetoothPrefix); 710 } 711 } 712 713 @Test startsDhcpServerOnWifiP2p()714 public void startsDhcpServerOnWifiP2p() throws Exception { 715 initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE); 716 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 717 718 assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress)); 719 } 720 721 @Test startsDhcpServerOnNcm()722 public void startsDhcpServerOnNcm() throws Exception { 723 initStateMachine(TETHERING_NCM); 724 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY); 725 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 726 727 assertDhcpStarted(new IpPrefix("192.168.42.0/24")); 728 } 729 730 @Test testOnNewPrefixRequest()731 public void testOnNewPrefixRequest() throws Exception { 732 initStateMachine(TETHERING_NCM); 733 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY); 734 735 final IDhcpEventCallbacks eventCallbacks; 736 final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor = 737 ArgumentCaptor.forClass(IDhcpEventCallbacks.class); 738 verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks( 739 any(), dhcpEventCbsCaptor.capture()); 740 eventCallbacks = dhcpEventCbsCaptor.getValue(); 741 assertDhcpStarted(new IpPrefix("192.168.42.0/24")); 742 743 final ArgumentCaptor<LinkProperties> lpCaptor = 744 ArgumentCaptor.forClass(LinkProperties.class); 745 InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator); 746 inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true)); 747 inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME); 748 // One for ipv4 route, one for ipv6 link local route. 749 inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), 750 any(), any()); 751 inOrder.verify(mCallback).updateInterfaceState( 752 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); 753 inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture()); 754 verifyNoMoreInteractions(mCallback, mAddressCoordinator); 755 756 // Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals 757 // onNewPrefixRequest callback. 758 final LinkAddress newAddress = new LinkAddress("192.168.100.125/24"); 759 when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn( 760 newAddress); 761 eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24")); 762 mLooper.dispatchAll(); 763 764 inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(false)); 765 inOrder.verify(mNetd).tetherApplyDnsInterfaces(); 766 inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture()); 767 verifyNoMoreInteractions(mCallback); 768 769 final LinkProperties linkProperties = lpCaptor.getValue(); 770 final List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses(); 771 assertEquals(1, linkProperties.getLinkAddresses().size()); 772 assertEquals(1, linkProperties.getRoutes().size()); 773 final IpPrefix prefix = new IpPrefix(linkAddresses.get(0).getAddress(), 774 linkAddresses.get(0).getPrefixLength()); 775 assertNotEquals(prefix, new IpPrefix("192.168.42.0/24")); 776 777 verify(mDhcpServer).updateParams(mDhcpParamsCaptor.capture(), any()); 778 assertDhcpServingParams(mDhcpParamsCaptor.getValue(), prefix); 779 } 780 781 @Test doesNotStartDhcpServerIfDisabled()782 public void doesNotStartDhcpServerIfDisabled() throws Exception { 783 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */, 784 DEFAULT_USING_BPF_OFFLOAD); 785 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 786 787 verify(mDependencies, never()).makeDhcpServer(any(), any(), any()); 788 } 789 addr(String addr)790 private InetAddress addr(String addr) throws Exception { 791 return InetAddresses.parseNumericAddress(addr); 792 } 793 recvNewNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac)794 private void recvNewNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) { 795 mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_NEWNEIGH, ifindex, addr, 796 nudState, mac)); 797 mLooper.dispatchAll(); 798 } 799 recvDelNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac)800 private void recvDelNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) { 801 mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_DELNEIGH, ifindex, addr, 802 nudState, mac)); 803 mLooper.dispatchAll(); 804 } 805 806 /** 807 * Custom ArgumentMatcher for TetherOffloadRuleParcel. This is needed because generated stable 808 * AIDL classes don't have equals(), so we cannot just use eq(). A custom assert, such as: 809 * 810 * private void checkFooCalled(StableParcelable p, ...) { 811 * ArgumentCaptor<FooParam> captor = ArgumentCaptor.forClass(FooParam.class); 812 * verify(mMock).foo(captor.capture()); 813 * Foo foo = captor.getValue(); 814 * assertFooMatchesExpectations(foo); 815 * } 816 * 817 * almost works, but not quite. This is because if the code under test calls foo() twice, the 818 * first call to checkFooCalled() matches both the calls, putting both calls into the captor, 819 * and then fails with TooManyActualInvocations. It also makes it harder to use other mockito 820 * features such as never(), inOrder(), etc. 821 * 822 * This approach isn't great because if the match fails, the error message is unhelpful 823 * (actual: "android.net.TetherOffloadRuleParcel@8c827b0" or some such), but at least it does 824 * work. 825 * 826 * TODO: consider making the error message more readable by adding a method that catching the 827 * AssertionFailedError and throwing a new assertion with more details. See 828 * NetworkMonitorTest#verifyNetworkTested. 829 * 830 * See ConnectivityServiceTest#assertRoutesAdded for an alternative approach which solves the 831 * TooManyActualInvocations problem described above by forcing the caller of the custom assert 832 * method to specify all expected invocations in one call. This is useful when the stable 833 * parcelable class being asserted on has a corresponding Java object (eg., RouteInfo and 834 * RouteInfoParcelable), and the caller can just pass in a list of them. It not useful here 835 * because there is no such object. 836 */ 837 private static class TetherOffloadRuleParcelMatcher implements 838 ArgumentMatcher<TetherOffloadRuleParcel> { 839 public final int upstreamIfindex; 840 public final InetAddress dst; 841 public final MacAddress dstMac; 842 TetherOffloadRuleParcelMatcher(int upstreamIfindex, InetAddress dst, MacAddress dstMac)843 TetherOffloadRuleParcelMatcher(int upstreamIfindex, InetAddress dst, MacAddress dstMac) { 844 this.upstreamIfindex = upstreamIfindex; 845 this.dst = dst; 846 this.dstMac = dstMac; 847 } 848 matches(TetherOffloadRuleParcel parcel)849 public boolean matches(TetherOffloadRuleParcel parcel) { 850 return upstreamIfindex == parcel.inputInterfaceIndex 851 && (TEST_IFACE_PARAMS.index == parcel.outputInterfaceIndex) 852 && Arrays.equals(dst.getAddress(), parcel.destination) 853 && (128 == parcel.prefixLength) 854 && Arrays.equals(TEST_IFACE_PARAMS.macAddr.toByteArray(), parcel.srcL2Address) 855 && Arrays.equals(dstMac.toByteArray(), parcel.dstL2Address); 856 } 857 toString()858 public String toString() { 859 return String.format("TetherOffloadRuleParcelMatcher(%d, %s, %s", 860 upstreamIfindex, dst.getHostAddress(), dstMac); 861 } 862 } 863 864 @NonNull matches( int upstreamIfindex, InetAddress dst, MacAddress dstMac)865 private static TetherOffloadRuleParcel matches( 866 int upstreamIfindex, InetAddress dst, MacAddress dstMac) { 867 return argThat(new TetherOffloadRuleParcelMatcher(upstreamIfindex, dst, dstMac)); 868 } 869 870 @NonNull makeForwardingRule( int upstreamIfindex, @NonNull InetAddress dst, @NonNull MacAddress dstMac)871 private static Ipv6ForwardingRule makeForwardingRule( 872 int upstreamIfindex, @NonNull InetAddress dst, @NonNull MacAddress dstMac) { 873 return new Ipv6ForwardingRule(upstreamIfindex, TEST_IFACE_PARAMS.index, 874 (Inet6Address) dst, TEST_IFACE_PARAMS.macAddr, dstMac); 875 } 876 877 @NonNull makeDownstream6Key(int upstreamIfindex, @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst)878 private static TetherDownstream6Key makeDownstream6Key(int upstreamIfindex, 879 @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst) { 880 return new TetherDownstream6Key(upstreamIfindex, upstreamMac, dst.getAddress()); 881 } 882 883 @NonNull makeDownstream6Value(@onNull final MacAddress dstMac)884 private static Tether6Value makeDownstream6Value(@NonNull final MacAddress dstMac) { 885 return new Tether6Value(TEST_IFACE_PARAMS.index, dstMac, 886 TEST_IFACE_PARAMS.macAddr, ETH_P_IPV6, NetworkStackConstants.ETHER_MTU); 887 } 888 verifyWithOrder(@ullable InOrder inOrder, @NonNull T t)889 private <T> T verifyWithOrder(@Nullable InOrder inOrder, @NonNull T t) { 890 if (inOrder != null) { 891 return inOrder.verify(t); 892 } else { 893 return verify(t); 894 } 895 } 896 verifyTetherOffloadRuleAdd(@ullable InOrder inOrder, int upstreamIfindex, @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, @NonNull final MacAddress dstMac)897 private void verifyTetherOffloadRuleAdd(@Nullable InOrder inOrder, int upstreamIfindex, 898 @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, 899 @NonNull final MacAddress dstMac) throws Exception { 900 if (mBpfDeps.isAtLeastS()) { 901 verifyWithOrder(inOrder, mBpfDownstream6Map).updateEntry( 902 makeDownstream6Key(upstreamIfindex, upstreamMac, dst), 903 makeDownstream6Value(dstMac)); 904 } else { 905 verifyWithOrder(inOrder, mNetd).tetherOffloadRuleAdd(matches(upstreamIfindex, dst, 906 dstMac)); 907 } 908 } 909 verifyNeverTetherOffloadRuleAdd(int upstreamIfindex, @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, @NonNull final MacAddress dstMac)910 private void verifyNeverTetherOffloadRuleAdd(int upstreamIfindex, 911 @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, 912 @NonNull final MacAddress dstMac) throws Exception { 913 if (mBpfDeps.isAtLeastS()) { 914 verify(mBpfDownstream6Map, never()).updateEntry( 915 makeDownstream6Key(upstreamIfindex, upstreamMac, dst), 916 makeDownstream6Value(dstMac)); 917 } else { 918 verify(mNetd, never()).tetherOffloadRuleAdd(matches(upstreamIfindex, dst, dstMac)); 919 } 920 } 921 verifyNeverTetherOffloadRuleAdd()922 private void verifyNeverTetherOffloadRuleAdd() throws Exception { 923 if (mBpfDeps.isAtLeastS()) { 924 verify(mBpfDownstream6Map, never()).updateEntry(any(), any()); 925 } else { 926 verify(mNetd, never()).tetherOffloadRuleAdd(any()); 927 } 928 } 929 verifyTetherOffloadRuleRemove(@ullable InOrder inOrder, int upstreamIfindex, @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, @NonNull final MacAddress dstMac)930 private void verifyTetherOffloadRuleRemove(@Nullable InOrder inOrder, int upstreamIfindex, 931 @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, 932 @NonNull final MacAddress dstMac) throws Exception { 933 if (mBpfDeps.isAtLeastS()) { 934 verifyWithOrder(inOrder, mBpfDownstream6Map).deleteEntry(makeDownstream6Key( 935 upstreamIfindex, upstreamMac, dst)); 936 } else { 937 // |dstMac| is not required for deleting rules. Used bacause tetherOffloadRuleRemove 938 // uses a whole rule to be a argument. 939 // See system/netd/server/TetherController.cpp/TetherController#removeOffloadRule. 940 verifyWithOrder(inOrder, mNetd).tetherOffloadRuleRemove(matches(upstreamIfindex, dst, 941 dstMac)); 942 } 943 } 944 verifyNeverTetherOffloadRuleRemove()945 private void verifyNeverTetherOffloadRuleRemove() throws Exception { 946 if (mBpfDeps.isAtLeastS()) { 947 verify(mBpfDownstream6Map, never()).deleteEntry(any()); 948 } else { 949 verify(mNetd, never()).tetherOffloadRuleRemove(any()); 950 } 951 } 952 verifyStartUpstreamIpv6Forwarding(@ullable InOrder inOrder, int upstreamIfindex)953 private void verifyStartUpstreamIpv6Forwarding(@Nullable InOrder inOrder, int upstreamIfindex) 954 throws Exception { 955 if (!mBpfDeps.isAtLeastS()) return; 956 final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index, 957 TEST_IFACE_PARAMS.macAddr); 958 final Tether6Value value = new Tether6Value(upstreamIfindex, 959 MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS, 960 ETH_P_IPV6, NetworkStackConstants.ETHER_MTU); 961 verifyWithOrder(inOrder, mBpfUpstream6Map).insertEntry(key, value); 962 } 963 verifyStopUpstreamIpv6Forwarding(@ullable InOrder inOrder)964 private void verifyStopUpstreamIpv6Forwarding(@Nullable InOrder inOrder) 965 throws Exception { 966 if (!mBpfDeps.isAtLeastS()) return; 967 final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index, 968 TEST_IFACE_PARAMS.macAddr); 969 verifyWithOrder(inOrder, mBpfUpstream6Map).deleteEntry(key); 970 } 971 verifyNoUpstreamIpv6ForwardingChange(@ullable InOrder inOrder)972 private void verifyNoUpstreamIpv6ForwardingChange(@Nullable InOrder inOrder) throws Exception { 973 if (!mBpfDeps.isAtLeastS()) return; 974 if (inOrder != null) { 975 inOrder.verify(mBpfUpstream6Map, never()).deleteEntry(any()); 976 inOrder.verify(mBpfUpstream6Map, never()).insertEntry(any(), any()); 977 inOrder.verify(mBpfUpstream6Map, never()).updateEntry(any(), any()); 978 } else { 979 verify(mBpfUpstream6Map, never()).deleteEntry(any()); 980 verify(mBpfUpstream6Map, never()).insertEntry(any(), any()); 981 verify(mBpfUpstream6Map, never()).updateEntry(any(), any()); 982 } 983 } 984 985 @NonNull buildEmptyTetherStatsParcel(int ifIndex)986 private static TetherStatsParcel buildEmptyTetherStatsParcel(int ifIndex) { 987 TetherStatsParcel parcel = new TetherStatsParcel(); 988 parcel.ifIndex = ifIndex; 989 return parcel; 990 } 991 resetNetdBpfMapAndCoordinator()992 private void resetNetdBpfMapAndCoordinator() throws Exception { 993 reset(mNetd, mBpfDownstream6Map, mBpfUpstream6Map, mBpfCoordinator); 994 // When the last rule is removed, tetherOffloadGetAndClearStats will log a WTF (and 995 // potentially crash the test) if the stats map is empty. 996 when(mNetd.tetherOffloadGetStats()).thenReturn(new TetherStatsParcel[0]); 997 when(mNetd.tetherOffloadGetAndClearStats(UPSTREAM_IFINDEX)) 998 .thenReturn(buildEmptyTetherStatsParcel(UPSTREAM_IFINDEX)); 999 when(mNetd.tetherOffloadGetAndClearStats(UPSTREAM_IFINDEX2)) 1000 .thenReturn(buildEmptyTetherStatsParcel(UPSTREAM_IFINDEX2)); 1001 // When the last rule is removed, tetherOffloadGetAndClearStats will log a WTF (and 1002 // potentially crash the test) if the stats map is empty. 1003 final TetherStatsValue allZeros = new TetherStatsValue(0, 0, 0, 0, 0, 0); 1004 when(mBpfStatsMap.getValue(new TetherStatsKey(UPSTREAM_IFINDEX))).thenReturn(allZeros); 1005 when(mBpfStatsMap.getValue(new TetherStatsKey(UPSTREAM_IFINDEX2))).thenReturn(allZeros); 1006 } 1007 1008 @Test addRemoveipv6ForwardingRules()1009 public void addRemoveipv6ForwardingRules() throws Exception { 1010 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, 1011 DEFAULT_USING_BPF_OFFLOAD); 1012 1013 final int myIfindex = TEST_IFACE_PARAMS.index; 1014 final int notMyIfindex = myIfindex - 1; 1015 1016 final InetAddress neighA = InetAddresses.parseNumericAddress("2001:db8::1"); 1017 final InetAddress neighB = InetAddresses.parseNumericAddress("2001:db8::2"); 1018 final InetAddress neighLL = InetAddresses.parseNumericAddress("fe80::1"); 1019 final InetAddress neighMC = InetAddresses.parseNumericAddress("ff02::1234"); 1020 final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00"); 1021 final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a"); 1022 final MacAddress macB = MacAddress.fromString("11:22:33:00:00:0b"); 1023 1024 resetNetdBpfMapAndCoordinator(); 1025 verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map); 1026 1027 // TODO: Perhaps verify the interaction of tetherOffloadSetInterfaceQuota and 1028 // tetherOffloadGetAndClearStats in netd while the rules are changed. 1029 1030 // Events on other interfaces are ignored. 1031 recvNewNeigh(notMyIfindex, neighA, NUD_REACHABLE, macA); 1032 verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map); 1033 1034 // Events on this interface are received and sent to netd. 1035 recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); 1036 verify(mBpfCoordinator).tetherOffloadRuleAdd( 1037 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA)); 1038 verifyTetherOffloadRuleAdd(null, 1039 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA); 1040 verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX); 1041 resetNetdBpfMapAndCoordinator(); 1042 1043 recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); 1044 verify(mBpfCoordinator).tetherOffloadRuleAdd( 1045 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB)); 1046 verifyTetherOffloadRuleAdd(null, 1047 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB); 1048 verifyNoUpstreamIpv6ForwardingChange(null); 1049 resetNetdBpfMapAndCoordinator(); 1050 1051 // Link-local and multicast neighbors are ignored. 1052 recvNewNeigh(myIfindex, neighLL, NUD_REACHABLE, macA); 1053 verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map); 1054 recvNewNeigh(myIfindex, neighMC, NUD_REACHABLE, macA); 1055 verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map); 1056 1057 // A neighbor that is no longer valid causes the rule to be removed. 1058 // NUD_FAILED events do not have a MAC address. 1059 recvNewNeigh(myIfindex, neighA, NUD_FAILED, null); 1060 verify(mBpfCoordinator).tetherOffloadRuleRemove( 1061 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macNull)); 1062 verifyTetherOffloadRuleRemove(null, 1063 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macNull); 1064 verifyNoUpstreamIpv6ForwardingChange(null); 1065 resetNetdBpfMapAndCoordinator(); 1066 1067 // A neighbor that is deleted causes the rule to be removed. 1068 recvDelNeigh(myIfindex, neighB, NUD_STALE, macB); 1069 verify(mBpfCoordinator).tetherOffloadRuleRemove( 1070 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macNull)); 1071 verifyTetherOffloadRuleRemove(null, 1072 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macNull); 1073 verifyStopUpstreamIpv6Forwarding(null); 1074 resetNetdBpfMapAndCoordinator(); 1075 1076 // Upstream changes result in updating the rules. 1077 recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); 1078 verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX); 1079 recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); 1080 resetNetdBpfMapAndCoordinator(); 1081 1082 InOrder inOrder = inOrder(mNetd, mBpfDownstream6Map, mBpfUpstream6Map); 1083 LinkProperties lp = new LinkProperties(); 1084 lp.setInterfaceName(UPSTREAM_IFACE2); 1085 dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1); 1086 verify(mBpfCoordinator).tetherOffloadRuleUpdate(mIpServer, UPSTREAM_IFINDEX2); 1087 verifyTetherOffloadRuleRemove(inOrder, 1088 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA); 1089 verifyTetherOffloadRuleRemove(inOrder, 1090 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB); 1091 verifyStopUpstreamIpv6Forwarding(inOrder); 1092 verifyTetherOffloadRuleAdd(inOrder, 1093 UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighA, macA); 1094 verifyStartUpstreamIpv6Forwarding(inOrder, UPSTREAM_IFINDEX2); 1095 verifyTetherOffloadRuleAdd(inOrder, 1096 UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighB, macB); 1097 verifyNoUpstreamIpv6ForwardingChange(inOrder); 1098 resetNetdBpfMapAndCoordinator(); 1099 1100 // When the upstream is lost, rules are removed. 1101 dispatchTetherConnectionChanged(null, null, 0); 1102 // Clear function is called two times by: 1103 // - processMessage CMD_TETHER_CONNECTION_CHANGED for the upstream is lost. 1104 // - processMessage CMD_IPV6_TETHER_UPDATE for the IPv6 upstream is lost. 1105 // See dispatchTetherConnectionChanged. 1106 verify(mBpfCoordinator, times(2)).tetherOffloadRuleClear(mIpServer); 1107 verifyTetherOffloadRuleRemove(null, 1108 UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighA, macA); 1109 verifyTetherOffloadRuleRemove(null, 1110 UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighB, macB); 1111 verifyStopUpstreamIpv6Forwarding(inOrder); 1112 resetNetdBpfMapAndCoordinator(); 1113 1114 // If the upstream is IPv4-only, no rules are added. 1115 dispatchTetherConnectionChanged(UPSTREAM_IFACE); 1116 resetNetdBpfMapAndCoordinator(); 1117 recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); 1118 // Clear function is called by #updateIpv6ForwardingRules for the IPv6 upstream is lost. 1119 verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer); 1120 verifyNoUpstreamIpv6ForwardingChange(null); 1121 verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map); 1122 1123 // Rules can be added again once upstream IPv6 connectivity is available. 1124 lp.setInterfaceName(UPSTREAM_IFACE); 1125 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); 1126 recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); 1127 verify(mBpfCoordinator).tetherOffloadRuleAdd( 1128 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB)); 1129 verifyTetherOffloadRuleAdd(null, 1130 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB); 1131 verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX); 1132 verify(mBpfCoordinator, never()).tetherOffloadRuleAdd( 1133 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA)); 1134 verifyNeverTetherOffloadRuleAdd( 1135 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA); 1136 1137 // If upstream IPv6 connectivity is lost, rules are removed. 1138 resetNetdBpfMapAndCoordinator(); 1139 dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); 1140 verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer); 1141 verifyTetherOffloadRuleRemove(null, 1142 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB); 1143 verifyStopUpstreamIpv6Forwarding(null); 1144 1145 // When the interface goes down, rules are removed. 1146 lp.setInterfaceName(UPSTREAM_IFACE); 1147 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); 1148 recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); 1149 recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); 1150 verify(mBpfCoordinator).tetherOffloadRuleAdd( 1151 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA)); 1152 verifyTetherOffloadRuleAdd(null, 1153 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA); 1154 verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX); 1155 verify(mBpfCoordinator).tetherOffloadRuleAdd( 1156 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB)); 1157 verifyTetherOffloadRuleAdd(null, 1158 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB); 1159 resetNetdBpfMapAndCoordinator(); 1160 1161 mIpServer.stop(); 1162 mLooper.dispatchAll(); 1163 verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer); 1164 verifyTetherOffloadRuleRemove(null, 1165 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA); 1166 verifyTetherOffloadRuleRemove(null, 1167 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB); 1168 verifyStopUpstreamIpv6Forwarding(null); 1169 verify(mIpNeighborMonitor).stop(); 1170 resetNetdBpfMapAndCoordinator(); 1171 } 1172 1173 @Test enableDisableUsingBpfOffload()1174 public void enableDisableUsingBpfOffload() throws Exception { 1175 final int myIfindex = TEST_IFACE_PARAMS.index; 1176 final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1"); 1177 final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a"); 1178 final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00"); 1179 1180 // Expect that rules can be only added/removed when the BPF offload config is enabled. 1181 // Note that the BPF offload disabled case is not a realistic test case. Because IP 1182 // neighbor monitor doesn't start if BPF offload is disabled, there should have no 1183 // neighbor event listening. This is used for testing the protection check just in case. 1184 // TODO: Perhaps remove the BPF offload disabled case test once this check isn't needed 1185 // anymore. 1186 1187 // [1] Enable BPF offload. 1188 // A neighbor that is added or deleted causes the rule to be added or removed. 1189 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, 1190 true /* usingBpfOffload */); 1191 resetNetdBpfMapAndCoordinator(); 1192 1193 recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA); 1194 verify(mBpfCoordinator).tetherOffloadRuleAdd( 1195 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macA)); 1196 verifyTetherOffloadRuleAdd(null, 1197 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neigh, macA); 1198 verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX); 1199 resetNetdBpfMapAndCoordinator(); 1200 1201 recvDelNeigh(myIfindex, neigh, NUD_STALE, macA); 1202 verify(mBpfCoordinator).tetherOffloadRuleRemove( 1203 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macNull)); 1204 verifyTetherOffloadRuleRemove(null, 1205 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neigh, macNull); 1206 verifyStopUpstreamIpv6Forwarding(null); 1207 resetNetdBpfMapAndCoordinator(); 1208 1209 // [2] Disable BPF offload. 1210 // A neighbor that is added or deleted doesn’t cause the rule to be added or removed. 1211 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, 1212 false /* usingBpfOffload */); 1213 resetNetdBpfMapAndCoordinator(); 1214 1215 recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA); 1216 verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(any(), any()); 1217 verifyNeverTetherOffloadRuleAdd(); 1218 verifyNoUpstreamIpv6ForwardingChange(null); 1219 resetNetdBpfMapAndCoordinator(); 1220 1221 recvDelNeigh(myIfindex, neigh, NUD_STALE, macA); 1222 verify(mBpfCoordinator, never()).tetherOffloadRuleRemove(any(), any()); 1223 verifyNeverTetherOffloadRuleRemove(); 1224 verifyNoUpstreamIpv6ForwardingChange(null); 1225 resetNetdBpfMapAndCoordinator(); 1226 } 1227 1228 @Test doesNotStartIpNeighborMonitorIfBpfOffloadDisabled()1229 public void doesNotStartIpNeighborMonitorIfBpfOffloadDisabled() throws Exception { 1230 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */, 1231 false /* usingBpfOffload */); 1232 1233 // IP neighbor monitor doesn't start if BPF offload is disabled. 1234 verify(mIpNeighborMonitor, never()).start(); 1235 } 1236 buildIpv6OnlyLinkProperties(final String iface)1237 private LinkProperties buildIpv6OnlyLinkProperties(final String iface) { 1238 final LinkProperties linkProp = new LinkProperties(); 1239 linkProp.setInterfaceName(iface); 1240 linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64")); 1241 linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST)); 1242 final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888"); 1243 linkProp.addDnsServer(dns); 1244 1245 return linkProp; 1246 } 1247 1248 @Test testAdjustTtlValue()1249 public void testAdjustTtlValue() throws Exception { 1250 final ArgumentCaptor<RaParams> raParamsCaptor = 1251 ArgumentCaptor.forClass(RaParams.class); 1252 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 1253 verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); 1254 final RaParams noV6Params = raParamsCaptor.getValue(); 1255 assertEquals(65, noV6Params.hopLimit); 1256 reset(mRaDaemon); 1257 1258 when(mNetd.getProcSysNet( 1259 INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64"); 1260 final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE); 1261 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1); 1262 verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); 1263 final RaParams nonCellularParams = raParamsCaptor.getValue(); 1264 assertEquals(65, nonCellularParams.hopLimit); 1265 reset(mRaDaemon); 1266 1267 dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); 1268 verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); 1269 final RaParams noUpstream = raParamsCaptor.getValue(); 1270 assertEquals(65, nonCellularParams.hopLimit); 1271 reset(mRaDaemon); 1272 1273 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); 1274 verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); 1275 final RaParams cellularParams = raParamsCaptor.getValue(); 1276 assertEquals(63, cellularParams.hopLimit); 1277 reset(mRaDaemon); 1278 } 1279 1280 @Test testStopObsoleteDhcpServer()1281 public void testStopObsoleteDhcpServer() throws Exception { 1282 final ArgumentCaptor<DhcpServerCallbacks> cbCaptor = 1283 ArgumentCaptor.forClass(DhcpServerCallbacks.class); 1284 doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), 1285 cbCaptor.capture()); 1286 initStateMachine(TETHERING_WIFI); 1287 dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); 1288 verify(mDhcpServer, never()).startWithCallbacks(any(), any()); 1289 1290 // No stop dhcp server because dhcp server is not created yet. 1291 dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); 1292 verify(mDhcpServer, never()).stop(any()); 1293 1294 // Stop obsolete dhcp server. 1295 try { 1296 final DhcpServerCallbacks cb = cbCaptor.getValue(); 1297 cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer); 1298 mLooper.dispatchAll(); 1299 } catch (RemoteException e) { 1300 fail(e.getMessage()); 1301 } 1302 verify(mDhcpServer).stop(any()); 1303 } 1304 assertDhcpServingParams(final DhcpServingParamsParcel params, final IpPrefix prefix)1305 private void assertDhcpServingParams(final DhcpServingParamsParcel params, 1306 final IpPrefix prefix) { 1307 // Last address byte is random 1308 assertTrue(prefix.contains(intToInet4AddressHTH(params.serverAddr))); 1309 assertEquals(prefix.getPrefixLength(), params.serverAddrPrefixLength); 1310 assertEquals(1, params.defaultRouters.length); 1311 assertEquals(params.serverAddr, params.defaultRouters[0]); 1312 assertEquals(1, params.dnsServers.length); 1313 assertEquals(params.serverAddr, params.dnsServers[0]); 1314 assertEquals(DHCP_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs); 1315 if (mIpServer.interfaceType() == TETHERING_NCM) { 1316 assertTrue(params.changePrefixOnDecline); 1317 } 1318 1319 if (mIpServer.interfaceType() == TETHERING_WIFI_P2P) { 1320 assertEquals(P2P_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength); 1321 } else { 1322 assertEquals(DEFAULT_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength); 1323 } 1324 } 1325 assertDhcpStarted(IpPrefix expectedPrefix)1326 private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception { 1327 verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any()); 1328 verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks( 1329 any(), any()); 1330 assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix); 1331 } 1332 1333 /** 1334 * Send a command to the state machine under test, and run the event loop to idle. 1335 * 1336 * @param command One of the IpServer.CMD_* constants. 1337 * @param arg1 An additional argument to pass. 1338 */ dispatchCommand(int command, int arg1)1339 private void dispatchCommand(int command, int arg1) { 1340 mIpServer.sendMessage(command, arg1); 1341 mLooper.dispatchAll(); 1342 } 1343 1344 /** 1345 * Send a command to the state machine under test, and run the event loop to idle. 1346 * 1347 * @param command One of the IpServer.CMD_* constants. 1348 */ dispatchCommand(int command)1349 private void dispatchCommand(int command) { 1350 mIpServer.sendMessage(command); 1351 mLooper.dispatchAll(); 1352 } 1353 1354 /** 1355 * Special override to tell the state machine that the upstream interface has changed. 1356 * 1357 * @see #dispatchCommand(int) 1358 * @param upstreamIface String name of upstream interface (or null) 1359 * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream. 1360 */ dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, int ttlAdjustment)1361 private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, 1362 int ttlAdjustment) { 1363 dispatchTetherConnectionChanged(upstreamIface); 1364 mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp); 1365 mLooper.dispatchAll(); 1366 } 1367 dispatchTetherConnectionChanged(String upstreamIface)1368 private void dispatchTetherConnectionChanged(String upstreamIface) { 1369 final InterfaceSet ifs = (upstreamIface != null) ? new InterfaceSet(upstreamIface) : null; 1370 mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifs); 1371 mLooper.dispatchAll(); 1372 } 1373 assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp)1374 private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) { 1375 // Find the first IPv4 LinkAddress. 1376 LinkAddress addr4 = null; 1377 for (LinkAddress addr : lp.getLinkAddresses()) { 1378 if (!(addr.getAddress() instanceof Inet4Address)) continue; 1379 addr4 = addr; 1380 break; 1381 } 1382 assertNotNull("missing IPv4 address", addr4); 1383 1384 final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength()); 1385 // Assert the presence of the associated directly connected route. 1386 final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(), 1387 RouteInfo.RTN_UNICAST); 1388 assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'", 1389 lp.getRoutes().contains(directlyConnected)); 1390 } 1391 assertNoAddressesNorRoutes(LinkProperties lp)1392 private void assertNoAddressesNorRoutes(LinkProperties lp) { 1393 assertTrue(lp.getLinkAddresses().isEmpty()); 1394 assertTrue(lp.getRoutes().isEmpty()); 1395 // We also check that interface name is non-empty, because we should 1396 // never see an empty interface name in any LinkProperties update. 1397 assertFalse(TextUtils.isEmpty(lp.getInterfaceName())); 1398 } 1399 assertContainsFlag(String[] flags, String match)1400 private boolean assertContainsFlag(String[] flags, String match) { 1401 for (String flag : flags) { 1402 if (flag.equals(match)) return true; 1403 } 1404 return false; 1405 } 1406 assertNotContainsFlag(String[] flags, String match)1407 private boolean assertNotContainsFlag(String[] flags, String match) { 1408 for (String flag : flags) { 1409 if (flag.equals(match)) { 1410 fail("Unexpected flag: " + match); 1411 return false; 1412 } 1413 } 1414 return true; 1415 } 1416 1417 @Test @IgnoreUpTo(Build.VERSION_CODES.R) dadProxyUpdates()1418 public void dadProxyUpdates() throws Exception { 1419 InOrder inOrder = inOrder(mDadProxy); 1420 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 1421 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1422 1423 // Add an upstream without IPv6. 1424 dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); 1425 inOrder.verify(mDadProxy).setUpstreamIface(null); 1426 1427 // Add IPv6 to the upstream. 1428 LinkProperties lp = new LinkProperties(); 1429 lp.setInterfaceName(UPSTREAM_IFACE); 1430 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); 1431 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1432 1433 // Change upstream. 1434 // New linkproperties is needed, otherwise changing the iface has no impact. 1435 LinkProperties lp2 = new LinkProperties(); 1436 lp2.setInterfaceName(UPSTREAM_IFACE2); 1437 dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, 0); 1438 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS2); 1439 1440 // Lose IPv6 on the upstream... 1441 dispatchTetherConnectionChanged(UPSTREAM_IFACE2, null, 0); 1442 inOrder.verify(mDadProxy).setUpstreamIface(null); 1443 1444 // ... and regain it on a different upstream. 1445 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); 1446 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1447 1448 // Lose upstream. 1449 dispatchTetherConnectionChanged(null, null, 0); 1450 inOrder.verify(mDadProxy).setUpstreamIface(null); 1451 1452 // Regain upstream. 1453 dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0); 1454 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1455 1456 // Stop tethering. 1457 mIpServer.stop(); 1458 mLooper.dispatchAll(); 1459 } 1460 checkDadProxyEnabled(boolean expectEnabled)1461 private void checkDadProxyEnabled(boolean expectEnabled) throws Exception { 1462 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); 1463 InOrder inOrder = inOrder(mDadProxy); 1464 // Add IPv6 to the upstream. 1465 LinkProperties lp = new LinkProperties(); 1466 lp.setInterfaceName(UPSTREAM_IFACE); 1467 if (expectEnabled) { 1468 inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS); 1469 } else { 1470 inOrder.verifyNoMoreInteractions(); 1471 } 1472 // Stop tethering. 1473 mIpServer.stop(); 1474 mLooper.dispatchAll(); 1475 if (expectEnabled) { 1476 inOrder.verify(mDadProxy).stop(); 1477 } 1478 else { 1479 verify(mDependencies, never()).getDadProxy(any(), any()); 1480 } 1481 } 1482 @Test @IgnoreAfter(Build.VERSION_CODES.R) testDadProxyUpdates_DisabledUpToR()1483 public void testDadProxyUpdates_DisabledUpToR() throws Exception { 1484 checkDadProxyEnabled(false); 1485 } 1486 @Test @IgnoreUpTo(Build.VERSION_CODES.R) testDadProxyUpdates_EnabledAfterR()1487 public void testDadProxyUpdates_EnabledAfterR() throws Exception { 1488 checkDadProxyEnabled(true); 1489 } 1490 1491 @Test testSkipVirtualNetworkInBpf()1492 public void testSkipVirtualNetworkInBpf() throws Exception { 1493 initTetheredStateMachine(TETHERING_BLUETOOTH, null); 1494 final LinkProperties v6Only = new LinkProperties(); 1495 v6Only.setInterfaceName(IPSEC_IFACE); 1496 dispatchTetherConnectionChanged(IPSEC_IFACE, v6Only, 0); 1497 1498 verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, IPSEC_IFACE); 1499 verify(mNetd).tetherAddForward(IFACE_NAME, IPSEC_IFACE); 1500 verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, IPSEC_IFACE); 1501 1502 final int myIfindex = TEST_IFACE_PARAMS.index; 1503 final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1"); 1504 final MacAddress mac = MacAddress.fromString("00:00:00:00:00:0a"); 1505 recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, mac); 1506 verify(mBpfCoordinator, never()).tetherOffloadRuleAdd( 1507 mIpServer, makeForwardingRule(IPSEC_IFINDEX, neigh, mac)); 1508 } 1509 } 1510