summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt12
-rw-r--r--core/java/android/net/metrics/RaEvent.java95
-rw-r--r--services/net/java/android/net/apf/ApfFilter.java77
3 files changed, 161 insertions, 23 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 41ca0e684b29..769f8678f608 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -26153,6 +26153,18 @@ package android.net.metrics {
field public final int netId;
}
+ public final class RaEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.metrics.RaEvent> CREATOR;
+ field public final long dnsslLifetime;
+ field public final long prefixPreferredLifetime;
+ field public final long prefixValidLifetime;
+ field public final long rdnssLifetime;
+ field public final long routeInfoLifetime;
+ field public final long routerLifetime;
+ }
+
public final class ValidationProbeEvent implements android.os.Parcelable {
method public int describeContents();
method public static void logEvent(int, long, int, int);
diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java
new file mode 100644
index 000000000000..69013c0de637
--- /dev/null
+++ b/core/java/android/net/metrics/RaEvent.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * An event logged when the APF packet socket receives an RA packet.
+ * {@hide}
+ */
+@SystemApi
+public final class RaEvent implements Parcelable {
+
+ // 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;
+ public final long routerLifetime;
+ public final long prefixValidLifetime;
+ public final long prefixPreferredLifetime;
+ public final long routeInfoLifetime;
+ public final long rdnssLifetime;
+ public final long dnsslLifetime;
+
+ /** {@hide} */
+ public RaEvent(long routerLifetime, long prefixValidLifetime, long prefixPreferredLifetime,
+ long routeInfoLifetime, long rdnssLifetime, long dnsslLifetime) {
+ this.routerLifetime = routerLifetime;
+ this.prefixValidLifetime = prefixValidLifetime;
+ this.prefixPreferredLifetime = prefixPreferredLifetime;
+ this.routeInfoLifetime = routeInfoLifetime;
+ this.rdnssLifetime = rdnssLifetime;
+ this.dnsslLifetime = dnsslLifetime;
+ }
+
+ private RaEvent(Parcel in) {
+ routerLifetime = in.readLong();
+ prefixValidLifetime = in.readLong();
+ prefixPreferredLifetime = in.readLong();
+ routeInfoLifetime = in.readLong();
+ rdnssLifetime = in.readLong();
+ dnsslLifetime = in.readLong();
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeLong(routerLifetime);
+ out.writeLong(prefixValidLifetime);
+ out.writeLong(prefixPreferredLifetime);
+ out.writeLong(routeInfoLifetime);
+ out.writeLong(rdnssLifetime);
+ out.writeLong(dnsslLifetime);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder("RaEvent(lifetimes: ")
+ .append(String.format("router=%ds, ", routerLifetime))
+ .append(String.format("prefix_valid=%ds, ", prefixValidLifetime))
+ .append(String.format("prefix_preferred=%ds, ", prefixPreferredLifetime))
+ .append(String.format("route_info=%ds, ", routeInfoLifetime))
+ .append(String.format("rdnss=%ds, ", rdnssLifetime))
+ .append(String.format("dnssl=%ds)", dnsslLifetime))
+ .toString();
+ }
+
+ public static final Parcelable.Creator<RaEvent> CREATOR = new Parcelable.Creator<RaEvent>() {
+ public RaEvent createFromParcel(Parcel in) {
+ return new RaEvent(in);
+ }
+
+ public RaEvent[] newArray(int size) {
+ return new RaEvent[size];
+ }
+ };
+}
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 6d1a4eb40021..0ef9d7abaa38 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -28,6 +28,7 @@ import android.net.ip.IpManager;
import android.net.metrics.ApfProgramEvent;
import android.net.metrics.ApfStats;
import android.net.metrics.IpConnectivityLog;
+import android.net.metrics.RaEvent;
import android.system.ErrnoException;
import android.system.Os;
import android.system.PacketSocketAddress;
@@ -357,7 +358,7 @@ public class ApfFilter {
}
// Can't be static because it's in a non-static inner class.
- // TODO: Make this final once RA is its own class.
+ // TODO: Make this static once RA is its own class.
private int uint8(byte b) {
return b & 0xff;
}
@@ -366,8 +367,8 @@ public class ApfFilter {
return s & 0xffff;
}
- private long uint32(int s) {
- return s & 0xffffffff;
+ private long uint32(int i) {
+ return i & 0xffffffffL;
}
private void prefixOptionToString(StringBuffer sb, int offset) {
@@ -427,6 +428,11 @@ public class ApfFilter {
return lifetimeOffset + lifetimeLength;
}
+ private int addNonLifetimeU32(int lastNonLifetimeStart) {
+ return addNonLifetime(lastNonLifetimeStart,
+ ICMP6_4_BYTE_LIFETIME_OFFSET, ICMP6_4_BYTE_LIFETIME_LEN);
+ }
+
// Note that this parses RA and may throw IllegalArgumentException (from
// Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
// (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
@@ -446,11 +452,20 @@ public class ApfFilter {
ICMP6_RA_ROUTER_LIFETIME_OFFSET,
ICMP6_RA_ROUTER_LIFETIME_LEN);
+ 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.
mPacket.position(ICMP6_RA_OPTION_OFFSET);
while (mPacket.hasRemaining()) {
- int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
- int optionLength = (((int)mPacket.get(mPacket.position() + 1)) & 0xff) * 8;
+ final int position = mPacket.position();
+ final int optionType = uint8(mPacket.get(position));
+ final int optionLength = uint8(mPacket.get(position + 1)) * 8;
switch (optionType) {
case ICMP6_PREFIX_OPTION_TYPE:
// Parse valid lifetime
@@ -461,19 +476,29 @@ public class ApfFilter {
lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN);
- mPrefixOptionOffsets.add(mPacket.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;
- // These three options have the same lifetime offset and size, so process
- // together:
+ // These three options have the same lifetime offset and size, and
+ // are processed with the same specialized addNonLifetime4B:
case ICMP6_RDNSS_OPTION_TYPE:
- mRdnssOptionOffsets.add(mPacket.position());
- // Fall through.
+ mRdnssOptionOffsets.add(position);
+ lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
+ rdnssLifetime =
+ uint32(mPacket.getInt(ICMP6_4_BYTE_LIFETIME_OFFSET + position));
+ break;
case ICMP6_ROUTE_INFO_OPTION_TYPE:
+ lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
+ routeInfoLifetime =
+ uint32(mPacket.getInt(ICMP6_4_BYTE_LIFETIME_OFFSET + position));
+ break;
case ICMP6_DNSSL_OPTION_TYPE:
- // Parse lifetime
- lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
- ICMP6_4_BYTE_LIFETIME_OFFSET,
- ICMP6_4_BYTE_LIFETIME_LEN);
+ lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
+ dnsslLifetime =
+ uint32(mPacket.getInt(ICMP6_4_BYTE_LIFETIME_OFFSET + position));
break;
default:
// RFC4861 section 4.2 dictates we ignore unknown options for fowards
@@ -484,11 +509,14 @@ public class ApfFilter {
throw new IllegalArgumentException(String.format(
"Invalid option length opt=%d len=%d", optionType, optionLength));
}
- mPacket.position(mPacket.position() + optionLength);
+ mPacket.position(position + optionLength);
}
// Mark non-lifetime bytes since last lifetime.
addNonLifetime(lastNonLifetimeStart, 0, 0);
mMinLifetime = minLifetime(packet, length);
+ // TODO: record per-option minimum lifetimes instead of last seen lifetimes
+ mMetricsLog.log(new RaEvent(routerLifetime, prefixValidLifetime,
+ prefixPreferredLifetime, routeInfoLifetime, rdnssLifetime, dnsslLifetime));
}
// Ignoring lifetimes (which may change) does {@code packet} match this RA?
@@ -517,16 +545,19 @@ public class ApfFilter {
continue;
}
- int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
- long val;
+ final int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
+ final long optionLifetime;
switch (lifetimeLength) {
- case 2: val = byteBuffer.getShort(offset); break;
- case 4: val = byteBuffer.getInt(offset); break;
- default: throw new IllegalStateException("bogus lifetime size " + length);
+ case 2:
+ optionLifetime = uint16(byteBuffer.getShort(offset));
+ break;
+ case 4:
+ optionLifetime = uint32(byteBuffer.getInt(offset));
+ break;
+ default:
+ throw new IllegalStateException("bogus lifetime size " + lifetimeLength);
}
- // Mask to size, converting signed to unsigned
- val &= (1L << (lifetimeLength * 8)) - 1;
- minLifetime = Math.min(minLifetime, val);
+ minLifetime = Math.min(minLifetime, optionLifetime);
}
return minLifetime;
}