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