Merge "IpConn metrics: correctly read RA lifetimes" into nyc-mr1-dev

This commit is contained in:
Hugo Benichi
2016-07-05 12:25:54 +00:00
committed by Android (Google) Code Review
3 changed files with 150 additions and 37 deletions

View File

@@ -27,6 +27,9 @@ import android.os.Parcelable;
@SystemApi @SystemApi
public final class RaEvent implements Parcelable { public final class RaEvent implements Parcelable {
/** {@hide} */
public static final long NO_LIFETIME = -1L;
// Lifetime in seconds of options found in a single RA packet. // Lifetime in seconds of options found in a single RA packet.
// When an option is not set, the value of the associated field is -1; // When an option is not set, the value of the associated field is -1;
public final long routerLifetime; public final long routerLifetime;
@@ -92,4 +95,60 @@ public final class RaEvent implements Parcelable {
return new RaEvent[size]; return new RaEvent[size];
} }
}; };
/** {@hide} */
public static class Builder {
long routerLifetime = NO_LIFETIME;
long prefixValidLifetime = NO_LIFETIME;
long prefixPreferredLifetime = NO_LIFETIME;
long routeInfoLifetime = NO_LIFETIME;
long rdnssLifetime = NO_LIFETIME;
long dnsslLifetime = NO_LIFETIME;
public Builder() {
}
public RaEvent build() {
return new RaEvent(routerLifetime, prefixValidLifetime, prefixPreferredLifetime,
routeInfoLifetime, rdnssLifetime, dnsslLifetime);
}
public Builder updateRouterLifetime(long lifetime) {
routerLifetime = updateLifetime(routerLifetime, lifetime);
return this;
}
public Builder updatePrefixValidLifetime(long lifetime) {
prefixValidLifetime = updateLifetime(prefixValidLifetime, lifetime);
return this;
}
public Builder updatePrefixPreferredLifetime(long lifetime) {
prefixPreferredLifetime = updateLifetime(prefixPreferredLifetime, lifetime);
return this;
}
public Builder updateRouteInfoLifetime(long lifetime) {
routeInfoLifetime = updateLifetime(routeInfoLifetime, lifetime);
return this;
}
public Builder updateRdnssLifetime(long lifetime) {
rdnssLifetime = updateLifetime(rdnssLifetime, lifetime);
return this;
}
public Builder updateDnsslLifetime(long lifetime) {
dnsslLifetime = updateLifetime(dnsslLifetime, lifetime);
return this;
}
private long updateLifetime(long currentLifetime, long newLifetime) {
if (currentLifetime == RaEvent.NO_LIFETIME) {
return newLifetime;
}
return Math.min(currentLifetime, newLifetime);
}
}
} }

View File

@@ -213,7 +213,7 @@ public class ApfFilter {
private final ApfCapabilities mApfCapabilities; private final ApfCapabilities mApfCapabilities;
private final IpManager.Callback mIpManagerCallback; private final IpManager.Callback mIpManagerCallback;
private final NetworkInterface mNetworkInterface; private final NetworkInterface mNetworkInterface;
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog(); private final IpConnectivityLog mMetricsLog;
@VisibleForTesting @VisibleForTesting
byte[] mHardwareAddress; byte[] mHardwareAddress;
@VisibleForTesting @VisibleForTesting
@@ -228,11 +228,12 @@ public class ApfFilter {
@VisibleForTesting @VisibleForTesting
ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface, ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface,
IpManager.Callback ipManagerCallback, boolean multicastFilter) { IpManager.Callback ipManagerCallback, boolean multicastFilter, IpConnectivityLog log) {
mApfCapabilities = apfCapabilities; mApfCapabilities = apfCapabilities;
mIpManagerCallback = ipManagerCallback; mIpManagerCallback = ipManagerCallback;
mNetworkInterface = networkInterface; mNetworkInterface = networkInterface;
mMulticastFilter = multicastFilter; mMulticastFilter = multicastFilter;
mMetricsLog = log;
maybeStartFilter(); maybeStartFilter();
} }
@@ -371,6 +372,14 @@ public class ApfFilter {
return i & 0xffffffffL; return i & 0xffffffffL;
} }
private long getUint16(ByteBuffer buffer, int position) {
return uint16(buffer.getShort(position));
}
private long getUint32(ByteBuffer buffer, int position) {
return uint32(buffer.getInt(position));
}
private void prefixOptionToString(StringBuffer sb, int offset) { private void prefixOptionToString(StringBuffer sb, int offset) {
String prefix = IPv6AddresstoString(offset + 16); String prefix = IPv6AddresstoString(offset + 16);
int length = uint8(mPacket.get(offset + 2)); int length = uint8(mPacket.get(offset + 2));
@@ -438,9 +447,9 @@ public class ApfFilter {
// (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
// specifications. // specifications.
Ra(byte[] packet, int length) { Ra(byte[] packet, int length) {
mPacket = ByteBuffer.allocate(length).put(ByteBuffer.wrap(packet, 0, length)); mPacket = ByteBuffer.wrap(Arrays.copyOf(packet, length));
mPacket.clear();
mLastSeen = curTime(); mLastSeen = curTime();
RaEvent.Builder builder = new RaEvent.Builder();
// Ignore the checksum. // Ignore the checksum.
int lastNonLifetimeStart = addNonLifetime(0, int lastNonLifetimeStart = addNonLifetime(0,
@@ -451,14 +460,7 @@ public class ApfFilter {
lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart, lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
ICMP6_RA_ROUTER_LIFETIME_OFFSET, ICMP6_RA_ROUTER_LIFETIME_OFFSET,
ICMP6_RA_ROUTER_LIFETIME_LEN); ICMP6_RA_ROUTER_LIFETIME_LEN);
builder.updateRouterLifetime(getUint16(mPacket, ICMP6_RA_ROUTER_LIFETIME_OFFSET));
long routerLifetime = uint16(mPacket.getShort(
ICMP6_RA_ROUTER_LIFETIME_OFFSET + mPacket.position()));
long prefixValidLifetime = -1L;
long prefixPreferredLifetime = -1L;
long routeInfoLifetime = -1L;
long dnsslLifetime = - 1L;
long rdnssLifetime = -1L;
// Ensures that the RA is not truncated. // Ensures that the RA is not truncated.
mPacket.position(ICMP6_RA_OPTION_OFFSET); mPacket.position(ICMP6_RA_OPTION_OFFSET);
@@ -466,39 +468,42 @@ public class ApfFilter {
final int position = mPacket.position(); final int position = mPacket.position();
final int optionType = uint8(mPacket.get(position)); final int optionType = uint8(mPacket.get(position));
final int optionLength = uint8(mPacket.get(position + 1)) * 8; final int optionLength = uint8(mPacket.get(position + 1)) * 8;
long lifetime;
switch (optionType) { switch (optionType) {
case ICMP6_PREFIX_OPTION_TYPE: case ICMP6_PREFIX_OPTION_TYPE:
// Parse valid lifetime // Parse valid lifetime
lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart, lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET, ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN); ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN);
lifetime = getUint32(mPacket,
position + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET);
builder.updatePrefixValidLifetime(lifetime);
// Parse preferred lifetime // Parse preferred lifetime
lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart, lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET, ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN); ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN);
lifetime = getUint32(mPacket,
position + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET);
builder.updatePrefixPreferredLifetime(lifetime);
mPrefixOptionOffsets.add(position); mPrefixOptionOffsets.add(position);
prefixValidLifetime = uint32(mPacket.getInt(
ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET + position));
prefixPreferredLifetime = uint32(mPacket.getInt(
ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET + position));
break; break;
// These three options have the same lifetime offset and size, and // These three options have the same lifetime offset and size, and
// are processed with the same specialized addNonLifetime4B: // are processed with the same specialized addNonLifetimeU32:
case ICMP6_RDNSS_OPTION_TYPE: case ICMP6_RDNSS_OPTION_TYPE:
mRdnssOptionOffsets.add(position); mRdnssOptionOffsets.add(position);
lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart); lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
rdnssLifetime = lifetime = getUint32(mPacket, position + ICMP6_4_BYTE_LIFETIME_OFFSET);
uint32(mPacket.getInt(ICMP6_4_BYTE_LIFETIME_OFFSET + position)); builder.updateRdnssLifetime(lifetime);
break; break;
case ICMP6_ROUTE_INFO_OPTION_TYPE: case ICMP6_ROUTE_INFO_OPTION_TYPE:
lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart); lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
routeInfoLifetime = lifetime = getUint32(mPacket, position + ICMP6_4_BYTE_LIFETIME_OFFSET);
uint32(mPacket.getInt(ICMP6_4_BYTE_LIFETIME_OFFSET + position)); builder.updateRouteInfoLifetime(lifetime);
break; break;
case ICMP6_DNSSL_OPTION_TYPE: case ICMP6_DNSSL_OPTION_TYPE:
lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart); lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
dnsslLifetime = lifetime = getUint32(mPacket, position + ICMP6_4_BYTE_LIFETIME_OFFSET);
uint32(mPacket.getInt(ICMP6_4_BYTE_LIFETIME_OFFSET + position)); builder.updateDnsslLifetime(lifetime);
break; break;
default: default:
// RFC4861 section 4.2 dictates we ignore unknown options for fowards // RFC4861 section 4.2 dictates we ignore unknown options for fowards
@@ -514,9 +519,7 @@ public class ApfFilter {
// Mark non-lifetime bytes since last lifetime. // Mark non-lifetime bytes since last lifetime.
addNonLifetime(lastNonLifetimeStart, 0, 0); addNonLifetime(lastNonLifetimeStart, 0, 0);
mMinLifetime = minLifetime(packet, length); mMinLifetime = minLifetime(packet, length);
// TODO: record per-option minimum lifetimes instead of last seen lifetimes mMetricsLog.log(builder.build());
mMetricsLog.log(new RaEvent(routerLifetime, prefixValidLifetime,
prefixPreferredLifetime, routeInfoLifetime, rdnssLifetime, dnsslLifetime));
} }
// Ignoring lifetimes (which may change) does {@code packet} match this RA? // Ignoring lifetimes (which may change) does {@code packet} match this RA?
@@ -1000,7 +1003,8 @@ public class ApfFilter {
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported); Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
return null; return null;
} }
return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback, multicastFilter); return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback,
multicastFilter, new IpConnectivityLog());
} }
public synchronized void shutdown() { public synchronized void shutdown() {

View File

@@ -26,14 +26,23 @@ import android.net.apf.ApfGenerator;
import android.net.apf.ApfGenerator.IllegalInstructionException; import android.net.apf.ApfGenerator.IllegalInstructionException;
import android.net.apf.ApfGenerator.Register; import android.net.apf.ApfGenerator.Register;
import android.net.ip.IpManager; import android.net.ip.IpManager;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.os.ConditionVariable; import android.os.ConditionVariable;
import android.os.Parcelable;
import android.system.ErrnoException; import android.system.ErrnoException;
import android.system.Os; import android.system.Os;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.LargeTest;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import java.io.File; import java.io.File;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@@ -43,6 +52,7 @@ import java.io.OutputStream;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List;
import libcore.io.IoUtils; import libcore.io.IoUtils;
import libcore.io.Streams; import libcore.io.Streams;
@@ -56,9 +66,12 @@ import libcore.io.Streams;
public class ApfTest extends AndroidTestCase { public class ApfTest extends AndroidTestCase {
private static final int TIMEOUT_MS = 500; private static final int TIMEOUT_MS = 500;
@Mock IpConnectivityLog mLog;
@Override @Override
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
MockitoAnnotations.initMocks(this);
// Load up native shared library containing APF interpreter exposed via JNI. // Load up native shared library containing APF interpreter exposed via JNI.
System.loadLibrary("servicestestsjni"); System.loadLibrary("servicestestsjni");
} }
@@ -70,6 +83,9 @@ public class ApfTest extends AndroidTestCase {
// least the minimum packet size. // least the minimum packet size.
private final static int MIN_PKT_SIZE = 15; private final static int MIN_PKT_SIZE = 15;
private final static boolean DROP_MULTICAST = true;
private final static boolean ALLOW_MULTICAST = false;
private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) { private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
assertEquals(expected, apfSimulate(program, packet, filterAge)); assertEquals(expected, apfSimulate(program, packet, filterAge));
} }
@@ -562,10 +578,10 @@ public class ApfTest extends AndroidTestCase {
public final static byte[] MOCK_MAC_ADDR = new byte[]{1,2,3,4,5,6}; public final static byte[] MOCK_MAC_ADDR = new byte[]{1,2,3,4,5,6};
private FileDescriptor mWriteSocket; private FileDescriptor mWriteSocket;
public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter) throws public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
Exception { IpConnectivityLog log) throws Exception {
super(new ApfCapabilities(2, 1000, ARPHRD_ETHER), NetworkInterface.getByName("lo"), super(new ApfCapabilities(2, 1000, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
ipManagerCallback, multicastFilter); ipManagerCallback, multicastFilter, log);
} }
// Pretend an RA packet has been received and show it to ApfFilter. // Pretend an RA packet has been received and show it to ApfFilter.
@@ -667,7 +683,7 @@ public class ApfTest extends AndroidTestCase {
@LargeTest @LargeTest
public void testApfFilterIPv4() throws Exception { public void testApfFilterIPv4() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
byte[] program = ipManagerCallback.getApfProgram(); byte[] program = ipManagerCallback.getApfProgram();
// Verify empty packet of 100 zero bytes is passed // Verify empty packet of 100 zero bytes is passed
@@ -699,7 +715,7 @@ public class ApfTest extends AndroidTestCase {
@LargeTest @LargeTest
public void testApfFilterIPv6() throws Exception { public void testApfFilterIPv6() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
byte[] program = ipManagerCallback.getApfProgram(); byte[] program = ipManagerCallback.getApfProgram();
// Verify empty IPv6 packet is passed // Verify empty IPv6 packet is passed
@@ -726,7 +742,7 @@ public class ApfTest extends AndroidTestCase {
@LargeTest @LargeTest
public void testApfFilterMulticast() throws Exception { public void testApfFilterMulticast() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
byte[] program = ipManagerCallback.getApfProgram(); byte[] program = ipManagerCallback.getApfProgram();
// Construct IPv4 and IPv6 multicast packets. // Construct IPv4 and IPv6 multicast packets.
@@ -772,7 +788,7 @@ public class ApfTest extends AndroidTestCase {
// Verify it can be initialized to on // Verify it can be initialized to on
ipManagerCallback.resetApfProgramWait(); ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown(); apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */); apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
program = ipManagerCallback.getApfProgram(); program = ipManagerCallback.getApfProgram();
assertDrop(program, bcastv4packet.array(), 0); assertDrop(program, bcastv4packet.array(), 0);
assertDrop(program, mcastv4packet.array(), 0); assertDrop(program, mcastv4packet.array(), 0);
@@ -804,7 +820,7 @@ public class ApfTest extends AndroidTestCase {
@LargeTest @LargeTest
public void testApfFilterArp() throws Exception { public void testApfFilterArp() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
byte[] program = ipManagerCallback.getApfProgram(); byte[] program = ipManagerCallback.getApfProgram();
// Verify initially ARP filter is off // Verify initially ARP filter is off
@@ -867,6 +883,35 @@ public class ApfTest extends AndroidTestCase {
verifyRaLifetime(ipManagerCallback, packet, lifetime); verifyRaLifetime(ipManagerCallback, packet, lifetime);
} }
private void verifyRaEvent(RaEvent expected) {
ArgumentCaptor<Parcelable> captor = ArgumentCaptor.forClass(Parcelable.class);
verify(mLog, atLeastOnce()).log(captor.capture());
RaEvent got = lastRaEvent(captor.getAllValues());
if (!raEventEquals(expected, got)) {
assertEquals(expected, got); // fail for printing an assertion error message.
}
}
private RaEvent lastRaEvent(List<Parcelable> events) {
RaEvent got = null;
for (Parcelable ev : events) {
if (ev instanceof RaEvent) {
got = (RaEvent) ev;
}
}
return got;
}
private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
return (ev1 != null) && (ev2 != null)
&& (ev1.routerLifetime == ev2.routerLifetime)
&& (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
&& (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
&& (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
&& (ev1.rdnssLifetime == ev2.rdnssLifetime)
&& (ev1.dnsslLifetime == ev2.dnsslLifetime);
}
private void assertInvalidRa(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback, private void assertInvalidRa(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
ByteBuffer packet) throws IOException, ErrnoException { ByteBuffer packet) throws IOException, ErrnoException {
ipManagerCallback.resetApfProgramWait(); ipManagerCallback.resetApfProgramWait();
@@ -877,7 +922,7 @@ public class ApfTest extends AndroidTestCase {
@LargeTest @LargeTest
public void testApfFilterRa() throws Exception { public void testApfFilterRa() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */); TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
byte[] program = ipManagerCallback.getApfProgram(); byte[] program = ipManagerCallback.getApfProgram();
// Verify RA is passed the first time // Verify RA is passed the first time
@@ -891,6 +936,7 @@ public class ApfTest extends AndroidTestCase {
assertPass(program, basePacket.array(), 0); assertPass(program, basePacket.array(), 0);
testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000); testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000);
verifyRaEvent(new RaEvent(1000, -1, -1, -1, -1, -1));
// Ensure zero-length options cause the packet to be silently skipped. // Ensure zero-length options cause the packet to be silently skipped.
// Do this before we test other packets. http://b/29586253 // Do this before we test other packets. http://b/29586253
@@ -916,6 +962,7 @@ public class ApfTest extends AndroidTestCase {
prefixOptionPacket.putInt( prefixOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET, 200); ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET, 200);
testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, 100); testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, 100);
verifyRaEvent(new RaEvent(1000, 200, 100, -1, -1, -1));
ByteBuffer rdnssOptionPacket = ByteBuffer.wrap( ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
@@ -926,6 +973,7 @@ public class ApfTest extends AndroidTestCase {
rdnssOptionPacket.putInt( rdnssOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 300); ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 300);
testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, 300); testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, 300);
verifyRaEvent(new RaEvent(1000, -1, -1, -1, 300, -1));
ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap( ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
@@ -936,6 +984,7 @@ public class ApfTest extends AndroidTestCase {
routeInfoOptionPacket.putInt( routeInfoOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 400); ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 400);
testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, 400); testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, 400);
verifyRaEvent(new RaEvent(1000, -1, -1, 400, -1, -1));
ByteBuffer dnsslOptionPacket = ByteBuffer.wrap( ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
@@ -948,6 +997,7 @@ public class ApfTest extends AndroidTestCase {
// Note that lifetime of 2000 will be ignored in favor of shorter // Note that lifetime of 2000 will be ignored in favor of shorter
// route lifetime of 1000. // route lifetime of 1000.
testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, 1000); testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, 1000);
verifyRaEvent(new RaEvent(1000, -1, -1, -1, -1, 2000));
// Verify that current program filters all five RAs: // Verify that current program filters all five RAs:
verifyRaLifetime(ipManagerCallback, basePacket, 1000); verifyRaLifetime(ipManagerCallback, basePacket, 1000);