summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorRubin Xu <rubinxu@google.com>2020-06-11 16:40:13 +0100
committerRubin Xu <rubinxu@google.com>2020-06-17 12:01:41 +0100
commitc3dec3448d047efc50f6526addbb2233f1f2ff27 (patch)
tree0f8d6a998938f1689aec4ba3aad28bb2a5ab3505 /core/java
parent85cf423804e34536dc2c36e3043d78a0e829f47d (diff)
Treat RouteInfo with different interfaces as different routes
On Android different interfaces usually use different routing tables. As a result, a change in interface should not be treated as route update, but rather a remove and an add. This change fixes a bug in VPN seamless handover where routes failed to be updated when a new tunnel interface replaces the existing one within the same network. Bug: 158696878 Test: atest com.android.cts.net.HostsideVpnTests Test: atest NetworkStackTests Test: atest CtsNetTestCases Test: atest FrameworksNetTests Change-Id: I57987233d42a0253eaee2e1ca5f28728c2354620
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/net/RouteInfo.java43
1 files changed, 36 insertions, 7 deletions
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index e550f85e6b9a..98760761736d 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -26,7 +26,6 @@ import android.net.util.NetUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Pair;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -554,15 +553,45 @@ public final class RouteInfo implements Parcelable {
}
/**
- * A helper class that contains the destination and the gateway in a {@code RouteInfo},
- * used by {@link ConnectivityService#updateRoutes} or
+ * A helper class that contains the destination, the gateway and the interface in a
+ * {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or
* {@link LinkProperties#addRoute} to calculate the list to be updated.
+ * {@code RouteInfo} objects with different interfaces are treated as different routes because
+ * *usually* on Android different interfaces use different routing tables, and moving a route
+ * to a new routing table never constitutes an update, but is always a remove and an add.
*
* @hide
*/
- public static class RouteKey extends Pair<IpPrefix, InetAddress> {
- RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway) {
- super(destination, gateway);
+ public static class RouteKey {
+ @NonNull private final IpPrefix mDestination;
+ @Nullable private final InetAddress mGateway;
+ @Nullable private final String mInterface;
+
+ RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway,
+ @Nullable String iface) {
+ mDestination = destination;
+ mGateway = gateway;
+ mInterface = iface;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RouteKey)) {
+ return false;
+ }
+ RouteKey p = (RouteKey) o;
+ // No need to do anything special for scoped addresses. Inet6Address#equals does not
+ // consider the scope ID, but the netd route IPCs (e.g., INetd#networkAddRouteParcel)
+ // and the kernel ignore scoped addresses both in the prefix and in the nexthop and only
+ // look at RTA_OIF.
+ return Objects.equals(p.mDestination, mDestination)
+ && Objects.equals(p.mGateway, mGateway)
+ && Objects.equals(p.mInterface, mInterface);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDestination, mGateway, mInterface);
}
}
@@ -574,7 +603,7 @@ public final class RouteInfo implements Parcelable {
*/
@NonNull
public RouteKey getRouteKey() {
- return new RouteKey(mDestination, mGateway);
+ return new RouteKey(mDestination, mGateway, mInterface);
}
/**