diff options
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", " >", |