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