diff options
| author | Rubin Xu <rubinxu@google.com> | 2020-06-11 16:40:13 +0100 |
|---|---|---|
| committer | Rubin Xu <rubinxu@google.com> | 2020-06-17 12:01:41 +0100 |
| commit | c3dec3448d047efc50f6526addbb2233f1f2ff27 (patch) | |
| tree | 0f8d6a998938f1689aec4ba3aad28bb2a5ab3505 /core/java | |
| parent | 85cf423804e34536dc2c36e3043d78a0e829f47d (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.java | 43 |
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); } /** |
