summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/core/java/com/android/server/connectivity/NetworkDiagnostics.java')
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkDiagnostics.java56
1 files changed, 51 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index aca6991..5fd39c0 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -18,6 +18,7 @@ package com.android.server.connectivity;
import static android.system.OsConstants.*;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkUtils;
@@ -27,6 +28,7 @@ import android.system.ErrnoException;
import android.system.Os;
import android.system.StructTimeval;
import android.text.TextUtils;
+import android.util.Pair;
import com.android.internal.util.IndentingPrintWriter;
@@ -149,6 +151,8 @@ public class NetworkDiagnostics {
}
private final Map<InetAddress, Measurement> mIcmpChecks = new HashMap<>();
+ private final Map<Pair<InetAddress, InetAddress>, Measurement> mExplicitSourceIcmpChecks =
+ new HashMap<>();
private final Map<InetAddress, Measurement> mDnsUdpChecks = new HashMap<>();
private final String mDescription;
@@ -178,7 +182,11 @@ public class NetworkDiagnostics {
for (RouteInfo route : mLinkProperties.getRoutes()) {
if (route.hasGateway()) {
- prepareIcmpMeasurement(route.getGateway());
+ InetAddress gateway = route.getGateway();
+ prepareIcmpMeasurement(gateway);
+ if (route.isIPv6Default()) {
+ prepareExplicitSourceIcmpMeasurements(gateway);
+ }
}
}
for (InetAddress nameserver : mLinkProperties.getDnsServers()) {
@@ -213,6 +221,20 @@ public class NetworkDiagnostics {
}
}
+ private void prepareExplicitSourceIcmpMeasurements(InetAddress target) {
+ for (LinkAddress l : mLinkProperties.getLinkAddresses()) {
+ InetAddress source = l.getAddress();
+ if (source instanceof Inet6Address && l.isGlobalPreferred()) {
+ Pair<InetAddress, InetAddress> srcTarget = new Pair<>(source, target);
+ if (!mExplicitSourceIcmpChecks.containsKey(srcTarget)) {
+ Measurement measurement = new Measurement();
+ measurement.thread = new Thread(new IcmpCheck(source, target, measurement));
+ mExplicitSourceIcmpChecks.put(srcTarget, measurement);
+ }
+ }
+ }
+ }
+
private void prepareDnsMeasurement(InetAddress target) {
if (!mDnsUdpChecks.containsKey(target)) {
Measurement measurement = new Measurement();
@@ -222,13 +244,16 @@ public class NetworkDiagnostics {
}
private int totalMeasurementCount() {
- return mIcmpChecks.size() + mDnsUdpChecks.size();
+ return mIcmpChecks.size() + mExplicitSourceIcmpChecks.size() + mDnsUdpChecks.size();
}
private void startMeasurements() {
for (Measurement measurement : mIcmpChecks.values()) {
measurement.thread.start();
}
+ for (Measurement measurement : mExplicitSourceIcmpChecks.values()) {
+ measurement.thread.start();
+ }
for (Measurement measurement : mDnsUdpChecks.values()) {
measurement.thread.start();
}
@@ -261,6 +286,10 @@ public class NetworkDiagnostics {
pw.println(entry.getValue().toString());
}
}
+ for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
+ mExplicitSourceIcmpChecks.entrySet()) {
+ pw.println(entry.getValue().toString());
+ }
for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
if (entry.getKey() instanceof Inet4Address) {
pw.println(entry.getValue().toString());
@@ -276,13 +305,15 @@ public class NetworkDiagnostics {
private class SimpleSocketCheck implements Closeable {
+ protected final InetAddress mSource; // Usually null.
protected final InetAddress mTarget;
protected final int mAddressFamily;
protected final Measurement mMeasurement;
protected FileDescriptor mFileDescriptor;
protected SocketAddress mSocketAddress;
- protected SimpleSocketCheck(InetAddress target, Measurement measurement) {
+ protected SimpleSocketCheck(
+ InetAddress source, InetAddress target, Measurement measurement) {
mMeasurement = measurement;
if (target instanceof Inet6Address) {
@@ -301,6 +332,14 @@ public class NetworkDiagnostics {
mTarget = target;
mAddressFamily = AF_INET;
}
+
+ // We don't need to check the scope ID here because we currently only do explicit-source
+ // measurements from global IPv6 addresses.
+ mSource = source;
+ }
+
+ protected SimpleSocketCheck(InetAddress target, Measurement measurement) {
+ this(null, target, measurement);
}
protected void setupSocket(
@@ -314,6 +353,9 @@ public class NetworkDiagnostics {
SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(readTimeout));
// TODO: Use IP_RECVERR/IPV6_RECVERR, pending OsContants availability.
mNetwork.bindSocket(mFileDescriptor);
+ if (mSource != null) {
+ Os.bind(mFileDescriptor, mSource, 0);
+ }
Os.connect(mFileDescriptor, mTarget, dstPort);
mSocketAddress = Os.getsockname(mFileDescriptor);
}
@@ -343,8 +385,8 @@ public class NetworkDiagnostics {
private final int mProtocol;
private final int mIcmpType;
- public IcmpCheck(InetAddress target, Measurement measurement) {
- super(target, measurement);
+ public IcmpCheck(InetAddress source, InetAddress target, Measurement measurement) {
+ super(source, target, measurement);
if (mAddressFamily == AF_INET6) {
mProtocol = IPPROTO_ICMPV6;
@@ -359,6 +401,10 @@ public class NetworkDiagnostics {
mMeasurement.description += " dst{" + mTarget.getHostAddress() + "}";
}
+ public IcmpCheck(InetAddress target, Measurement measurement) {
+ this(null, target, measurement);
+ }
+
@Override
public void run() {
// Check if this measurement has already failed during setup.