summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/metrics/ApfProgramEvent.java27
-rw-r--r--core/java/android/net/metrics/ApfStats.java48
-rw-r--r--services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java27
-rw-r--r--services/net/java/android/net/apf/ApfFilter.java90
-rw-r--r--tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java9
-rw-r--r--tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java19
6 files changed, 139 insertions, 81 deletions
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index c2795a2ab956..ad4588f139f9 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -47,23 +47,19 @@ public final class ApfProgramEvent implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface Flags {}
- public final long lifetime; // Lifetime of the program in seconds
- public final int filteredRas; // Number of RAs filtered by the APF program
- public final int currentRas; // Total number of current RAs at generation time
- public final int programLength; // Length of the APF program in bytes
- public final int flags; // Bitfield compound of FLAG_* constants
-
- public ApfProgramEvent(
- long lifetime, int filteredRas, int currentRas, int programLength, @Flags int flags) {
- this.lifetime = lifetime;
- this.filteredRas = filteredRas;
- this.currentRas = currentRas;
- this.programLength = programLength;
- this.flags = flags;
+ public long lifetime; // Maximum computed lifetime of the program in seconds
+ public long actualLifetime; // Effective program lifetime in seconds
+ public int filteredRas; // Number of RAs filtered by the APF program
+ public int currentRas; // Total number of current RAs at generation time
+ public int programLength; // Length of the APF program in bytes
+ public int flags; // Bitfield compound of FLAG_* constants
+
+ public ApfProgramEvent() {
}
private ApfProgramEvent(Parcel in) {
this.lifetime = in.readLong();
+ this.actualLifetime = in.readLong();
this.filteredRas = in.readInt();
this.currentRas = in.readInt();
this.programLength = in.readInt();
@@ -73,6 +69,7 @@ public final class ApfProgramEvent implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeLong(lifetime);
+ out.writeLong(actualLifetime);
out.writeInt(filteredRas);
out.writeInt(currentRas);
out.writeInt(programLength);
@@ -87,8 +84,8 @@ public final class ApfProgramEvent implements Parcelable {
@Override
public String toString() {
String lifetimeString = (lifetime < Long.MAX_VALUE) ? lifetime + "s" : "forever";
- return String.format("ApfProgramEvent(%d/%d RAs %dB %s %s)",
- filteredRas, currentRas, programLength, lifetimeString, namesOf(flags));
+ return String.format("ApfProgramEvent(%d/%d RAs %dB %ds/%s %s)", filteredRas, currentRas,
+ programLength, actualLifetime, lifetimeString, namesOf(flags));
}
public static final Parcelable.Creator<ApfProgramEvent> CREATOR
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index f8d7fa9d2e8d..3b0dc7efc45e 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -25,25 +25,28 @@ import android.os.Parcelable;
*/
public final class ApfStats implements Parcelable {
- public final long durationMs; // time interval in milliseconds these stastistics covers
- public final int receivedRas; // number of received RAs
- public final int matchingRas; // number of received RAs matching a known RA
- public final int droppedRas; // number of received RAs ignored due to the MAX_RAS limit
- public final int zeroLifetimeRas; // number of received RAs with a minimum lifetime of 0
- public final int parseErrors; // number of received RAs that could not be parsed
- public final int programUpdates; // number of APF program updates
- public final int maxProgramSize; // maximum APF program size advertised by hardware
+ /** time interval in milliseconds these stastistics covers. */
+ public long durationMs;
+ /** number of received RAs. */
+ public int receivedRas;
+ /** number of received RAs matching a known RA. */
+ public int matchingRas;
+ /** number of received RAs ignored due to the MAX_RAS limit. */
+ public int droppedRas;
+ /** number of received RAs with a minimum lifetime of 0. */
+ public int zeroLifetimeRas;
+ /** number of received RAs that could not be parsed. */
+ public int parseErrors;
+ /** number of APF program updates from receiving RAs.. */
+ public int programUpdates;
+ /** total number of APF program updates. */
+ public int programUpdatesAll;
+ /** number of APF program updates from allowing multicast traffic. */
+ public int programUpdatesAllowingMulticast;
+ /** maximum APF program size advertised by hardware. */
+ public int maxProgramSize;
- public ApfStats(long durationMs, int receivedRas, int matchingRas, int droppedRas,
- int zeroLifetimeRas, int parseErrors, int programUpdates, int maxProgramSize) {
- this.durationMs = durationMs;
- this.receivedRas = receivedRas;
- this.matchingRas = matchingRas;
- this.droppedRas = droppedRas;
- this.zeroLifetimeRas = zeroLifetimeRas;
- this.parseErrors = parseErrors;
- this.programUpdates = programUpdates;
- this.maxProgramSize = maxProgramSize;
+ public ApfStats() {
}
private ApfStats(Parcel in) {
@@ -54,6 +57,8 @@ public final class ApfStats implements Parcelable {
this.zeroLifetimeRas = in.readInt();
this.parseErrors = in.readInt();
this.programUpdates = in.readInt();
+ this.programUpdatesAll = in.readInt();
+ this.programUpdatesAllowingMulticast = in.readInt();
this.maxProgramSize = in.readInt();
}
@@ -66,6 +71,8 @@ public final class ApfStats implements Parcelable {
out.writeInt(zeroLifetimeRas);
out.writeInt(parseErrors);
out.writeInt(programUpdates);
+ out.writeInt(programUpdatesAll);
+ out.writeInt(programUpdatesAllowingMulticast);
out.writeInt(maxProgramSize);
}
@@ -83,8 +90,9 @@ public final class ApfStats implements Parcelable {
.append(String.format("%d matching, ", matchingRas))
.append(String.format("%d dropped, ", droppedRas))
.append(String.format("%d zero lifetime, ", zeroLifetimeRas))
- .append(String.format("%d parse errors, ", parseErrors))
- .append(String.format("%d program updates})", programUpdates))
+ .append(String.format("%d parse errors}, ", parseErrors))
+ .append(String.format("updates: {all: %d, RAs: %d, allow multicast: %d})",
+ programUpdatesAll, programUpdates, programUpdatesAllowingMulticast))
.toString();
}
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index d5fa26c49251..81e891a90499 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -151,7 +151,8 @@ final public class IpConnectivityEventBuilder {
}
private static void setDnsEvent(IpConnectivityEvent out, DnsEvent in) {
- IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch = new IpConnectivityLogClass.DNSLookupBatch();
+ IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch =
+ new IpConnectivityLogClass.DNSLookupBatch();
dnsLookupBatch.networkId = netIdOf(in.netId);
dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
@@ -160,7 +161,8 @@ final public class IpConnectivityEventBuilder {
}
private static void setIpManagerEvent(IpConnectivityEvent out, IpManagerEvent in) {
- IpConnectivityLogClass.IpProvisioningEvent ipProvisioningEvent = new IpConnectivityLogClass.IpProvisioningEvent();
+ IpConnectivityLogClass.IpProvisioningEvent ipProvisioningEvent =
+ new IpConnectivityLogClass.IpProvisioningEvent();
ipProvisioningEvent.ifName = in.ifName;
ipProvisioningEvent.eventType = in.eventType;
ipProvisioningEvent.latencyMs = (int) in.durationMs;
@@ -168,14 +170,16 @@ final public class IpConnectivityEventBuilder {
}
private static void setIpReachabilityEvent(IpConnectivityEvent out, IpReachabilityEvent in) {
- IpConnectivityLogClass.IpReachabilityEvent ipReachabilityEvent = new IpConnectivityLogClass.IpReachabilityEvent();
+ IpConnectivityLogClass.IpReachabilityEvent ipReachabilityEvent =
+ new IpConnectivityLogClass.IpReachabilityEvent();
ipReachabilityEvent.ifName = in.ifName;
ipReachabilityEvent.eventType = in.eventType;
out.setIpReachabilityEvent(ipReachabilityEvent);
}
private static void setDefaultNetworkEvent(IpConnectivityEvent out, DefaultNetworkEvent in) {
- IpConnectivityLogClass.DefaultNetworkEvent defaultNetworkEvent = new IpConnectivityLogClass.DefaultNetworkEvent();
+ IpConnectivityLogClass.DefaultNetworkEvent defaultNetworkEvent =
+ new IpConnectivityLogClass.DefaultNetworkEvent();
defaultNetworkEvent.networkId = netIdOf(in.netId);
defaultNetworkEvent.previousNetworkId = netIdOf(in.prevNetId);
defaultNetworkEvent.transportTypes = in.transportTypes;
@@ -184,7 +188,8 @@ final public class IpConnectivityEventBuilder {
}
private static void setNetworkEvent(IpConnectivityEvent out, NetworkEvent in) {
- IpConnectivityLogClass.NetworkEvent networkEvent = new IpConnectivityLogClass.NetworkEvent();
+ IpConnectivityLogClass.NetworkEvent networkEvent =
+ new IpConnectivityLogClass.NetworkEvent();
networkEvent.networkId = netIdOf(in.netId);
networkEvent.eventType = in.eventType;
networkEvent.latencyMs = (int) in.durationMs;
@@ -192,7 +197,8 @@ final public class IpConnectivityEventBuilder {
}
private static void setValidationProbeEvent(IpConnectivityEvent out, ValidationProbeEvent in) {
- IpConnectivityLogClass.ValidationProbeEvent validationProbeEvent = new IpConnectivityLogClass.ValidationProbeEvent();
+ IpConnectivityLogClass.ValidationProbeEvent validationProbeEvent =
+ new IpConnectivityLogClass.ValidationProbeEvent();
validationProbeEvent.networkId = netIdOf(in.netId);
validationProbeEvent.latencyMs = (int) in.durationMs;
validationProbeEvent.probeType = in.probeType;
@@ -201,8 +207,10 @@ final public class IpConnectivityEventBuilder {
}
private static void setApfProgramEvent(IpConnectivityEvent out, ApfProgramEvent in) {
- IpConnectivityLogClass.ApfProgramEvent apfProgramEvent = new IpConnectivityLogClass.ApfProgramEvent();
+ IpConnectivityLogClass.ApfProgramEvent apfProgramEvent =
+ new IpConnectivityLogClass.ApfProgramEvent();
apfProgramEvent.lifetime = in.lifetime;
+ apfProgramEvent.effectiveLifetime = in.actualLifetime;
apfProgramEvent.filteredRas = in.filteredRas;
apfProgramEvent.currentRas = in.currentRas;
apfProgramEvent.programLength = in.programLength;
@@ -216,7 +224,8 @@ final public class IpConnectivityEventBuilder {
}
private static void setApfStats(IpConnectivityEvent out, ApfStats in) {
- IpConnectivityLogClass.ApfStatistics apfStatistics = new IpConnectivityLogClass.ApfStatistics();
+ IpConnectivityLogClass.ApfStatistics apfStatistics =
+ new IpConnectivityLogClass.ApfStatistics();
apfStatistics.durationMs = in.durationMs;
apfStatistics.receivedRas = in.receivedRas;
apfStatistics.matchingRas = in.matchingRas;
@@ -224,6 +233,8 @@ final public class IpConnectivityEventBuilder {
apfStatistics.zeroLifetimeRas = in.zeroLifetimeRas;
apfStatistics.parseErrors = in.parseErrors;
apfStatistics.programUpdates = in.programUpdates;
+ apfStatistics.programUpdatesAll = in.programUpdatesAll;
+ apfStatistics.programUpdatesAllowingMulticast = in.programUpdatesAllowingMulticast;
apfStatistics.maxProgramSize = in.maxProgramSize;
out.setApfStatistics(apfStatistics);
}
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 0a907496ebdd..a0a9310af28c 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -93,17 +93,10 @@ public class ApfFilter {
class ReceiveThread extends Thread {
private final byte[] mPacket = new byte[1514];
private final FileDescriptor mSocket;
- private volatile boolean mStopped;
-
- // Starting time of the RA receiver thread.
private final long mStart = SystemClock.elapsedRealtime();
+ private final ApfStats mStats = new ApfStats();
- private int mReceivedRas; // Number of received RAs
- private int mMatchingRas; // Number of received RAs matching a known RA
- private int mDroppedRas; // Number of received RAs ignored due to the MAX_RAS limit
- private int mParseErrors; // Number of received RAs that could not be parsed
- private int mZeroLifetimeRas; // Number of received RAs with a 0 lifetime
- private int mProgramUpdates; // Number of APF program updates triggered by receiving a RA
+ private volatile boolean mStopped;
public ReceiveThread(FileDescriptor socket) {
mSocket = socket;
@@ -134,35 +127,40 @@ public class ApfFilter {
}
private void updateStats(ProcessRaResult result) {
- mReceivedRas++;
+ mStats.receivedRas++;
switch(result) {
case MATCH:
- mMatchingRas++;
+ mStats.matchingRas++;
return;
case DROPPED:
- mDroppedRas++;
+ mStats.droppedRas++;
return;
case PARSE_ERROR:
- mParseErrors++;
+ mStats.parseErrors++;
return;
case ZERO_LIFETIME:
- mZeroLifetimeRas++;
+ mStats.zeroLifetimeRas++;
return;
case UPDATE_EXPIRY:
- mMatchingRas++;
- mProgramUpdates++;
+ mStats.matchingRas++;
+ mStats.programUpdates++;
return;
case UPDATE_NEW_RA:
- mProgramUpdates++;
+ mStats.programUpdates++;
return;
}
}
private void logStats() {
- long durationMs = SystemClock.elapsedRealtime() - mStart;
- int maxSize = mApfCapabilities.maximumApfProgramSize;
- mMetricsLog.log(new ApfStats(durationMs, mReceivedRas, mMatchingRas, mDroppedRas,
- mZeroLifetimeRas, mParseErrors, mProgramUpdates, maxSize));
+ final long nowMs = SystemClock.elapsedRealtime();
+ synchronized (this) {
+ mStats.durationMs = nowMs - mStart;
+ mStats.maxProgramSize = mApfCapabilities.maximumApfProgramSize;
+ mStats.programUpdatesAll = mNumProgramUpdates;
+ mStats.programUpdatesAllowingMulticast = mNumProgramUpdatesAllowingMulticast;
+ mMetricsLog.log(mStats);
+ logApfProgramEventLocked(nowMs / DateUtils.SECOND_IN_MILLIS);
+ }
}
}
@@ -218,6 +216,8 @@ public class ApfFilter {
4, // Protocol size: 4
};
private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
+ // Do not log ApfProgramEvents whose actual lifetimes was less than this.
+ private static final int APF_PROGRAM_EVENT_LIFETIME_THRESHOLD = 2;
private final ApfCapabilities mApfCapabilities;
private final IpManager.Callback mIpManagerCallback;
@@ -247,6 +247,7 @@ public class ApfFilter {
mMulticastFilter = multicastFilter;
mMetricsLog = log;
+ // TODO: ApfFilter should not generate programs until IpManager sends provisioning success.
maybeStartFilter();
}
@@ -661,14 +662,19 @@ public class ApfFilter {
// How long should the last installed filter program live for? In seconds.
@GuardedBy("this")
private long mLastInstalledProgramMinLifetime;
+ @GuardedBy("this")
+ private ApfProgramEvent mLastInstallEvent;
// For debugging only. The last program installed.
@GuardedBy("this")
private byte[] mLastInstalledProgram;
- // For debugging only. How many times the program was updated since we started.
+ // How many times the program was updated since we started.
+ @GuardedBy("this")
+ private int mNumProgramUpdates = 0;
+ // How many times the program was updated since we started for allowing multicast traffic.
@GuardedBy("this")
- private int mNumProgramUpdates;
+ private int mNumProgramUpdatesAllowingMulticast = 0;
/**
* Generate filter code to process ARP packets. Execution of this code ends in either the
@@ -947,7 +953,8 @@ public class ApfFilter {
Log.e(TAG, "Failed to generate APF program.", e);
return;
}
- mLastTimeInstalledProgram = currentTimeSeconds();
+ final long now = currentTimeSeconds();
+ mLastTimeInstalledProgram = now;
mLastInstalledProgramMinLifetime = programMinLifetime;
mLastInstalledProgram = program;
mNumProgramUpdates++;
@@ -956,9 +963,26 @@ public class ApfFilter {
hexDump("Installing filter: ", program, program.length);
}
mIpManagerCallback.installPacketFilter(program);
- int flags = ApfProgramEvent.flagsFor(mIPv4Address != null, mMulticastFilter);
- mMetricsLog.log(new ApfProgramEvent(
- programMinLifetime, rasToFilter.size(), mRas.size(), program.length, flags));
+ logApfProgramEventLocked(now);
+ mLastInstallEvent = new ApfProgramEvent();
+ mLastInstallEvent.lifetime = programMinLifetime;
+ mLastInstallEvent.filteredRas = rasToFilter.size();
+ mLastInstallEvent.currentRas = mRas.size();
+ mLastInstallEvent.programLength = program.length;
+ mLastInstallEvent.flags = ApfProgramEvent.flagsFor(mIPv4Address != null, mMulticastFilter);
+ }
+
+ private void logApfProgramEventLocked(long now) {
+ if (mLastInstallEvent == null) {
+ return;
+ }
+ ApfProgramEvent ev = mLastInstallEvent;
+ mLastInstallEvent = null;
+ ev.actualLifetime = now - mLastTimeInstalledProgram;
+ if (ev.actualLifetime < APF_PROGRAM_EVENT_LIFETIME_THRESHOLD) {
+ return;
+ }
+ mMetricsLog.log(ev);
}
/**
@@ -1078,11 +1102,15 @@ public class ApfFilter {
mRas.clear();
}
- public synchronized void setMulticastFilter(boolean enabled) {
- if (mMulticastFilter != enabled) {
- mMulticastFilter = enabled;
- installNewProgramLocked();
+ public synchronized void setMulticastFilter(boolean isEnabled) {
+ if (mMulticastFilter == isEnabled) {
+ return;
+ }
+ mMulticastFilter = isEnabled;
+ if (!isEnabled) {
+ mNumProgramUpdatesAllowingMulticast++;
}
+ installNewProgramLocked();
}
/** Find the single IPv4 LinkAddress if there is one, otherwise return null. */
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 11105d6de75b..48861bde77b3 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -304,6 +304,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(ApfProgramEvent.class),
aLong(200),
+ aLong(18),
anInt(7),
anInt(9),
anInt(2048),
@@ -320,7 +321,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" apf_program_event <",
" current_ras: 9",
" drop_multicast: true",
- " effective_lifetime: 0",
+ " effective_lifetime: 18",
" filtered_ras: 7",
" has_ipv4_addr: true",
" lifetime: 200",
@@ -343,6 +344,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
anInt(1),
anInt(2),
anInt(4),
+ anInt(7),
+ anInt(3),
anInt(2048));
String want = joinLines(
@@ -360,8 +363,8 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" max_program_size: 2048",
" parse_errors: 2",
" program_updates: 4",
- " program_updates_all: 0",
- " program_updates_allowing_multicast: 0",
+ " program_updates_all: 7",
+ " program_updates_allowing_multicast: 3",
" received_ras: 10",
" zero_lifetime_ras: 1",
" >",
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 1f7c5f418d74..58511b927cfb 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -118,7 +118,7 @@ public class IpConnectivityMetricsTest extends TestCase {
@SmallTest
public void testRateLimiting() {
final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
- final ApfProgramEvent ev = new ApfProgramEvent(0, 0, 0, 0, 0);
+ final ApfProgramEvent ev = new ApfProgramEvent();
final long fakeTimestamp = 1;
int attempt = 100; // More than burst quota, but less than buffer size.
@@ -142,13 +142,24 @@ public class IpConnectivityMetricsTest extends TestCase {
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
+ ApfStats apfStats = new ApfStats();
+ apfStats.durationMs = 45000;
+ apfStats.receivedRas = 10;
+ apfStats.matchingRas = 2;
+ apfStats.droppedRas = 2;
+ apfStats.parseErrors = 2;
+ apfStats.zeroLifetimeRas = 1;
+ apfStats.programUpdates = 4;
+ apfStats.programUpdatesAll = 7;
+ apfStats.programUpdatesAllowingMulticast = 3;
+ apfStats.maxProgramSize = 2048;
Parcelable[] events = {
new IpReachabilityEvent("wlan0", IpReachabilityEvent.NUD_FAILED),
new DhcpClientEvent("wlan0", "SomeState", 192),
new DefaultNetworkEvent(102, new int[]{1,2,3}, 101, true, false),
new IpManagerEvent("wlan0", IpManagerEvent.PROVISIONING_OK, 5678),
new ValidationProbeEvent(120, 40730, ValidationProbeEvent.PROBE_HTTP, 204),
- new ApfStats(45000, 10, 2, 2, 1, 2, 4, 2048),
+ apfStats,
new RaEvent(2000, 400, 300, -1, 1000, -1)
};
@@ -240,8 +251,8 @@ public class IpConnectivityMetricsTest extends TestCase {
" max_program_size: 2048",
" parse_errors: 2",
" program_updates: 4",
- " program_updates_all: 0",
- " program_updates_allowing_multicast: 0",
+ " program_updates_all: 7",
+ " program_updates_allowing_multicast: 3",
" received_ras: 10",
" zero_lifetime_ras: 1",
" >",