1 /* 2 * Copyright (C) 2022 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; 18 19 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; 20 import static android.Manifest.permission.MANAGE_TEST_NETWORKS; 21 import static android.Manifest.permission.NETWORK_SETTINGS; 22 import static android.Manifest.permission.TETHER_PRIVILEGED; 23 import static android.content.pm.PackageManager.FEATURE_WIFI; 24 import static android.net.InetAddresses.parseNumericAddress; 25 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL; 26 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL; 27 import static android.net.TetheringManager.TETHERING_ETHERNET; 28 import static android.net.TetheringTester.isExpectedIcmpPacket; 29 import static android.net.TetheringTester.isExpectedTcpPacket; 30 import static android.net.TetheringTester.isExpectedUdpPacket; 31 import static android.system.OsConstants.IPPROTO_IP; 32 import static android.system.OsConstants.IPPROTO_IPV6; 33 import static android.system.OsConstants.IPPROTO_TCP; 34 import static android.system.OsConstants.IPPROTO_UDP; 35 36 import static com.android.net.module.util.HexDump.dumpHexString; 37 import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV4; 38 import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6; 39 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT; 40 import static com.android.net.module.util.NetworkStackConstants.TCPHDR_ACK; 41 import static com.android.net.module.util.NetworkStackConstants.TCPHDR_SYN; 42 import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork; 43 import static com.android.testutils.TestPermissionUtil.runAsShell; 44 45 import static org.junit.Assert.assertEquals; 46 import static org.junit.Assert.assertFalse; 47 import static org.junit.Assert.assertNotNull; 48 import static org.junit.Assert.assertNull; 49 import static org.junit.Assert.assertTrue; 50 import static org.junit.Assert.fail; 51 import static org.junit.Assume.assumeFalse; 52 import static org.junit.Assume.assumeTrue; 53 54 import android.app.UiAutomation; 55 import android.content.Context; 56 import android.content.pm.PackageManager; 57 import android.net.EthernetManager.TetheredInterfaceCallback; 58 import android.net.EthernetManager.TetheredInterfaceRequest; 59 import android.net.TetheringManager.StartTetheringCallback; 60 import android.net.TetheringManager.TetheringEventCallback; 61 import android.net.TetheringManager.TetheringRequest; 62 import android.net.TetheringTester.TetheredDevice; 63 import android.net.cts.util.CtsNetUtils; 64 import android.os.Handler; 65 import android.os.HandlerThread; 66 import android.os.SystemClock; 67 import android.util.Log; 68 69 import androidx.annotation.NonNull; 70 import androidx.annotation.Nullable; 71 import androidx.test.platform.app.InstrumentationRegistry; 72 73 import com.android.modules.utils.build.SdkLevel; 74 import com.android.net.module.util.PacketBuilder; 75 import com.android.net.module.util.Struct; 76 import com.android.net.module.util.structs.Ipv6Header; 77 import com.android.testutils.HandlerUtils; 78 import com.android.testutils.TapPacketReader; 79 import com.android.testutils.TestNetworkTracker; 80 81 import org.junit.After; 82 import org.junit.Before; 83 84 import java.io.FileDescriptor; 85 import java.net.Inet4Address; 86 import java.net.Inet6Address; 87 import java.net.InetAddress; 88 import java.net.NetworkInterface; 89 import java.net.SocketException; 90 import java.nio.ByteBuffer; 91 import java.util.Arrays; 92 import java.util.Collection; 93 import java.util.List; 94 import java.util.Objects; 95 import java.util.Set; 96 import java.util.concurrent.CompletableFuture; 97 import java.util.concurrent.CountDownLatch; 98 import java.util.concurrent.TimeUnit; 99 import java.util.concurrent.TimeoutException; 100 101 /** 102 * TODO: Common variables or methods shared between CtsEthernetTetheringTest and 103 * MtsEthernetTetheringTest. 104 */ 105 public abstract class EthernetTetheringTestBase { 106 private static final String TAG = EthernetTetheringTestBase.class.getSimpleName(); 107 108 protected static final int TIMEOUT_MS = 5000; 109 // Used to check if any tethering interface is available. Choose 200ms to be request timeout 110 // because the average interface requested time on cuttlefish@acloud is around 10ms. 111 // See TetheredInterfaceRequester.getInterface, isInterfaceForTetheringAvailable. 112 private static final int AVAILABLE_TETHER_IFACE_REQUEST_TIMEOUT_MS = 200; 113 private static final int TETHER_REACHABILITY_ATTEMPTS = 20; 114 protected static final long WAIT_RA_TIMEOUT_MS = 2000; 115 116 // Address and NAT prefix definition. 117 protected static final MacAddress TEST_MAC = MacAddress.fromString("1:2:3:4:5:6"); 118 protected static final LinkAddress TEST_IP4_ADDR = new LinkAddress("10.0.0.1/24"); 119 protected static final LinkAddress TEST_IP6_ADDR = new LinkAddress("2001:db8:1::101/64"); 120 protected static final InetAddress TEST_IP4_DNS = parseNumericAddress("8.8.8.8"); 121 protected static final InetAddress TEST_IP6_DNS = parseNumericAddress("2001:db8:1::888"); 122 123 protected static final Inet4Address REMOTE_IP4_ADDR = 124 (Inet4Address) parseNumericAddress("8.8.8.8"); 125 protected static final Inet6Address REMOTE_IP6_ADDR = 126 (Inet6Address) parseNumericAddress("2002:db8:1::515:ca"); 127 protected static final Inet6Address REMOTE_NAT64_ADDR = 128 (Inet6Address) parseNumericAddress("64:ff9b::808:808"); 129 protected static final IpPrefix TEST_NAT64PREFIX = new IpPrefix("64:ff9b::/96"); 130 131 // IPv4 header definition. 132 protected static final short ID = 27149; 133 protected static final short FLAGS_AND_FRAGMENT_OFFSET = (short) 0x4000; // flags=DF, offset=0 134 protected static final byte TIME_TO_LIVE = (byte) 0x40; 135 protected static final byte TYPE_OF_SERVICE = 0; 136 137 // IPv6 header definition. 138 private static final short HOP_LIMIT = 0x40; 139 // version=6, traffic class=0x0, flowlabel=0x0; 140 private static final int VERSION_TRAFFICCLASS_FLOWLABEL = 0x60000000; 141 142 // UDP and TCP header definition. 143 // LOCAL_PORT is used by public port and private port. Assume port 9876 has not been used yet 144 // before the testing that public port and private port are the same in the testing. Note that 145 // NAT port forwarding could be different between private port and public port. 146 protected static final short LOCAL_PORT = 9876; 147 protected static final short REMOTE_PORT = 433; 148 private static final short WINDOW = (short) 0x2000; 149 private static final short URGENT_POINTER = 0; 150 151 // Payload definition. 152 protected static final ByteBuffer EMPTY_PAYLOAD = ByteBuffer.wrap(new byte[0]); 153 private static final ByteBuffer TEST_REACHABILITY_PAYLOAD = 154 ByteBuffer.wrap(new byte[] { (byte) 0x55, (byte) 0xaa }); 155 protected static final ByteBuffer RX_PAYLOAD = 156 ByteBuffer.wrap(new byte[] { (byte) 0x12, (byte) 0x34 }); 157 protected static final ByteBuffer TX_PAYLOAD = 158 ByteBuffer.wrap(new byte[] { (byte) 0x56, (byte) 0x78 }); 159 160 private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); 161 private final EthernetManager mEm = mContext.getSystemService(EthernetManager.class); 162 private final TetheringManager mTm = mContext.getSystemService(TetheringManager.class); 163 private final PackageManager mPackageManager = mContext.getPackageManager(); 164 private final CtsNetUtils mCtsNetUtils = new CtsNetUtils(mContext); 165 private final UiAutomation mUiAutomation = 166 InstrumentationRegistry.getInstrumentation().getUiAutomation(); 167 168 // Late initialization in setUp() 169 private boolean mRunTests; 170 private HandlerThread mHandlerThread; 171 private Handler mHandler; 172 private TetheredInterfaceRequester mTetheredInterfaceRequester; 173 174 // Late initialization in initTetheringTester(). 175 private TapPacketReader mUpstreamReader; 176 private TestNetworkTracker mUpstreamTracker; 177 private TestNetworkInterface mDownstreamIface; 178 private TapPacketReader mDownstreamReader; 179 private MyTetheringEventCallback mTetheringEventCallback; 180 181 @Before setUp()182 public void setUp() throws Exception { 183 mHandlerThread = new HandlerThread(getClass().getSimpleName()); 184 mHandlerThread.start(); 185 mHandler = new Handler(mHandlerThread.getLooper()); 186 187 mRunTests = runAsShell(NETWORK_SETTINGS, TETHER_PRIVILEGED, () -> 188 mTm.isTetheringSupported()); 189 assumeTrue(mRunTests); 190 191 mTetheredInterfaceRequester = new TetheredInterfaceRequester(mHandler, mEm); 192 } 193 maybeStopTapPacketReader(final TapPacketReader tapPacketReader)194 protected void maybeStopTapPacketReader(final TapPacketReader tapPacketReader) 195 throws Exception { 196 if (tapPacketReader != null) { 197 TapPacketReader reader = tapPacketReader; 198 mHandler.post(() -> reader.stop()); 199 } 200 } 201 maybeCloseTestInterface(final TestNetworkInterface testInterface)202 protected void maybeCloseTestInterface(final TestNetworkInterface testInterface) 203 throws Exception { 204 if (testInterface != null) { 205 testInterface.getFileDescriptor().close(); 206 Log.d(TAG, "Deleted test interface " + testInterface.getInterfaceName()); 207 } 208 } 209 maybeUnregisterTetheringEventCallback(final MyTetheringEventCallback callback)210 protected void maybeUnregisterTetheringEventCallback(final MyTetheringEventCallback callback) 211 throws Exception { 212 if (callback != null) { 213 callback.awaitInterfaceUntethered(); 214 callback.unregister(); 215 } 216 } 217 stopEthernetTethering(final MyTetheringEventCallback callback)218 protected void stopEthernetTethering(final MyTetheringEventCallback callback) { 219 runAsShell(TETHER_PRIVILEGED, () -> { 220 mTm.stopTethering(TETHERING_ETHERNET); 221 maybeUnregisterTetheringEventCallback(callback); 222 }); 223 } 224 cleanUp()225 protected void cleanUp() throws Exception { 226 setPreferTestNetworks(false); 227 228 if (mUpstreamTracker != null) { 229 runAsShell(MANAGE_TEST_NETWORKS, () -> { 230 mUpstreamTracker.teardown(); 231 mUpstreamTracker = null; 232 }); 233 } 234 if (mUpstreamReader != null) { 235 TapPacketReader reader = mUpstreamReader; 236 mHandler.post(() -> reader.stop()); 237 mUpstreamReader = null; 238 } 239 240 maybeStopTapPacketReader(mDownstreamReader); 241 mDownstreamReader = null; 242 // To avoid flaky which caused by the next test started but the previous interface is not 243 // untracked from EthernetTracker yet. Just delete the test interface without explicitly 244 // calling TetheringManager#stopTethering could let EthernetTracker untrack the test 245 // interface from server mode before tethering stopped. Thus, awaitInterfaceUntethered 246 // could not only make sure tethering is stopped but also guarantee the test interface is 247 // untracked from EthernetTracker. 248 maybeCloseTestInterface(mDownstreamIface); 249 mDownstreamIface = null; 250 maybeUnregisterTetheringEventCallback(mTetheringEventCallback); 251 mTetheringEventCallback = null; 252 253 runAsShell(NETWORK_SETTINGS, () -> mTetheredInterfaceRequester.release()); 254 setIncludeTestInterfaces(false); 255 } 256 257 @After tearDown()258 public void tearDown() throws Exception { 259 try { 260 if (mRunTests) cleanUp(); 261 } finally { 262 mHandlerThread.quitSafely(); 263 mHandlerThread.join(); 264 mUiAutomation.dropShellPermissionIdentity(); 265 } 266 } 267 isInterfaceForTetheringAvailable()268 protected boolean isInterfaceForTetheringAvailable() throws Exception { 269 // Before T, all ethernet interfaces could be used for server mode. Instead of 270 // waiting timeout, just checking whether the system currently has any 271 // ethernet interface is more reliable. 272 if (!SdkLevel.isAtLeastT()) { 273 return runAsShell(CONNECTIVITY_USE_RESTRICTED_NETWORKS, () -> mEm.isAvailable()); 274 } 275 276 // If previous test case doesn't release tethering interface successfully, the other tests 277 // after that test may be skipped as unexcepted. 278 // TODO: figure out a better way to check default tethering interface existenion. 279 final TetheredInterfaceRequester requester = new TetheredInterfaceRequester(mHandler, mEm); 280 try { 281 // Use short timeout (200ms) for requesting an existing interface, if any, because 282 // it should reurn faster than requesting a new tethering interface. Using default 283 // timeout (5000ms, TIMEOUT_MS) may make that total testing time is over 1 minute 284 // test module timeout on internal testing. 285 // TODO: if this becomes flaky, consider using default timeout (5000ms) and moving 286 // this check into #setUpOnce. 287 return requester.getInterface(AVAILABLE_TETHER_IFACE_REQUEST_TIMEOUT_MS) != null; 288 } catch (TimeoutException e) { 289 return false; 290 } finally { 291 runAsShell(NETWORK_SETTINGS, () -> { 292 requester.release(); 293 }); 294 } 295 } 296 setIncludeTestInterfaces(boolean include)297 protected void setIncludeTestInterfaces(boolean include) { 298 runAsShell(NETWORK_SETTINGS, () -> { 299 mEm.setIncludeTestInterfaces(include); 300 }); 301 } 302 setPreferTestNetworks(boolean prefer)303 protected void setPreferTestNetworks(boolean prefer) { 304 runAsShell(NETWORK_SETTINGS, () -> { 305 mTm.setPreferTestNetworks(prefer); 306 }); 307 } 308 getTetheredInterface()309 protected String getTetheredInterface() throws Exception { 310 return mTetheredInterfaceRequester.getInterface(); 311 } 312 requestTetheredInterface()313 protected CompletableFuture<String> requestTetheredInterface() throws Exception { 314 return mTetheredInterfaceRequester.requestInterface(); 315 } 316 waitForRouterAdvertisement(TapPacketReader reader, String iface, long timeoutMs)317 protected static void waitForRouterAdvertisement(TapPacketReader reader, String iface, 318 long timeoutMs) { 319 final long deadline = SystemClock.uptimeMillis() + timeoutMs; 320 do { 321 byte[] pkt = reader.popPacket(timeoutMs); 322 if (isExpectedIcmpPacket(pkt, true /* hasEth */, false /* isIpv4 */, 323 ICMPV6_ROUTER_ADVERTISEMENT)) { 324 return; 325 } 326 327 timeoutMs = deadline - SystemClock.uptimeMillis(); 328 } while (timeoutMs > 0); 329 fail("Did not receive router advertisement on " + iface + " after " 330 + timeoutMs + "ms idle"); 331 } 332 333 334 protected static final class MyTetheringEventCallback implements TetheringEventCallback { 335 private final TetheringManager mTm; 336 private final CountDownLatch mTetheringStartedLatch = new CountDownLatch(1); 337 private final CountDownLatch mTetheringStoppedLatch = new CountDownLatch(1); 338 private final CountDownLatch mLocalOnlyStartedLatch = new CountDownLatch(1); 339 private final CountDownLatch mLocalOnlyStoppedLatch = new CountDownLatch(1); 340 private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1); 341 private final CountDownLatch mUpstreamLatch = new CountDownLatch(1); 342 private final CountDownLatch mCallbackRegisteredLatch = new CountDownLatch(1); 343 private final TetheringInterface mIface; 344 private final Network mExpectedUpstream; 345 346 private boolean mAcceptAnyUpstream = false; 347 348 private volatile boolean mInterfaceWasTethered = false; 349 private volatile boolean mInterfaceWasLocalOnly = false; 350 private volatile boolean mUnregistered = false; 351 private volatile Collection<TetheredClient> mClients = null; 352 private volatile Network mUpstream = null; 353 MyTetheringEventCallback(TetheringManager tm, String iface)354 MyTetheringEventCallback(TetheringManager tm, String iface) { 355 this(tm, iface, null); 356 mAcceptAnyUpstream = true; 357 } 358 MyTetheringEventCallback(TetheringManager tm, String iface, Network expectedUpstream)359 MyTetheringEventCallback(TetheringManager tm, String iface, Network expectedUpstream) { 360 mTm = tm; 361 mIface = new TetheringInterface(TETHERING_ETHERNET, iface); 362 mExpectedUpstream = expectedUpstream; 363 } 364 unregister()365 public void unregister() { 366 mTm.unregisterTetheringEventCallback(this); 367 mUnregistered = true; 368 } 369 @Override onTetheredInterfacesChanged(List<String> interfaces)370 public void onTetheredInterfacesChanged(List<String> interfaces) { 371 fail("Should only call callback that takes a Set<TetheringInterface>"); 372 } 373 374 @Override onTetheredInterfacesChanged(Set<TetheringInterface> interfaces)375 public void onTetheredInterfacesChanged(Set<TetheringInterface> interfaces) { 376 // Ignore stale callbacks registered by previous test cases. 377 if (mUnregistered) return; 378 379 if (!mInterfaceWasTethered && interfaces.contains(mIface)) { 380 // This interface is being tethered for the first time. 381 Log.d(TAG, "Tethering started: " + interfaces); 382 mInterfaceWasTethered = true; 383 mTetheringStartedLatch.countDown(); 384 } else if (mInterfaceWasTethered && !interfaces.contains(mIface)) { 385 Log.d(TAG, "Tethering stopped: " + interfaces); 386 mTetheringStoppedLatch.countDown(); 387 } 388 } 389 390 @Override onLocalOnlyInterfacesChanged(List<String> interfaces)391 public void onLocalOnlyInterfacesChanged(List<String> interfaces) { 392 fail("Should only call callback that takes a Set<TetheringInterface>"); 393 } 394 395 @Override onLocalOnlyInterfacesChanged(Set<TetheringInterface> interfaces)396 public void onLocalOnlyInterfacesChanged(Set<TetheringInterface> interfaces) { 397 // Ignore stale callbacks registered by previous test cases. 398 if (mUnregistered) return; 399 400 if (!mInterfaceWasLocalOnly && interfaces.contains(mIface)) { 401 // This interface is being put into local-only mode for the first time. 402 Log.d(TAG, "Local-only started: " + interfaces); 403 mInterfaceWasLocalOnly = true; 404 mLocalOnlyStartedLatch.countDown(); 405 } else if (mInterfaceWasLocalOnly && !interfaces.contains(mIface)) { 406 Log.d(TAG, "Local-only stopped: " + interfaces); 407 mLocalOnlyStoppedLatch.countDown(); 408 } 409 } 410 awaitInterfaceTethered()411 public void awaitInterfaceTethered() throws Exception { 412 assertTrue("Ethernet not tethered after " + TIMEOUT_MS + "ms", 413 mTetheringStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 414 } 415 awaitInterfaceLocalOnly()416 public void awaitInterfaceLocalOnly() throws Exception { 417 assertTrue("Ethernet not local-only after " + TIMEOUT_MS + "ms", 418 mLocalOnlyStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 419 } 420 421 // Used to check if the callback has registered. When the callback is registered, 422 // onSupportedTetheringTypes is celled in onCallbackStarted(). After 423 // onSupportedTetheringTypes called, drop the permission for registering callback. 424 // See MyTetheringEventCallback#register, TetheringManager#onCallbackStarted. 425 @Override onSupportedTetheringTypes(Set<Integer> supportedTypes)426 public void onSupportedTetheringTypes(Set<Integer> supportedTypes) { 427 // Used to check callback registered. 428 mCallbackRegisteredLatch.countDown(); 429 } 430 awaitCallbackRegistered()431 public void awaitCallbackRegistered() throws Exception { 432 if (!mCallbackRegisteredLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) { 433 fail("Did not receive callback registered signal after " + TIMEOUT_MS + "ms"); 434 } 435 } 436 awaitInterfaceUntethered()437 public void awaitInterfaceUntethered() throws Exception { 438 // Don't block teardown if the interface was never tethered. 439 // This is racy because the interface might become tethered right after this check, but 440 // that can only happen in tearDown if startTethering timed out, which likely means 441 // the test has already failed. 442 if (!mInterfaceWasTethered && !mInterfaceWasLocalOnly) return; 443 444 if (mInterfaceWasTethered) { 445 assertTrue(mIface + " not untethered after " + TIMEOUT_MS + "ms", 446 mTetheringStoppedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 447 } else if (mInterfaceWasLocalOnly) { 448 assertTrue(mIface + " not untethered after " + TIMEOUT_MS + "ms", 449 mLocalOnlyStoppedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 450 } else { 451 fail(mIface + " cannot be both tethered and local-only. Update this test class."); 452 } 453 } 454 455 @Override onError(String ifName, int error)456 public void onError(String ifName, int error) { 457 // Ignore stale callbacks registered by previous test cases. 458 if (mUnregistered) return; 459 460 fail("TetheringEventCallback got error:" + error + " on iface " + ifName); 461 } 462 463 @Override onClientsChanged(Collection<TetheredClient> clients)464 public void onClientsChanged(Collection<TetheredClient> clients) { 465 // Ignore stale callbacks registered by previous test cases. 466 if (mUnregistered) return; 467 468 Log.d(TAG, "Got clients changed: " + clients); 469 mClients = clients; 470 if (clients.size() > 0) { 471 mClientConnectedLatch.countDown(); 472 } 473 } 474 awaitClientConnected()475 public Collection<TetheredClient> awaitClientConnected() throws Exception { 476 assertTrue("Did not receive client connected callback after " + TIMEOUT_MS + "ms", 477 mClientConnectedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 478 return mClients; 479 } 480 481 @Override onUpstreamChanged(Network network)482 public void onUpstreamChanged(Network network) { 483 // Ignore stale callbacks registered by previous test cases. 484 if (mUnregistered) return; 485 486 Log.d(TAG, "Got upstream changed: " + network); 487 mUpstream = network; 488 if (mAcceptAnyUpstream || Objects.equals(mUpstream, mExpectedUpstream)) { 489 mUpstreamLatch.countDown(); 490 } 491 } 492 awaitUpstreamChanged(boolean throwTimeoutException)493 public Network awaitUpstreamChanged(boolean throwTimeoutException) throws Exception { 494 if (!mUpstreamLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) { 495 final String errorMessage = "Did not receive upstream " 496 + (mAcceptAnyUpstream ? "any" : mExpectedUpstream) 497 + " callback after " + TIMEOUT_MS + "ms"; 498 499 if (throwTimeoutException) { 500 throw new TimeoutException(errorMessage); 501 } else { 502 fail(errorMessage); 503 } 504 } 505 return mUpstream; 506 } 507 } 508 enableEthernetTethering(String iface, TetheringRequest request, Network expectedUpstream)509 protected MyTetheringEventCallback enableEthernetTethering(String iface, 510 TetheringRequest request, Network expectedUpstream) throws Exception { 511 // Enable ethernet tethering with null expectedUpstream means the test accept any upstream 512 // after etherent tethering started. 513 final MyTetheringEventCallback callback; 514 if (expectedUpstream != null) { 515 callback = new MyTetheringEventCallback(mTm, iface, expectedUpstream); 516 } else { 517 callback = new MyTetheringEventCallback(mTm, iface); 518 } 519 runAsShell(NETWORK_SETTINGS, () -> { 520 mTm.registerTetheringEventCallback(mHandler::post, callback); 521 // Need to hold the shell permission until callback is registered. This helps to avoid 522 // the test become flaky. 523 callback.awaitCallbackRegistered(); 524 }); 525 final CountDownLatch tetheringStartedLatch = new CountDownLatch(1); 526 StartTetheringCallback startTetheringCallback = new StartTetheringCallback() { 527 @Override 528 public void onTetheringStarted() { 529 Log.d(TAG, "Ethernet tethering started"); 530 tetheringStartedLatch.countDown(); 531 } 532 533 @Override 534 public void onTetheringFailed(int resultCode) { 535 fail("Unexpectedly got onTetheringFailed"); 536 } 537 }; 538 Log.d(TAG, "Starting Ethernet tethering"); 539 runAsShell(TETHER_PRIVILEGED, () -> { 540 mTm.startTethering(request, mHandler::post /* executor */, startTetheringCallback); 541 // Binder call is an async call. Need to hold the shell permission until tethering 542 // started. This helps to avoid the test become flaky. 543 if (!tetheringStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) { 544 fail("Did not receive tethering started callback after " + TIMEOUT_MS + "ms"); 545 } 546 }); 547 548 final int connectivityType = request.getConnectivityScope(); 549 switch (connectivityType) { 550 case CONNECTIVITY_SCOPE_GLOBAL: 551 callback.awaitInterfaceTethered(); 552 break; 553 case CONNECTIVITY_SCOPE_LOCAL: 554 callback.awaitInterfaceLocalOnly(); 555 break; 556 default: 557 fail("Unexpected connectivity type requested: " + connectivityType); 558 } 559 560 return callback; 561 } 562 enableEthernetTethering(String iface, Network expectedUpstream)563 protected MyTetheringEventCallback enableEthernetTethering(String iface, 564 Network expectedUpstream) throws Exception { 565 return enableEthernetTethering(iface, 566 new TetheringRequest.Builder(TETHERING_ETHERNET) 567 .setShouldShowEntitlementUi(false).build(), expectedUpstream); 568 } 569 getMTU(TestNetworkInterface iface)570 protected int getMTU(TestNetworkInterface iface) throws SocketException { 571 NetworkInterface nif = NetworkInterface.getByName(iface.getInterfaceName()); 572 assertNotNull("Can't get NetworkInterface object for " + iface.getInterfaceName(), nif); 573 return nif.getMTU(); 574 } 575 makePacketReader(final TestNetworkInterface iface)576 protected TapPacketReader makePacketReader(final TestNetworkInterface iface) throws Exception { 577 FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor(); 578 return makePacketReader(fd, getMTU(iface)); 579 } 580 makePacketReader(FileDescriptor fd, int mtu)581 protected TapPacketReader makePacketReader(FileDescriptor fd, int mtu) { 582 final TapPacketReader reader = new TapPacketReader(mHandler, fd, mtu); 583 mHandler.post(() -> reader.start()); 584 HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS); 585 return reader; 586 } 587 588 protected static final class TetheredInterfaceRequester implements TetheredInterfaceCallback { 589 private final Handler mHandler; 590 private final EthernetManager mEm; 591 592 private TetheredInterfaceRequest mRequest; 593 private final CompletableFuture<String> mFuture = new CompletableFuture<>(); 594 TetheredInterfaceRequester(Handler handler, EthernetManager em)595 TetheredInterfaceRequester(Handler handler, EthernetManager em) { 596 mHandler = handler; 597 mEm = em; 598 } 599 600 @Override onAvailable(String iface)601 public void onAvailable(String iface) { 602 Log.d(TAG, "Ethernet interface available: " + iface); 603 mFuture.complete(iface); 604 } 605 606 @Override onUnavailable()607 public void onUnavailable() { 608 mFuture.completeExceptionally(new IllegalStateException("onUnavailable received")); 609 } 610 requestInterface()611 public CompletableFuture<String> requestInterface() { 612 assertNull("BUG: more than one tethered interface request", mRequest); 613 Log.d(TAG, "Requesting tethered interface"); 614 mRequest = runAsShell(NETWORK_SETTINGS, () -> 615 mEm.requestTetheredInterface(mHandler::post, this)); 616 return mFuture; 617 } 618 getInterface(int timeout)619 public String getInterface(int timeout) throws Exception { 620 return requestInterface().get(timeout, TimeUnit.MILLISECONDS); 621 } 622 getInterface()623 public String getInterface() throws Exception { 624 return getInterface(TIMEOUT_MS); 625 } 626 release()627 public void release() { 628 if (mRequest != null) { 629 mFuture.obtrudeException(new IllegalStateException("Request already released")); 630 mRequest.release(); 631 mRequest = null; 632 } 633 } 634 } 635 createTestInterface()636 protected TestNetworkInterface createTestInterface() throws Exception { 637 TestNetworkManager tnm = runAsShell(MANAGE_TEST_NETWORKS, () -> 638 mContext.getSystemService(TestNetworkManager.class)); 639 TestNetworkInterface iface = runAsShell(MANAGE_TEST_NETWORKS, () -> 640 tnm.createTapInterface()); 641 Log.d(TAG, "Created test interface " + iface.getInterfaceName()); 642 return iface; 643 } 644 createTestUpstream(final List<LinkAddress> addresses, final List<InetAddress> dnses)645 protected TestNetworkTracker createTestUpstream(final List<LinkAddress> addresses, 646 final List<InetAddress> dnses) throws Exception { 647 setPreferTestNetworks(true); 648 649 final LinkProperties lp = new LinkProperties(); 650 lp.setLinkAddresses(addresses); 651 lp.setDnsServers(dnses); 652 lp.setNat64Prefix(TEST_NAT64PREFIX); 653 654 return runAsShell(MANAGE_TEST_NETWORKS, () -> initTestNetwork(mContext, lp, TIMEOUT_MS)); 655 } 656 getEthType(@onNull final InetAddress srcIp, @NonNull final InetAddress dstIp)657 private short getEthType(@NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp) { 658 return isAddressIpv4(srcIp, dstIp) ? (short) ETHER_TYPE_IPV4 : (short) ETHER_TYPE_IPV6; 659 } 660 getIpProto(@onNull final InetAddress srcIp, @NonNull final InetAddress dstIp)661 private int getIpProto(@NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp) { 662 return isAddressIpv4(srcIp, dstIp) ? IPPROTO_IP : IPPROTO_IPV6; 663 } 664 665 @NonNull buildUdpPacket( @ullable final MacAddress srcMac, @Nullable final MacAddress dstMac, @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, short srcPort, short dstPort, @Nullable final ByteBuffer payload)666 protected ByteBuffer buildUdpPacket( 667 @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac, 668 @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, 669 short srcPort, short dstPort, @Nullable final ByteBuffer payload) 670 throws Exception { 671 final int ipProto = getIpProto(srcIp, dstIp); 672 final boolean hasEther = (srcMac != null && dstMac != null); 673 final int payloadLen = (payload == null) ? 0 : payload.limit(); 674 final ByteBuffer buffer = PacketBuilder.allocate(hasEther, ipProto, IPPROTO_UDP, 675 payloadLen); 676 final PacketBuilder packetBuilder = new PacketBuilder(buffer); 677 678 // [1] Ethernet header 679 if (hasEther) { 680 packetBuilder.writeL2Header(srcMac, dstMac, getEthType(srcIp, dstIp)); 681 } 682 683 // [2] IP header 684 if (ipProto == IPPROTO_IP) { 685 packetBuilder.writeIpv4Header(TYPE_OF_SERVICE, ID, FLAGS_AND_FRAGMENT_OFFSET, 686 TIME_TO_LIVE, (byte) IPPROTO_UDP, (Inet4Address) srcIp, (Inet4Address) dstIp); 687 } else { 688 packetBuilder.writeIpv6Header(VERSION_TRAFFICCLASS_FLOWLABEL, (byte) IPPROTO_UDP, 689 HOP_LIMIT, (Inet6Address) srcIp, (Inet6Address) dstIp); 690 } 691 692 // [3] UDP header 693 packetBuilder.writeUdpHeader(srcPort, dstPort); 694 695 // [4] Payload 696 if (payload != null) { 697 buffer.put(payload); 698 // in case data might be reused by caller, restore the position and 699 // limit of bytebuffer. 700 payload.clear(); 701 } 702 703 return packetBuilder.finalizePacket(); 704 } 705 706 @NonNull buildUdpPacket(@onNull final InetAddress srcIp, @NonNull final InetAddress dstIp, short srcPort, short dstPort, @Nullable final ByteBuffer payload)707 protected ByteBuffer buildUdpPacket(@NonNull final InetAddress srcIp, 708 @NonNull final InetAddress dstIp, short srcPort, short dstPort, 709 @Nullable final ByteBuffer payload) throws Exception { 710 return buildUdpPacket(null /* srcMac */, null /* dstMac */, srcIp, dstIp, srcPort, 711 dstPort, payload); 712 } 713 isAddressIpv4(@onNull final InetAddress srcIp, @NonNull final InetAddress dstIp)714 private boolean isAddressIpv4(@NonNull final InetAddress srcIp, 715 @NonNull final InetAddress dstIp) { 716 if (srcIp instanceof Inet4Address && dstIp instanceof Inet4Address) return true; 717 if (srcIp instanceof Inet6Address && dstIp instanceof Inet6Address) return false; 718 719 fail("Unsupported conditions: srcIp " + srcIp + ", dstIp " + dstIp); 720 return false; // unreachable 721 } 722 sendDownloadPacketUdp(@onNull final InetAddress srcIp, @NonNull final InetAddress dstIp, @NonNull final TetheringTester tester, boolean is6To4)723 protected void sendDownloadPacketUdp(@NonNull final InetAddress srcIp, 724 @NonNull final InetAddress dstIp, @NonNull final TetheringTester tester, 725 boolean is6To4) throws Exception { 726 if (is6To4) { 727 assertFalse("CLAT download test must sends IPv6 packet", isAddressIpv4(srcIp, dstIp)); 728 } 729 730 // Expected received UDP packet IP protocol. While testing CLAT (is6To4 = true), the packet 731 // on downstream must be IPv4. Otherwise, the IP protocol of test packet is the same on 732 // both downstream and upstream. 733 final boolean isIpv4 = is6To4 ? true : isAddressIpv4(srcIp, dstIp); 734 735 final ByteBuffer testPacket = buildUdpPacket(srcIp, dstIp, REMOTE_PORT /* srcPort */, 736 LOCAL_PORT /* dstPort */, RX_PAYLOAD); 737 tester.verifyDownload(testPacket, p -> { 738 Log.d(TAG, "Packet in downstream: " + dumpHexString(p)); 739 return isExpectedUdpPacket(p, true /* hasEther */, isIpv4, RX_PAYLOAD); 740 }); 741 } 742 sendUploadPacketUdp(@onNull final MacAddress srcMac, @NonNull final MacAddress dstMac, @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, @NonNull final TetheringTester tester, boolean is4To6)743 protected void sendUploadPacketUdp(@NonNull final MacAddress srcMac, 744 @NonNull final MacAddress dstMac, @NonNull final InetAddress srcIp, 745 @NonNull final InetAddress dstIp, @NonNull final TetheringTester tester, 746 boolean is4To6) throws Exception { 747 if (is4To6) { 748 assertTrue("CLAT upload test must sends IPv4 packet", isAddressIpv4(srcIp, dstIp)); 749 } 750 751 // Expected received UDP packet IP protocol. While testing CLAT (is4To6 = true), the packet 752 // on upstream must be IPv6. Otherwise, the IP protocol of test packet is the same on 753 // both downstream and upstream. 754 final boolean isIpv4 = is4To6 ? false : isAddressIpv4(srcIp, dstIp); 755 756 final ByteBuffer testPacket = buildUdpPacket(srcMac, dstMac, srcIp, dstIp, 757 LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */, TX_PAYLOAD); 758 tester.verifyUpload(testPacket, p -> { 759 Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); 760 return isExpectedUdpPacket(p, false /* hasEther */, isIpv4, TX_PAYLOAD); 761 }); 762 } 763 764 765 @NonNull buildTcpPacket( @ullable final MacAddress srcMac, @Nullable final MacAddress dstMac, @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, short srcPort, short dstPort, final short seq, final short ack, final byte tcpFlags, @NonNull final ByteBuffer payload)766 private ByteBuffer buildTcpPacket( 767 @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac, 768 @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, 769 short srcPort, short dstPort, final short seq, final short ack, 770 final byte tcpFlags, @NonNull final ByteBuffer payload) throws Exception { 771 final int ipProto = getIpProto(srcIp, dstIp); 772 final boolean hasEther = (srcMac != null && dstMac != null); 773 final ByteBuffer buffer = PacketBuilder.allocate(hasEther, ipProto, IPPROTO_TCP, 774 payload.limit()); 775 final PacketBuilder packetBuilder = new PacketBuilder(buffer); 776 777 // [1] Ethernet header 778 if (hasEther) { 779 packetBuilder.writeL2Header(srcMac, dstMac, getEthType(srcIp, dstIp)); 780 } 781 782 // [2] IP header 783 if (ipProto == IPPROTO_IP) { 784 packetBuilder.writeIpv4Header(TYPE_OF_SERVICE, ID, FLAGS_AND_FRAGMENT_OFFSET, 785 TIME_TO_LIVE, (byte) IPPROTO_TCP, (Inet4Address) srcIp, (Inet4Address) dstIp); 786 } else { 787 packetBuilder.writeIpv6Header(VERSION_TRAFFICCLASS_FLOWLABEL, (byte) IPPROTO_TCP, 788 HOP_LIMIT, (Inet6Address) srcIp, (Inet6Address) dstIp); 789 } 790 791 // [3] TCP header 792 packetBuilder.writeTcpHeader(srcPort, dstPort, seq, ack, tcpFlags, WINDOW, URGENT_POINTER); 793 794 // [4] Payload 795 buffer.put(payload); 796 // in case data might be reused by caller, restore the position and 797 // limit of bytebuffer. 798 payload.clear(); 799 800 return packetBuilder.finalizePacket(); 801 } 802 sendDownloadPacketTcp(@onNull final InetAddress srcIp, @NonNull final InetAddress dstIp, short seq, short ack, byte tcpFlags, @NonNull final ByteBuffer payload, @NonNull final TetheringTester tester, boolean is6To4)803 protected void sendDownloadPacketTcp(@NonNull final InetAddress srcIp, 804 @NonNull final InetAddress dstIp, short seq, short ack, byte tcpFlags, 805 @NonNull final ByteBuffer payload, @NonNull final TetheringTester tester, 806 boolean is6To4) throws Exception { 807 if (is6To4) { 808 assertFalse("CLAT download test must sends IPv6 packet", isAddressIpv4(srcIp, dstIp)); 809 } 810 811 // Expected received TCP packet IP protocol. While testing CLAT (is6To4 = true), the packet 812 // on downstream must be IPv4. Otherwise, the IP protocol of test packet is the same on 813 // both downstream and upstream. 814 final boolean isIpv4 = is6To4 ? true : isAddressIpv4(srcIp, dstIp); 815 816 final ByteBuffer testPacket = buildTcpPacket(null /* srcMac */, null /* dstMac */, 817 srcIp, dstIp, REMOTE_PORT /* srcPort */, LOCAL_PORT /* dstPort */, seq, ack, 818 tcpFlags, payload); 819 tester.verifyDownload(testPacket, p -> { 820 Log.d(TAG, "Packet in downstream: " + dumpHexString(p)); 821 822 return isExpectedTcpPacket(p, true /* hasEther */, isIpv4, seq, payload); 823 }); 824 } 825 sendUploadPacketTcp(@onNull final MacAddress srcMac, @NonNull final MacAddress dstMac, @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, short seq, short ack, byte tcpFlags, @NonNull final ByteBuffer payload, @NonNull final TetheringTester tester, boolean is4To6)826 protected void sendUploadPacketTcp(@NonNull final MacAddress srcMac, 827 @NonNull final MacAddress dstMac, @NonNull final InetAddress srcIp, 828 @NonNull final InetAddress dstIp, short seq, short ack, byte tcpFlags, 829 @NonNull final ByteBuffer payload, @NonNull final TetheringTester tester, 830 boolean is4To6) throws Exception { 831 if (is4To6) { 832 assertTrue("CLAT upload test must sends IPv4 packet", isAddressIpv4(srcIp, dstIp)); 833 } 834 835 // Expected received TCP packet IP protocol. While testing CLAT (is4To6 = true), the packet 836 // on upstream must be IPv6. Otherwise, the IP protocol of test packet is the same on 837 // both downstream and upstream. 838 final boolean isIpv4 = is4To6 ? false : isAddressIpv4(srcIp, dstIp); 839 840 final ByteBuffer testPacket = buildTcpPacket(srcMac, dstMac, srcIp, dstIp, 841 LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */, seq, ack, tcpFlags, 842 payload); 843 tester.verifyUpload(testPacket, p -> { 844 Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); 845 846 return isExpectedTcpPacket(p, false /* hasEther */, isIpv4, seq, payload); 847 }); 848 } 849 runTcpTest( @onNull final MacAddress uploadSrcMac, @NonNull final MacAddress uploadDstMac, @NonNull final InetAddress uploadSrcIp, @NonNull final InetAddress uploadDstIp, @NonNull final InetAddress downloadSrcIp, @NonNull final InetAddress downloadDstIp, @NonNull final TetheringTester tester, boolean isClat)850 protected void runTcpTest( 851 @NonNull final MacAddress uploadSrcMac, @NonNull final MacAddress uploadDstMac, 852 @NonNull final InetAddress uploadSrcIp, @NonNull final InetAddress uploadDstIp, 853 @NonNull final InetAddress downloadSrcIp, @NonNull final InetAddress downloadDstIp, 854 @NonNull final TetheringTester tester, boolean isClat) throws Exception { 855 // Three way handshake and data transfer. 856 // 857 // Server (base seq = 2000) Client (base seq = 1000) 858 // | | 859 // | [1] [SYN] SEQ = 1000 | 860 // |<---------------------------------------------------------| - 861 // | | ^ 862 // | [2] [SYN + ACK] SEQ = 2000, ACK = 1000+1 | | 863 // |--------------------------------------------------------->| three way handshake 864 // | | | 865 // | [3] [ACK] SEQ = 1001, ACK = 2000+1 | v 866 // |<---------------------------------------------------------| - 867 // | | ^ 868 // | [4] [ACK] SEQ = 1001, ACK = 2001, 2 byte payload | | 869 // |<---------------------------------------------------------| data transfer 870 // | | | 871 // | [5] [ACK] SEQ = 2001, ACK = 1001+2, 2 byte payload | v 872 // |--------------------------------------------------------->| - 873 // | | 874 // 875 876 // This test can only verify the packets are transferred end to end but TCP state. 877 // TODO: verify TCP state change via /proc/net/nf_conntrack or netlink conntrack event. 878 // [1] [UPLOAD] [SYN]: SEQ = 1000 879 sendUploadPacketTcp(uploadSrcMac, uploadDstMac, uploadSrcIp, uploadDstIp, 880 (short) 1000 /* seq */, (short) 0 /* ack */, TCPHDR_SYN, EMPTY_PAYLOAD, 881 tester, isClat /* is4To6 */); 882 883 // [2] [DONWLOAD] [SYN + ACK]: SEQ = 2000, ACK = 1001 884 sendDownloadPacketTcp(downloadSrcIp, downloadDstIp, (short) 2000 /* seq */, 885 (short) 1001 /* ack */, (byte) ((TCPHDR_SYN | TCPHDR_ACK) & 0xff), EMPTY_PAYLOAD, 886 tester, isClat /* is6To4 */); 887 888 // [3] [UPLOAD] [ACK]: SEQ = 1001, ACK = 2001 889 sendUploadPacketTcp(uploadSrcMac, uploadDstMac, uploadSrcIp, uploadDstIp, 890 (short) 1001 /* seq */, (short) 2001 /* ack */, TCPHDR_ACK, EMPTY_PAYLOAD, tester, 891 isClat /* is4To6 */); 892 893 // [4] [UPLOAD] [ACK]: SEQ = 1001, ACK = 2001, 2 byte payload 894 sendUploadPacketTcp(uploadSrcMac, uploadDstMac, uploadSrcIp, uploadDstIp, 895 (short) 1001 /* seq */, (short) 2001 /* ack */, TCPHDR_ACK, TX_PAYLOAD, 896 tester, isClat /* is4To6 */); 897 898 // [5] [DONWLOAD] [ACK]: SEQ = 2001, ACK = 1003, 2 byte payload 899 sendDownloadPacketTcp(downloadSrcIp, downloadDstIp, (short) 2001 /* seq */, 900 (short) 1003 /* ack */, TCPHDR_ACK, RX_PAYLOAD, tester, isClat /* is6To4 */); 901 902 // TODO: test BPF offload maps. 903 } 904 905 // TODO: remove ipv4 verification (is4To6 = false) once upstream connected notification race is 906 // fixed. See #runUdp4Test. 907 // 908 // This function sends a probe packet to downstream interface and exam the result from upstream 909 // interface to make sure ipv4 tethering is ready. Return the entire packet which received from 910 // upstream interface. 911 @NonNull probeV4TetheringConnectivity(TetheringTester tester, TetheredDevice tethered, boolean is4To6)912 protected byte[] probeV4TetheringConnectivity(TetheringTester tester, TetheredDevice tethered, 913 boolean is4To6) throws Exception { 914 final ByteBuffer probePacket = buildUdpPacket(tethered.macAddr, 915 tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */, 916 REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */, 917 TEST_REACHABILITY_PAYLOAD); 918 919 // Send a UDP packet from client and check the packet can be found on upstream interface. 920 for (int i = 0; i < TETHER_REACHABILITY_ATTEMPTS; i++) { 921 byte[] expectedPacket = tester.testUpload(probePacket, p -> { 922 Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); 923 // If is4To6 is true, the ipv4 probe packet would be translated to ipv6 by Clat and 924 // would see this translated ipv6 packet in upstream interface. 925 return isExpectedUdpPacket(p, false /* hasEther */, !is4To6 /* isIpv4 */, 926 TEST_REACHABILITY_PAYLOAD); 927 }); 928 if (expectedPacket != null) return expectedPacket; 929 } 930 931 fail("Can't verify " + (is4To6 ? "ipv4 to ipv6" : "ipv4") + " tethering connectivity after " 932 + TETHER_REACHABILITY_ATTEMPTS + " attempts"); 933 return null; 934 } 935 936 // TODO: remove triggering upstream reselection once test network can replace selected upstream 937 // network in Tethering module. maybeRetryTestedUpstreamChanged(final Network expectedUpstream, final TimeoutException fallbackException)938 private void maybeRetryTestedUpstreamChanged(final Network expectedUpstream, 939 final TimeoutException fallbackException) throws Exception { 940 // Fall back original exception because no way to reselect if there is no WIFI feature. 941 assertTrue(fallbackException.toString(), mPackageManager.hasSystemFeature(FEATURE_WIFI)); 942 943 // Try to toggle wifi network, if any, to reselect upstream network via default network 944 // switching. Because test network has higher priority than internet network, this can 945 // help selecting test network to be upstream network for testing. This tries to avoid 946 // the flaky upstream selection under multinetwork environment. Internet and test network 947 // upstream changed event order is not guaranteed. Once tethering selects non-test 948 // upstream {wifi, ..}, test network won't be selected anymore. If too many test cases 949 // trigger the reselection, the total test time may over test suite 1 minmute timeout. 950 // Probably need to disable/restore all internet networks in a common place of test 951 // process. Currently, EthernetTetheringTest is part of CTS test which needs wifi network 952 // connection if device has wifi feature. CtsNetUtils#toggleWifi() checks wifi connection 953 // during the toggling process. 954 // See Tethering#chooseUpstreamType, CtsNetUtils#toggleWifi. 955 // TODO: toggle cellular network if the device has no WIFI feature. 956 Log.d(TAG, "Toggle WIFI to retry upstream selection"); 957 mCtsNetUtils.toggleWifi(); 958 959 // Wait for expected upstream. 960 final CompletableFuture<Network> future = new CompletableFuture<>(); 961 final TetheringEventCallback callback = new TetheringEventCallback() { 962 @Override 963 public void onUpstreamChanged(Network network) { 964 Log.d(TAG, "Got upstream changed: " + network); 965 if (Objects.equals(expectedUpstream, network)) { 966 future.complete(network); 967 } 968 } 969 }; 970 try { 971 mTm.registerTetheringEventCallback(mHandler::post, callback); 972 assertEquals("onUpstreamChanged for unexpected network", expectedUpstream, 973 future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 974 } catch (TimeoutException e) { 975 throw new AssertionError("Did not receive upstream " + expectedUpstream 976 + " callback after " + TIMEOUT_MS + "ms"); 977 } finally { 978 mTm.unregisterTetheringEventCallback(callback); 979 } 980 } 981 initTetheringTester(List<LinkAddress> upstreamAddresses, List<InetAddress> upstreamDnses)982 protected TetheringTester initTetheringTester(List<LinkAddress> upstreamAddresses, 983 List<InetAddress> upstreamDnses) throws Exception { 984 assumeFalse(isInterfaceForTetheringAvailable()); 985 986 // MyTetheringEventCallback currently only support await first available upstream. Tethering 987 // may select internet network as upstream if test network is not available and not be 988 // preferred yet. Create test upstream network before enable tethering. 989 mUpstreamTracker = createTestUpstream(upstreamAddresses, upstreamDnses); 990 991 mDownstreamIface = createTestInterface(); 992 setIncludeTestInterfaces(true); 993 994 // Make sure EtherentTracker use "mDownstreamIface" as server mode interface. 995 assertEquals("TetheredInterfaceCallback for unexpected interface", 996 mDownstreamIface.getInterfaceName(), mTetheredInterfaceRequester.getInterface()); 997 998 mTetheringEventCallback = enableEthernetTethering(mDownstreamIface.getInterfaceName(), 999 mUpstreamTracker.getNetwork()); 1000 1001 try { 1002 assertEquals("onUpstreamChanged for test network", mUpstreamTracker.getNetwork(), 1003 mTetheringEventCallback.awaitUpstreamChanged( 1004 true /* throwTimeoutException */)); 1005 } catch (TimeoutException e) { 1006 // Due to race condition inside tethering module, test network may not be selected as 1007 // tethering upstream. Force tethering retry upstream if possible. If it is not 1008 // possible to retry, fail the test with the original timeout exception. 1009 maybeRetryTestedUpstreamChanged(mUpstreamTracker.getNetwork(), e); 1010 } 1011 1012 mDownstreamReader = makePacketReader(mDownstreamIface); 1013 mUpstreamReader = makePacketReader(mUpstreamTracker.getTestIface()); 1014 1015 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1016 // Currently tethering don't have API to tell when ipv6 tethering is available. Thus, make 1017 // sure tethering already have ipv6 connectivity before testing. 1018 if (cm.getLinkProperties(mUpstreamTracker.getNetwork()).hasGlobalIpv6Address()) { 1019 waitForRouterAdvertisement(mDownstreamReader, mDownstreamIface.getInterfaceName(), 1020 WAIT_RA_TIMEOUT_MS); 1021 } 1022 1023 return new TetheringTester(mDownstreamReader, mUpstreamReader); 1024 } 1025 1026 @NonNull getClatIpv6Address(TetheringTester tester, TetheredDevice tethered)1027 protected Inet6Address getClatIpv6Address(TetheringTester tester, TetheredDevice tethered) 1028 throws Exception { 1029 // Send an IPv4 UDP packet from client and check that a CLAT translated IPv6 UDP packet can 1030 // be found on upstream interface. Get CLAT IPv6 address from the CLAT translated IPv6 UDP 1031 // packet. 1032 byte[] expectedPacket = probeV4TetheringConnectivity(tester, tethered, true /* is4To6 */); 1033 1034 // Above has guaranteed that the found packet is an IPv6 packet without ether header. 1035 return Struct.parse(Ipv6Header.class, ByteBuffer.wrap(expectedPacket)).srcIp; 1036 } 1037 toList(T... array)1038 protected <T> List<T> toList(T... array) { 1039 return Arrays.asList(array); 1040 } 1041 } 1042