Merge "Treat RouteInfo with different interfaces as different routes" am: d77e15c125
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1331916 Change-Id: Ibe919ea7c2096094fdb48fc91881d9f19678ac50
This commit is contained in:
@@ -26,7 +26,6 @@ import android.net.util.NetUtils;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
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},
|
* A helper class that contains the destination, the gateway and the interface in a
|
||||||
* used by {@link ConnectivityService#updateRoutes} or
|
* {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or
|
||||||
* {@link LinkProperties#addRoute} to calculate the list to be updated.
|
* {@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
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static class RouteKey extends Pair<IpPrefix, InetAddress> {
|
public static class RouteKey {
|
||||||
RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway) {
|
@NonNull private final IpPrefix mDestination;
|
||||||
super(destination, gateway);
|
@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
|
@NonNull
|
||||||
public RouteKey getRouteKey() {
|
public RouteKey getRouteKey() {
|
||||||
return new RouteKey(mDestination, mGateway);
|
return new RouteKey(mDestination, mGateway, mInterface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
|
import static android.net.RouteInfo.RTN_THROW;
|
||||||
|
import static android.net.RouteInfo.RTN_UNICAST;
|
||||||
import static android.net.RouteInfo.RTN_UNREACHABLE;
|
import static android.net.RouteInfo.RTN_UNREACHABLE;
|
||||||
|
|
||||||
import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
|
import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
|
||||||
@@ -1282,4 +1284,20 @@ public class LinkPropertiesTest {
|
|||||||
assertTrue(lp.hasIpv6UnreachableDefaultRoute());
|
assertTrue(lp.hasIpv6UnreachableDefaultRoute());
|
||||||
assertFalse(lp.hasIpv4UnreachableDefaultRoute());
|
assertFalse(lp.hasIpv4UnreachableDefaultRoute());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test @IgnoreUpTo(Build.VERSION_CODES.Q)
|
||||||
|
public void testRouteAddWithSameKey() throws Exception {
|
||||||
|
LinkProperties lp = new LinkProperties();
|
||||||
|
lp.setInterfaceName("wlan0");
|
||||||
|
final IpPrefix v6 = new IpPrefix("64:ff9b::/96");
|
||||||
|
lp.addRoute(new RouteInfo(v6, address("fe80::1"), "wlan0", RTN_UNICAST, 1280));
|
||||||
|
assertEquals(1, lp.getRoutes().size());
|
||||||
|
lp.addRoute(new RouteInfo(v6, address("fe80::1"), "wlan0", RTN_UNICAST, 1500));
|
||||||
|
assertEquals(1, lp.getRoutes().size());
|
||||||
|
final IpPrefix v4 = new IpPrefix("192.0.2.128/25");
|
||||||
|
lp.addRoute(new RouteInfo(v4, address("192.0.2.1"), "wlan0", RTN_UNICAST, 1460));
|
||||||
|
assertEquals(2, lp.getRoutes().size());
|
||||||
|
lp.addRoute(new RouteInfo(v4, address("192.0.2.1"), "wlan0", RTN_THROW, 1460));
|
||||||
|
assertEquals(2, lp.getRoutes().size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
@@ -56,7 +57,7 @@ public class RouteInfoTest {
|
|||||||
private static final int INVALID_ROUTE_TYPE = -1;
|
private static final int INVALID_ROUTE_TYPE = -1;
|
||||||
|
|
||||||
private InetAddress Address(String addr) {
|
private InetAddress Address(String addr) {
|
||||||
return InetAddress.parseNumericAddress(addr);
|
return InetAddresses.parseNumericAddress(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IpPrefix Prefix(String prefix) {
|
private IpPrefix Prefix(String prefix) {
|
||||||
@@ -391,4 +392,43 @@ public class RouteInfoTest {
|
|||||||
r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0");
|
r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0");
|
||||||
assertEquals(0, r.getMtu());
|
assertEquals(0, r.getMtu());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test @IgnoreUpTo(Build.VERSION_CODES.Q)
|
||||||
|
public void testRouteKey() {
|
||||||
|
RouteInfo.RouteKey k1, k2;
|
||||||
|
// Only prefix, null gateway and null interface
|
||||||
|
k1 = new RouteInfo(Prefix("2001:db8::/128"), null).getRouteKey();
|
||||||
|
k2 = new RouteInfo(Prefix("2001:db8::/128"), null).getRouteKey();
|
||||||
|
assertEquals(k1, k2);
|
||||||
|
assertEquals(k1.hashCode(), k2.hashCode());
|
||||||
|
|
||||||
|
// With prefix, gateway and interface. Type and MTU does not affect RouteKey equality
|
||||||
|
k1 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0",
|
||||||
|
RTN_UNREACHABLE, 1450).getRouteKey();
|
||||||
|
k2 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0",
|
||||||
|
RouteInfo.RTN_UNICAST, 1400).getRouteKey();
|
||||||
|
assertEquals(k1, k2);
|
||||||
|
assertEquals(k1.hashCode(), k2.hashCode());
|
||||||
|
|
||||||
|
// Different scope IDs are ignored by the kernel, so we consider them equal here too.
|
||||||
|
k1 = new RouteInfo(Prefix("2001:db8::/64"), Address("fe80::1%1"), "wlan0").getRouteKey();
|
||||||
|
k2 = new RouteInfo(Prefix("2001:db8::/64"), Address("fe80::1%2"), "wlan0").getRouteKey();
|
||||||
|
assertEquals(k1, k2);
|
||||||
|
assertEquals(k1.hashCode(), k2.hashCode());
|
||||||
|
|
||||||
|
// Different prefix
|
||||||
|
k1 = new RouteInfo(Prefix("192.0.2.0/24"), null).getRouteKey();
|
||||||
|
k2 = new RouteInfo(Prefix("192.0.3.0/24"), null).getRouteKey();
|
||||||
|
assertNotEquals(k1, k2);
|
||||||
|
|
||||||
|
// Different gateway
|
||||||
|
k1 = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::1"), null).getRouteKey();
|
||||||
|
k2 = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::2"), null).getRouteKey();
|
||||||
|
assertNotEquals(k1, k2);
|
||||||
|
|
||||||
|
// Different interface
|
||||||
|
k1 = new RouteInfo(Prefix("ff02::1/128"), null, "tun0").getRouteKey();
|
||||||
|
k2 = new RouteInfo(Prefix("ff02::1/128"), null, "tun1").getRouteKey();
|
||||||
|
assertNotEquals(k1, k2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user