Merge \"IpConn metrics: correctly read RA lifetimes\" into nyc-mr1-dev
am: 54756fdfd9
Change-Id: Iabf3cfa4b6aaf5a1fbda6f169a65a1c7c117fd32
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
@@ -417,7 +426,7 @@ public class ApfFilter {
|
|||||||
* @param lifetimeOffset offset from mPacket.position() to the next lifetime data.
|
* @param lifetimeOffset offset from mPacket.position() to the next lifetime data.
|
||||||
* @param lifetimeLength length of the next lifetime data.
|
* @param lifetimeLength length of the next lifetime data.
|
||||||
* @return offset within packet of where the next binary range of data not including
|
* @return offset within packet of where the next binary range of data not including
|
||||||
* a lifetime. This can be passed into the next invocation of this function
|
* a lifetime. This can be passed into the next invocation of this function
|
||||||
* via {@code lastNonLifetimeStart}.
|
* via {@code lastNonLifetimeStart}.
|
||||||
*/
|
*/
|
||||||
private int addNonLifetime(int lastNonLifetimeStart, int lifetimeOffset,
|
private int addNonLifetime(int lastNonLifetimeStart, int lifetimeOffset,
|
||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user