Loading tests/integration/src/android/net/ip/IpClientIntegrationTest.java +80 −11 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ import com.android.networkstack.apishim.CaptivePortalDataShimImpl; import com.android.networkstack.apishim.ConstantsShim; import com.android.networkstack.apishim.ShimUtils; import com.android.networkstack.arp.ArpPacket; import com.android.server.NetworkObserver; import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; Loading Loading @@ -164,6 +165,8 @@ import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Tests for IpClient. Loading Loading @@ -195,6 +198,7 @@ public class IpClientIntegrationTest { @Spy private INetd mNetd; private String mIfaceName; private NetworkObserverRegistry mNetworkObserverRegistry; private HandlerThread mPacketReaderThread; private Handler mHandler; private TapPacketReader mPacketReader; Loading Loading @@ -437,10 +441,10 @@ public class IpClientIntegrationTest { when(mContext.getSystemService(eq(Context.NETD_SERVICE))).thenReturn(netdIBinder); assertNotNull(mNetd); final NetworkObserverRegistry reg = new NetworkObserverRegistry(); reg.register(mNetd); mIpc = new IpClient(mContext, mIfaceName, mCb, reg, mNetworkStackServiceManager, mDependencies); mNetworkObserverRegistry = new NetworkObserverRegistry(); mNetworkObserverRegistry.register(mNetd); mIpc = new IpClient(mContext, mIfaceName, mCb, mNetworkObserverRegistry, mNetworkStackServiceManager, mDependencies); } private boolean packetContainsExpectedField(final byte[] packet, final int offset, Loading Loading @@ -1176,6 +1180,19 @@ public class IpClientIntegrationTest { fail("No router solicitation received on interface within timeout"); } private void sendBasicRouterAdvertisement(boolean waitForRs) throws Exception { final String dnsServer = "2001:4860:4860::64"; final ByteBuffer pio = buildPioOption(3600, 1800, "2001:db8:1::/64"); ByteBuffer rdnss = buildRdnssOption(3600, dnsServer); ByteBuffer ra = buildRaPacket(pio, rdnss); if (waitForRs) { waitForRouterSolicitation(); } mPacketReader.sendResponse(ra); } // TODO: move this and the following method to a common location and use them in ApfTest. private static ByteBuffer buildPioOption(int valid, int preferred, String prefixString) throws Exception { Loading Loading @@ -1428,6 +1445,41 @@ public class IpClientIntegrationTest { expectNat64PrefixUpdate(inOrder, otherPrefix); } private void addIpAddressAndWaitForIt(final String iface) throws Exception { final CountDownLatch latch = new CountDownLatch(1); final String addr1 = "192.0.2.99"; final String addr2 = "192.0.2.3"; final int prefixLength = 26; // Add two IPv4 addresses to the specified interface, and proceed when the NetworkObserver // has seen the second one. This ensures that every other NetworkObserver registered with // mNetworkObserverRegistry - in particular, IpClient's - has seen the addition of the first // address. final LinkAddress trigger = new LinkAddress(addr2 + "/" + prefixLength); NetworkObserver observer = new NetworkObserver() { @Override public void onInterfaceAddressUpdated(LinkAddress address, String ifName) { if (ifName.equals(iface) && address.isSameAddressAs(trigger)) { latch.countDown(); } } }; mNetworkObserverRegistry.registerObserverForNonblockingCallback(observer); try { mNetd.interfaceAddAddress(iface, addr1, prefixLength); mNetd.interfaceAddAddress(iface, addr2, prefixLength); assertTrue("Trigger IP address " + addr2 + " not seen after " + TEST_TIMEOUT_MS + "ms", latch.await(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)); } finally { mNetworkObserverRegistry.unregisterObserver(observer); } // Wait for IpClient to process the addition of the address. HandlerUtilsKt.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS); } @Test public void testIpClientClearingIpAddressState() throws Exception { final long currentTime = System.currentTimeMillis(); Loading @@ -1446,14 +1498,31 @@ public class IpClientIntegrationTest { // Pretend that something else (e.g., Tethering) used the interface and left an IP address // configured on it. When IpClient starts, it must clear this address before proceeding. // TODO: test IPv6 instead, since the DHCP client will remove this address by replacing it // with the new address. mNetd.interfaceAddAddress(mIfaceName, "192.0.2.99", 26); // The address must be noticed before startProvisioning is called, or IpClient will // immediately declare provisioning success due to the presence of an IPv4 address. // The address must be IPv4 because IpClient clears IPv6 addresses on startup. // // TODO: once IpClient gets IP addresses directly from netlink instead of from netd, it // may be sufficient to call waitForIdle to see if IpClient has seen the address. addIpAddressAndWaitForIt(mIfaceName); // start IpClient again and should enter Clearing State and wait for the message from kernel performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, TEST_DEFAULT_MTU, false /* isDhcpIpConflictDetectEnabled */); disableRouterSolicitationDelay(); ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() .withoutIpReachabilityMonitor() .build(); mIpc.startProvisioning(config); sendBasicRouterAdvertisement(true /*waitForRs*/); // Check that the IPv4 addresses configured earlier are not in LinkProperties... ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture()); assertFalse(captor.getValue().hasIpv4Address()); // ... or configured on the interface. InterfaceConfigurationParcel cfg = mNetd.interfaceGetCfg(mIfaceName); assertEquals("0.0.0.0", cfg.ipv4Addr); } @Test Loading Loading
tests/integration/src/android/net/ip/IpClientIntegrationTest.java +80 −11 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ import com.android.networkstack.apishim.CaptivePortalDataShimImpl; import com.android.networkstack.apishim.ConstantsShim; import com.android.networkstack.apishim.ShimUtils; import com.android.networkstack.arp.ArpPacket; import com.android.server.NetworkObserver; import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; Loading Loading @@ -164,6 +165,8 @@ import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Tests for IpClient. Loading Loading @@ -195,6 +198,7 @@ public class IpClientIntegrationTest { @Spy private INetd mNetd; private String mIfaceName; private NetworkObserverRegistry mNetworkObserverRegistry; private HandlerThread mPacketReaderThread; private Handler mHandler; private TapPacketReader mPacketReader; Loading Loading @@ -437,10 +441,10 @@ public class IpClientIntegrationTest { when(mContext.getSystemService(eq(Context.NETD_SERVICE))).thenReturn(netdIBinder); assertNotNull(mNetd); final NetworkObserverRegistry reg = new NetworkObserverRegistry(); reg.register(mNetd); mIpc = new IpClient(mContext, mIfaceName, mCb, reg, mNetworkStackServiceManager, mDependencies); mNetworkObserverRegistry = new NetworkObserverRegistry(); mNetworkObserverRegistry.register(mNetd); mIpc = new IpClient(mContext, mIfaceName, mCb, mNetworkObserverRegistry, mNetworkStackServiceManager, mDependencies); } private boolean packetContainsExpectedField(final byte[] packet, final int offset, Loading Loading @@ -1176,6 +1180,19 @@ public class IpClientIntegrationTest { fail("No router solicitation received on interface within timeout"); } private void sendBasicRouterAdvertisement(boolean waitForRs) throws Exception { final String dnsServer = "2001:4860:4860::64"; final ByteBuffer pio = buildPioOption(3600, 1800, "2001:db8:1::/64"); ByteBuffer rdnss = buildRdnssOption(3600, dnsServer); ByteBuffer ra = buildRaPacket(pio, rdnss); if (waitForRs) { waitForRouterSolicitation(); } mPacketReader.sendResponse(ra); } // TODO: move this and the following method to a common location and use them in ApfTest. private static ByteBuffer buildPioOption(int valid, int preferred, String prefixString) throws Exception { Loading Loading @@ -1428,6 +1445,41 @@ public class IpClientIntegrationTest { expectNat64PrefixUpdate(inOrder, otherPrefix); } private void addIpAddressAndWaitForIt(final String iface) throws Exception { final CountDownLatch latch = new CountDownLatch(1); final String addr1 = "192.0.2.99"; final String addr2 = "192.0.2.3"; final int prefixLength = 26; // Add two IPv4 addresses to the specified interface, and proceed when the NetworkObserver // has seen the second one. This ensures that every other NetworkObserver registered with // mNetworkObserverRegistry - in particular, IpClient's - has seen the addition of the first // address. final LinkAddress trigger = new LinkAddress(addr2 + "/" + prefixLength); NetworkObserver observer = new NetworkObserver() { @Override public void onInterfaceAddressUpdated(LinkAddress address, String ifName) { if (ifName.equals(iface) && address.isSameAddressAs(trigger)) { latch.countDown(); } } }; mNetworkObserverRegistry.registerObserverForNonblockingCallback(observer); try { mNetd.interfaceAddAddress(iface, addr1, prefixLength); mNetd.interfaceAddAddress(iface, addr2, prefixLength); assertTrue("Trigger IP address " + addr2 + " not seen after " + TEST_TIMEOUT_MS + "ms", latch.await(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)); } finally { mNetworkObserverRegistry.unregisterObserver(observer); } // Wait for IpClient to process the addition of the address. HandlerUtilsKt.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS); } @Test public void testIpClientClearingIpAddressState() throws Exception { final long currentTime = System.currentTimeMillis(); Loading @@ -1446,14 +1498,31 @@ public class IpClientIntegrationTest { // Pretend that something else (e.g., Tethering) used the interface and left an IP address // configured on it. When IpClient starts, it must clear this address before proceeding. // TODO: test IPv6 instead, since the DHCP client will remove this address by replacing it // with the new address. mNetd.interfaceAddAddress(mIfaceName, "192.0.2.99", 26); // The address must be noticed before startProvisioning is called, or IpClient will // immediately declare provisioning success due to the presence of an IPv4 address. // The address must be IPv4 because IpClient clears IPv6 addresses on startup. // // TODO: once IpClient gets IP addresses directly from netlink instead of from netd, it // may be sufficient to call waitForIdle to see if IpClient has seen the address. addIpAddressAndWaitForIt(mIfaceName); // start IpClient again and should enter Clearing State and wait for the message from kernel performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, TEST_DEFAULT_MTU, false /* isDhcpIpConflictDetectEnabled */); disableRouterSolicitationDelay(); ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() .withoutIpReachabilityMonitor() .build(); mIpc.startProvisioning(config); sendBasicRouterAdvertisement(true /*waitForRs*/); // Check that the IPv4 addresses configured earlier are not in LinkProperties... ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture()); assertFalse(captor.getValue().hasIpv4Address()); // ... or configured on the interface. InterfaceConfigurationParcel cfg = mNetd.interfaceGetCfg(mIfaceName); assertEquals("0.0.0.0", cfg.ipv4Addr); } @Test Loading