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