Add an integration test to verify NUD failure due to router MAC changes.
Simulate a MAC address change scenario where the device sends broadcast
ARP request to query the default gateway's MAC address, but receives two
ARP replies, that would trigger onReachabilityFailure callback and WiFi
refreshes L3 provisioning.
Bug: 315076572
Test: atest NetworkStackIntegrationTests
Change-Id: I3f77cedb68e88ccd8ce215c16eb0b43b90256f12
diff --git a/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java b/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
index c769f84..d23e328 100644
--- a/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
+++ b/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
@@ -4241,9 +4241,60 @@
NudEventType.NUD_POST_ROAMING_MAC_ADDRESS_CHANGED);
}
- private void sendUdpPacketToNetwork(final Network network, final Inet6Address remoteIp,
+ @Test
+ @SignatureRequiredTest(reason = "Need to mock the NetworkAgent")
+ public void testIpReachabilityMonitor_replyBroadcastArpRequestWithDiffMacAddresses()
+ throws Exception {
+ mNetworkAgentThread =
+ new HandlerThread(IpClientIntegrationTestCommon.class.getSimpleName());
+ mNetworkAgentThread.start();
+
+ ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withoutIPv6()
+ .build();
+ setDhcpFeatures(true /* isRapidCommitEnabled */, false /* isDhcpIpConflictDetectEnabled */);
+ startIpClientProvisioning(config);
+
+ // Start IPv4 provisioning and wait until entire provisioning completes.
+ handleDhcpPackets(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
+ true /* shouldReplyRapidCommitAck */, TEST_DEFAULT_MTU, null /* serverSentUrl */);
+ final LinkProperties lp =
+ verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
+
+ runAsShell(MANAGE_TEST_NETWORKS, () -> createTestNetworkAgentAndRegister(lp));
+
+ // Send a UDP packet to IPv4 DNS server to trigger address resolution process for IPv4
+ // on-link DNS server or default router.
+ final Random random = new Random();
+ final byte[] data = new byte[100];
+ random.nextBytes(data);
+ sendUdpPacketToNetwork(mNetworkAgent.getNetwork(), SERVER_ADDR, 1234 /* port */, data);
+
+ // Respond to the broadcast ARP request.
+ final ArpPacket request = getNextArpPacket();
+ assertArpRequest(request, SERVER_ADDR);
+ sendArpReply(request.senderHwAddress.toByteArray() /* dst */, ROUTER_MAC_BYTES /* srcMac */,
+ request.senderIp /* target IP */, SERVER_ADDR /* sender IP */);
+
+ Thread.sleep(1500);
+
+ // Reply with a different MAC address but the same server IP.
+ final MacAddress gateway = MacAddress.fromString("00:11:22:33:44:55");
+ sendArpReply(request.senderHwAddress.toByteArray() /* dst */,
+ gateway.toByteArray() /* srcMac */,
+ request.senderIp /* target IP */, SERVER_ADDR /* sender IP */);
+
+ final ArgumentCaptor<ReachabilityLossInfoParcelable> lossInfoCaptor =
+ ArgumentCaptor.forClass(ReachabilityLossInfoParcelable.class);
+ verify(mCb, timeout(TEST_TIMEOUT_MS)).onReachabilityFailure(lossInfoCaptor.capture());
+ assertEquals(ReachabilityLossReason.ORGANIC, lossInfoCaptor.getValue().reason);
+ }
+
+ private void sendUdpPacketToNetwork(final Network network, final InetAddress remoteIp,
int port, final byte[] data) throws Exception {
- final DatagramSocket socket = new DatagramSocket(0, (InetAddress) Inet6Address.ANY);
+ final InetAddress laddr =
+ (remoteIp instanceof Inet6Address) ? Inet6Address.ANY : Inet4Address.ANY;
+ final DatagramSocket socket = new DatagramSocket(0, laddr);
final DatagramPacket pkt = new DatagramPacket(data, data.length, remoteIp, port);
network.bindSocket(socket);
socket.send(pkt);