diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java index 609d759e5b..d0ba43174c 100644 --- a/Tethering/src/android/net/ip/IpServer.java +++ b/Tethering/src/android/net/ip/IpServer.java @@ -852,16 +852,13 @@ public class IpServer extends StateMachineShim { } } - private void removeRoutesFromNetworkAndLinkProperties(int netId, - @NonNull final List toBeRemoved) { + private void removeRoutesFromNetwork(int netId, @NonNull final List toBeRemoved) { final int removalFailures = NetdUtils.removeRoutesFromNetwork( mNetd, netId, toBeRemoved); if (removalFailures > 0) { mLog.e("Failed to remove " + removalFailures + " IPv6 routes from network " + netId + "."); } - - for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route); } private void addInterfaceToNetwork(final int netId, @NonNull final String ifaceName) { @@ -888,7 +885,7 @@ public class IpServer extends StateMachineShim { } } - private void addRoutesToNetworkAndLinkProperties(int netId, + private void addRoutesToNetwork(int netId, @NonNull final List toBeAdded) { // It's safe to call addInterfaceToNetwork() even if // the interface is already in the network. @@ -901,16 +898,16 @@ public class IpServer extends StateMachineShim { mLog.e("Failed to add IPv4/v6 routes to local table: " + e); return; } - - for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); } private void configureLocalIPv6Routes( ArraySet deprecatedPrefixes, ArraySet newPrefixes) { // [1] Remove the routes that are deprecated. if (!deprecatedPrefixes.isEmpty()) { - removeRoutesFromNetworkAndLinkProperties(LOCAL_NET_ID, - getLocalRoutesFor(mIfaceName, deprecatedPrefixes)); + final List routesToBeRemoved = + getLocalRoutesFor(mIfaceName, deprecatedPrefixes); + removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved); + for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route); } // [2] Add only the routes that have not previously been added. @@ -921,8 +918,10 @@ public class IpServer extends StateMachineShim { } if (!addedPrefixes.isEmpty()) { - addRoutesToNetworkAndLinkProperties(LOCAL_NET_ID, - getLocalRoutesFor(mIfaceName, addedPrefixes)); + final List routesToBeAdded = + getLocalRoutesFor(mIfaceName, addedPrefixes); + addRoutesToNetwork(LOCAL_NET_ID, routesToBeAdded); + for (RouteInfo route : routesToBeAdded) mLinkProperties.addRoute(route); } } } @@ -1126,8 +1125,17 @@ public class IpServer extends StateMachineShim { } try { - NetdUtils.tetherInterface(mNetd, LOCAL_NET_ID, mIfaceName, - asIpPrefix(mIpv4Address)); + // Enable IPv6, disable accepting RA, etc. See TetherController::tetherInterface() + // for more detail. + mNetd.tetherInterfaceAdd(mIfaceName); + NetdUtils.networkAddInterface(mNetd, LOCAL_NET_ID, mIfaceName, + 20 /* maxAttempts */, 50 /* pollingIntervalMs */); + // Activate a route to dest and IPv6 link local. + NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID, + new RouteInfo(asIpPrefix(mIpv4Address), null, mIfaceName, RTN_UNICAST)); + NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID, + new RouteInfo(new IpPrefix("fe80::/64"), null, mIfaceName, + RTN_UNICAST)); } catch (RemoteException | ServiceSpecificException | IllegalStateException e) { mLog.e("Error Tethering", e); mLastError = TETHER_ERROR_TETHER_IFACE_ERROR; @@ -1148,8 +1156,13 @@ public class IpServer extends StateMachineShim { // all in sequence. stopIPv6(); + // Reset interface for tethering. try { - NetdUtils.untetherInterface(mNetd, LOCAL_NET_ID, mIfaceName); + try { + mNetd.tetherInterfaceRemove(mIfaceName); + } finally { + mNetd.networkRemoveInterface(LOCAL_NET_ID, mIfaceName); + } } catch (RemoteException | ServiceSpecificException e) { mLastError = TETHER_ERROR_UNTETHER_IFACE_ERROR; mLog.e("Failed to untether interface: " + e); @@ -1227,13 +1240,16 @@ public class IpServer extends StateMachineShim { } // Remove deprecated routes from downstream network. - removeRoutesFromNetworkAndLinkProperties(LOCAL_NET_ID, - List.of(getDirectConnectedRoute(deprecatedLinkAddress))); + final List routesToBeRemoved = + List.of(getDirectConnectedRoute(deprecatedLinkAddress)); + removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved); + for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route); mLinkProperties.removeLinkAddress(deprecatedLinkAddress); // Add new routes to downstream network. - addRoutesToNetworkAndLinkProperties(LOCAL_NET_ID, - List.of(getDirectConnectedRoute(mIpv4Address))); + final List routesToBeAdded = List.of(getDirectConnectedRoute(mIpv4Address)); + addRoutesToNetwork(LOCAL_NET_ID, routesToBeAdded); + for (RouteInfo route : routesToBeAdded) mLinkProperties.addRoute(route); mLinkProperties.addLinkAddress(mIpv4Address); // Update local DNS caching server with new IPv4 address, otherwise, dnsmasq doesn't diff --git a/staticlibs/client-libs/netd/com/android/net/module/util/NetdUtils.java b/staticlibs/client-libs/netd/com/android/net/module/util/NetdUtils.java index 8b2fe58d56..4af516d0e9 100644 --- a/staticlibs/client-libs/netd/com/android/net/module/util/NetdUtils.java +++ b/staticlibs/client-libs/netd/com/android/net/module/util/NetdUtils.java @@ -148,25 +148,6 @@ public class NetdUtils { netd.tetherStartWithConfiguration(config); } - /** Setup interface for tethering. */ - public static void tetherInterface(final INetd netd, int netId, final String iface, - final IpPrefix dest) throws RemoteException, ServiceSpecificException { - tetherInterface(netd, netId, iface, dest, 20 /* maxAttempts */, 50 /* pollingIntervalMs */); - } - - /** Setup interface with configurable retries for tethering. */ - public static void tetherInterface(final INetd netd, int netId, final String iface, - final IpPrefix dest, int maxAttempts, int pollingIntervalMs) - throws RemoteException, ServiceSpecificException { - netd.tetherInterfaceAdd(iface); - networkAddInterface(netd, netId, iface, maxAttempts, pollingIntervalMs); - // Activate a route to dest and IPv6 link local. - modifyRoute(netd, ModifyOperation.ADD, netId, - new RouteInfo(dest, null, iface, RTN_UNICAST)); - modifyRoute(netd, ModifyOperation.ADD, netId, - new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST)); - } - /** * Retry Netd#networkAddInterface for EBUSY error code. * If the same interface (e.g., wlan0) is in client mode and then switches to tethered mode. @@ -174,7 +155,7 @@ public class NetdUtils { * in use in netd because the ConnectivityService thread hasn't processed the disconnect yet. * See b/158269544 for detail. */ - private static void networkAddInterface(final INetd netd, int netId, final String iface, + public static void networkAddInterface(final INetd netd, int netId, final String iface, int maxAttempts, int pollingIntervalMs) throws ServiceSpecificException, RemoteException { for (int i = 1; i <= maxAttempts; i++) { @@ -193,16 +174,6 @@ public class NetdUtils { } } - /** Reset interface for tethering. */ - public static void untetherInterface(final INetd netd, int netId, String iface) - throws RemoteException, ServiceSpecificException { - try { - netd.tetherInterfaceRemove(iface); - } finally { - netd.networkRemoveInterface(netId, iface); - } - } - /** Add |routes| to the given network. */ public static void addRoutesToNetwork(final INetd netd, int netId, final String iface, final List routes) { diff --git a/staticlibs/client-libs/tests/unit/src/com/android/net/module/util/NetdUtilsTest.java b/staticlibs/client-libs/tests/unit/src/com/android/net/module/util/NetdUtilsTest.java index c2fbb561e2..0241d0a2e9 100644 --- a/staticlibs/client-libs/tests/unit/src/com/android/net/module/util/NetdUtilsTest.java +++ b/staticlibs/client-libs/tests/unit/src/com/android/net/module/util/NetdUtilsTest.java @@ -24,13 +24,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -39,7 +35,6 @@ import static org.mockito.Mockito.when; import android.net.INetd; import android.net.InterfaceConfigurationParcel; -import android.net.IpPrefix; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -61,7 +56,6 @@ public class NetdUtilsTest { @Mock private INetd mNetd; private static final String IFACE = "TEST_IFACE"; - private static final IpPrefix TEST_IPPREFIX = new IpPrefix("192.168.42.1/24"); private static final int TEST_NET_ID = 123; @Before @@ -150,20 +144,21 @@ public class NetdUtilsTest { } @Test - public void testTetherInterfaceSuccessful() throws Exception { + public void testNetworkAddInterfaceSuccessful() throws Exception { // Expect #networkAddInterface successful at first tries. - verifyTetherInterfaceSucceeds(1); + verifyNetworkAddInterfaceSucceeds(1); // Expect #networkAddInterface successful after 10 tries. - verifyTetherInterfaceSucceeds(10); + verifyNetworkAddInterfaceSucceeds(10); } - private void runTetherInterfaceWithServiceSpecificException(int expectedTries, + private void runNetworkAddInterfaceWithServiceSpecificException(int expectedTries, int expectedCode) throws Exception { setNetworkAddInterfaceOutcome(new ServiceSpecificException(expectedCode), expectedTries); try { - NetdUtils.tetherInterface(mNetd, TEST_NET_ID, IFACE, TEST_IPPREFIX, 20, 0); + NetdUtils.networkAddInterface(mNetd, TEST_NET_ID, IFACE, + 20 /* maxAttempts */, 0 /* pollingIntervalMs */); fail("Expect throw ServiceSpecificException"); } catch (ServiceSpecificException e) { assertEquals(e.errorCode, expectedCode); @@ -173,11 +168,12 @@ public class NetdUtilsTest { reset(mNetd); } - private void runTetherInterfaceWithRemoteException(int expectedTries) throws Exception { + private void runNetworkAddInterfaceWithRemoteException(int expectedTries) throws Exception { setNetworkAddInterfaceOutcome(new RemoteException(), expectedTries); try { - NetdUtils.tetherInterface(mNetd, TEST_NET_ID, IFACE, TEST_IPPREFIX, 20, 0); + NetdUtils.networkAddInterface(mNetd, TEST_NET_ID, IFACE, + 20 /* maxAttempts */, 0 /* pollingIntervalMs */); fail("Expect throw RemoteException"); } catch (RemoteException e) { } @@ -186,41 +182,37 @@ public class NetdUtilsTest { } private void verifyNetworkAddInterfaceFails(int expectedTries) throws Exception { - verify(mNetd).tetherInterfaceAdd(IFACE); verify(mNetd, times(expectedTries)).networkAddInterface(TEST_NET_ID, IFACE); - verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any()); - verifyNoMoreInteractions(mNetd); } - private void verifyTetherInterfaceSucceeds(int expectedTries) throws Exception { + private void verifyNetworkAddInterfaceSucceeds(int expectedTries) throws Exception { setNetworkAddInterfaceOutcome(null, expectedTries); - NetdUtils.tetherInterface(mNetd, TEST_NET_ID, IFACE, TEST_IPPREFIX); - verify(mNetd).tetherInterfaceAdd(IFACE); + NetdUtils.networkAddInterface(mNetd, TEST_NET_ID, IFACE, + 20 /* maxAttempts */, 0 /* pollingIntervalMs */); verify(mNetd, times(expectedTries)).networkAddInterface(TEST_NET_ID, IFACE); - verify(mNetd, times(2)).networkAddRoute(eq(TEST_NET_ID), eq(IFACE), any(), any()); verifyNoMoreInteractions(mNetd); reset(mNetd); } @Test - public void testTetherInterfaceFailOnNetworkAddInterface() throws Exception { + public void testFailOnNetworkAddInterface() throws Exception { // Test throwing ServiceSpecificException with EBUSY failure. - runTetherInterfaceWithServiceSpecificException(20, EBUSY); + runNetworkAddInterfaceWithServiceSpecificException(20, EBUSY); // Test throwing ServiceSpecificException with unexpectedError. final int unexpectedError = 999; - runTetherInterfaceWithServiceSpecificException(1, unexpectedError); + runNetworkAddInterfaceWithServiceSpecificException(1, unexpectedError); // Test throwing ServiceSpecificException with unexpectedError after 7 tries. - runTetherInterfaceWithServiceSpecificException(7, unexpectedError); + runNetworkAddInterfaceWithServiceSpecificException(7, unexpectedError); // Test throwing RemoteException. - runTetherInterfaceWithRemoteException(1); + runNetworkAddInterfaceWithRemoteException(1); // Test throwing RemoteException after 3 tries. - runTetherInterfaceWithRemoteException(3); + runNetworkAddInterfaceWithRemoteException(3); } @Test