Merge "Improve RouterAdvertisementDaemonTest." am: 662237f2f8

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1669025

Change-Id: I9e9bb95e095fa1b8d907d56cc0e347746ae9a01c
This commit is contained in:
Treehugger Robot
2021-04-08 04:45:41 +00:00
committed by Automerger Merge Worker

View File

@@ -16,6 +16,8 @@
package android.net.ip; package android.net.ip;
import static android.net.RouteInfo.RTN_UNICAST;
import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN; import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6; import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_MTU; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_MTU;
@@ -27,6 +29,8 @@ import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_AD
import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST; import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST;
import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_LEN; import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_LEN;
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN; import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_AUTONOMOUS;
import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_ON_LINK;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@@ -38,7 +42,9 @@ import android.content.Context;
import android.net.INetd; import android.net.INetd;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.MacAddress; import android.net.MacAddress;
import android.net.RouteInfo;
import android.net.ip.RouterAdvertisementDaemon.RaParams; import android.net.ip.RouterAdvertisementDaemon.RaParams;
import android.net.shared.RouteUtils;
import android.net.util.InterfaceParams; import android.net.util.InterfaceParams;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
@@ -74,6 +80,7 @@ import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
@@ -96,8 +103,6 @@ public final class RouterAdvertisementDaemonTest {
@BeforeClass @BeforeClass
public static void setupOnce() { public static void setupOnce() {
System.loadLibrary("tetherutilsjni");
final Instrumentation inst = InstrumentationRegistry.getInstrumentation(); final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
final IBinder netdIBinder = final IBinder netdIBinder =
(IBinder) inst.getContext().getSystemService(Context.NETD_SERVICE); (IBinder) inst.getContext().getSystemService(Context.NETD_SERVICE);
@@ -151,7 +156,7 @@ public final class RouterAdvertisementDaemonTest {
mNewParams = newParams; mNewParams = newParams;
} }
public boolean isPacketMatched(final byte[] pkt) throws Exception { public boolean isPacketMatched(final byte[] pkt, boolean multicast) throws Exception {
if (pkt.length < (ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_RA_HEADER_LEN)) { if (pkt.length < (ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_RA_HEADER_LEN)) {
return false; return false;
} }
@@ -172,6 +177,15 @@ public final class RouterAdvertisementDaemonTest {
final Icmpv6Header icmpv6Hdr = Struct.parse(Icmpv6Header.class, buf); final Icmpv6Header icmpv6Hdr = Struct.parse(Icmpv6Header.class, buf);
if (icmpv6Hdr.type != (short) ICMPV6_ROUTER_ADVERTISEMENT) return false; if (icmpv6Hdr.type != (short) ICMPV6_ROUTER_ADVERTISEMENT) return false;
// Check whether IPv6 destination address is multicast or unicast
if (multicast) {
assertEquals(ipv6Hdr.dstIp, IPV6_ADDR_ALL_NODES_MULTICAST);
} else {
// The unicast IPv6 destination address in RA can be either link-local or global
// IPv6 address. This test only expects link-local address.
assertTrue(ipv6Hdr.dstIp.isLinkLocalAddress());
}
// Parse RA header // Parse RA header
final RaHeader raHdr = Struct.parse(RaHeader.class, buf); final RaHeader raHdr = Struct.parse(RaHeader.class, buf);
assertEquals(mNewParams.hopLimit, raHdr.hopLimit); assertEquals(mNewParams.hopLimit, raHdr.hopLimit);
@@ -182,13 +196,15 @@ public final class RouterAdvertisementDaemonTest {
final int length = Byte.toUnsignedInt(buf.get()); final int length = Byte.toUnsignedInt(buf.get());
switch (type) { switch (type) {
case ICMPV6_ND_OPTION_PIO: case ICMPV6_ND_OPTION_PIO:
// length is 4 because this test only expects one PIO included in the
// router advertisement packet.
assertEquals(4, length); assertEquals(4, length);
final ByteBuffer pioBuf = ByteBuffer.wrap(buf.array(), currentPos, final ByteBuffer pioBuf = ByteBuffer.wrap(buf.array(), currentPos,
Struct.getSize(PrefixInformationOption.class)); Struct.getSize(PrefixInformationOption.class));
final PrefixInformationOption pio = final PrefixInformationOption pio =
Struct.parse(PrefixInformationOption.class, pioBuf); Struct.parse(PrefixInformationOption.class, pioBuf);
assertEquals((byte) 0xc0, pio.flags); // L & A set assertEquals((byte) (PIO_FLAG_ON_LINK | PIO_FLAG_AUTONOMOUS), pio.flags);
final InetAddress address = InetAddress.getByAddress(pio.prefix); final InetAddress address = InetAddress.getByAddress(pio.prefix);
final IpPrefix prefix = new IpPrefix(address, pio.prefixLen); final IpPrefix prefix = new IpPrefix(address, pio.prefixLen);
@@ -199,7 +215,7 @@ public final class RouterAdvertisementDaemonTest {
assertEquals(0, pio.validLifetime); assertEquals(0, pio.validLifetime);
assertEquals(0, pio.preferredLifetime); assertEquals(0, pio.preferredLifetime);
} else { } else {
fail("Unepxected prefix: " + prefix); fail("Unexpected prefix: " + prefix);
} }
// Move ByteBuffer position to the next option. // Move ByteBuffer position to the next option.
@@ -261,15 +277,24 @@ public final class RouterAdvertisementDaemonTest {
return params; return params;
} }
private boolean assertRaPacket(final TestRaPacket testRa) private boolean isRaPacket(final TestRaPacket testRa, boolean multicast) throws Exception {
throws Exception {
byte[] packet; byte[] packet;
while ((packet = mTetheredPacketReader.poll(PACKET_TIMEOUT_MS)) != null) { while ((packet = mTetheredPacketReader.poll(PACKET_TIMEOUT_MS)) != null) {
if (testRa.isPacketMatched(packet)) return true; if (testRa.isPacketMatched(packet, multicast)) {
return true;
}
} }
return false; return false;
} }
private void assertUnicastRaPacket(final TestRaPacket testRa) throws Exception {
assertTrue(isRaPacket(testRa, false /* multicast */));
}
private void assertMulticastRaPacket(final TestRaPacket testRa) throws Exception {
assertTrue(isRaPacket(testRa, true /* multicast */));
}
private ByteBuffer createRsPacket(final String srcIp) throws Exception { private ByteBuffer createRsPacket(final String srcIp) throws Exception {
final MacAddress dstMac = MacAddress.fromString("33:33:03:04:05:06"); final MacAddress dstMac = MacAddress.fromString("33:33:03:04:05:06");
final MacAddress srcMac = mTetheredParams.macAddr; final MacAddress srcMac = mTetheredParams.macAddr;
@@ -284,22 +309,36 @@ public final class RouterAdvertisementDaemonTest {
assertTrue(mRaDaemon.start()); assertTrue(mRaDaemon.start());
final RaParams params1 = createRaParams("2001:1122:3344::5566"); final RaParams params1 = createRaParams("2001:1122:3344::5566");
mRaDaemon.buildNewRa(null, params1); mRaDaemon.buildNewRa(null, params1);
assertRaPacket(new TestRaPacket(null, params1)); assertMulticastRaPacket(new TestRaPacket(null, params1));
final RaParams params2 = createRaParams("2006:3344:5566::7788"); final RaParams params2 = createRaParams("2006:3344:5566::7788");
mRaDaemon.buildNewRa(params1, params2); mRaDaemon.buildNewRa(params1, params2);
assertRaPacket(new TestRaPacket(params1, params2)); assertMulticastRaPacket(new TestRaPacket(params1, params2));
} }
@Test @Test
public void testSolicitRouterAdvertisement() throws Exception { public void testSolicitRouterAdvertisement() throws Exception {
// Enable IPv6 forwarding is necessary, which makes kernel process RS correctly and
// create the neighbor entry for peer's link-layer address and IPv6 address. Otherwise,
// when device receives RS with IPv6 link-local address as source address, it has to
// initiate the address resolution first before responding the unicast RA.
sNetd.setProcSysNet(INetd.IPV6, INetd.CONF, mTetheredParams.name, "forwarding", "1");
assertTrue(mRaDaemon.start()); assertTrue(mRaDaemon.start());
final RaParams params1 = createRaParams("2001:1122:3344::5566"); final RaParams params1 = createRaParams("2001:1122:3344::5566");
mRaDaemon.buildNewRa(null, params1); mRaDaemon.buildNewRa(null, params1);
assertRaPacket(new TestRaPacket(null, params1)); assertMulticastRaPacket(new TestRaPacket(null, params1));
// Add a default route "fe80::/64 -> ::" to local network, otherwise, device will fail to
// send the unicast RA out due to the ENETUNREACH error(No route to the peer's link-local
// address is present).
final String iface = mTetheredParams.name;
final RouteInfo linkLocalRoute =
new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST);
RouteUtils.addRoutesToLocalNetwork(sNetd, iface, List.of(linkLocalRoute));
final ByteBuffer rs = createRsPacket("fe80::1122:3344:5566:7788"); final ByteBuffer rs = createRsPacket("fe80::1122:3344:5566:7788");
mTetheredPacketReader.sendResponse(rs); mTetheredPacketReader.sendResponse(rs);
assertRaPacket(new TestRaPacket(null, params1)); assertUnicastRaPacket(new TestRaPacket(null, params1));
} }
} }