Track NAT64 in the framework and start clatd iff NAT64 detected
Currently, both netd and clatd do NAT64 prefix detection, and we start clatd on all IPv6-only networks regardless of whether netd has detected a NAT64 prefix or not. Instead, track the NAT64 prefix in the framework, and only start clatd if the prefix is detected. This will allow us to remove DNS64 detection in clatd, and pass the NAT64 prefix and the IPv6 address to clatd on the command line instead of clatd finding it itself. That way, netd and the framework will always know how 464xlat is configured, and we'll be able to use that information in netd. Test: builds, boots Test: atest FrameworksNetTests Change-Id: Ida32d5760c5aecf7aeebef08fdb596291b2ce14a
This commit is contained in:
@@ -1798,6 +1798,12 @@ public class ConnectivityServiceTest {
|
||||
fn.test((NetworkCapabilities) cbi.arg));
|
||||
}
|
||||
|
||||
void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
|
||||
CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
|
||||
assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
|
||||
fn.test((LinkProperties) cbi.arg));
|
||||
}
|
||||
|
||||
void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
|
||||
CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
|
||||
boolean actualBlocked = (boolean) cbi.arg;
|
||||
@@ -5087,6 +5093,9 @@ public class ConnectivityServiceTest {
|
||||
public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
|
||||
final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
|
||||
final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
|
||||
final String kNat64PrefixString = "2001:db8:64:64:64:64::";
|
||||
final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
|
||||
|
||||
final NetworkRequest networkRequest = new NetworkRequest.Builder()
|
||||
.addTransportType(TRANSPORT_CELLULAR)
|
||||
.addCapability(NET_CAPABILITY_INTERNET)
|
||||
@@ -5110,10 +5119,19 @@ public class ConnectivityServiceTest {
|
||||
mCellNetworkAgent.sendLinkProperties(cellLp);
|
||||
mCellNetworkAgent.connect(true);
|
||||
networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
|
||||
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME);
|
||||
Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
|
||||
|
||||
// Clat iface up, expect stack link updated.
|
||||
// When NAT64 prefix detection succeeds, LinkProperties are updated and clatd is started.
|
||||
Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
|
||||
assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
|
||||
mService.mNetdEventCallback.onNat64PrefixEvent(mCellNetworkAgent.getNetwork().netId,
|
||||
true /* added */, kNat64PrefixString, 96);
|
||||
LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
|
||||
CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
|
||||
assertEquals(0, lpBeforeClat.getStackedLinks().size());
|
||||
assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
|
||||
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
|
||||
|
||||
// Clat iface comes up. Expect stacked link to be added.
|
||||
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
|
||||
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
|
||||
List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
|
||||
@@ -5130,20 +5148,50 @@ public class ConnectivityServiceTest {
|
||||
assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
|
||||
assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
|
||||
|
||||
// Add ipv4 address, expect stacked linkproperties be cleaned up
|
||||
// Add ipv4 address, expect that clatd is stopped and stacked linkproperties are cleaned up.
|
||||
cellLp.addLinkAddress(myIpv4);
|
||||
cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
|
||||
mCellNetworkAgent.sendLinkProperties(cellLp);
|
||||
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
|
||||
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
|
||||
|
||||
// Clat iface removed, expect linkproperties revert to original one
|
||||
clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
|
||||
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
|
||||
LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
|
||||
assertEquals(cellLp, actualLpAfterIpv4);
|
||||
|
||||
// Clean up
|
||||
// As soon as stop is called, the linkproperties lose the stacked interface.
|
||||
LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
|
||||
LinkProperties expected = new LinkProperties(cellLp);
|
||||
expected.setNat64Prefix(kNat64Prefix);
|
||||
assertEquals(expected, actualLpAfterIpv4);
|
||||
assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
|
||||
|
||||
// The interface removed callback happens but has no effect after stop is called.
|
||||
clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
|
||||
networkCallback.assertNoCallback();
|
||||
|
||||
reset(mMockNetd);
|
||||
|
||||
// Remove IPv4 address and expect clatd to be started again.
|
||||
cellLp.removeLinkAddress(myIpv4);
|
||||
cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
|
||||
cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
|
||||
mCellNetworkAgent.sendLinkProperties(cellLp);
|
||||
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
|
||||
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
|
||||
|
||||
// Clat iface comes up. Expect stacked link to be added.
|
||||
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
|
||||
networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 1,
|
||||
mCellNetworkAgent);
|
||||
|
||||
// NAT64 prefix is removed. Expect that clat is stopped.
|
||||
mService.mNetdEventCallback.onNat64PrefixEvent(mCellNetworkAgent.getNetwork().netId,
|
||||
false /* added */, kNat64PrefixString, 96);
|
||||
networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
|
||||
mCellNetworkAgent);
|
||||
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
|
||||
networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
|
||||
mCellNetworkAgent);
|
||||
|
||||
// Clean up.
|
||||
mCellNetworkAgent.disconnect();
|
||||
networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
|
||||
networkCallback.assertNoCallback();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.connectivity;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.eq;
|
||||
@@ -28,6 +29,7 @@ import static org.mockito.Mockito.when;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.INetd;
|
||||
import android.net.InterfaceConfiguration;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.NetworkInfo;
|
||||
@@ -55,6 +57,7 @@ public class Nat464XlatTest {
|
||||
static final String BASE_IFACE = "test0";
|
||||
static final String STACKED_IFACE = "v4-test0";
|
||||
static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29");
|
||||
static final String NAT64_PREFIX = "64:ff9b::/96";
|
||||
|
||||
@Mock ConnectivityService mConnectivity;
|
||||
@Mock NetworkMisc mMisc;
|
||||
@@ -89,6 +92,15 @@ public class Nat464XlatTest {
|
||||
when(mConfig.getLinkAddress()).thenReturn(ADDR);
|
||||
}
|
||||
|
||||
private void assertRequiresClat(boolean expected, NetworkAgentInfo nai) {
|
||||
String msg = String.format("requiresClat expected %b for type=%d state=%s skip464xlat=%b "
|
||||
+ "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(),
|
||||
nai.networkInfo.getDetailedState(),
|
||||
mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(),
|
||||
nai.linkProperties.getLinkAddresses());
|
||||
assertEquals(msg, expected, Nat464Xlat.requiresClat(nai));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiresClat() throws Exception {
|
||||
final int[] supportedTypes = {
|
||||
@@ -104,20 +116,31 @@ public class Nat464XlatTest {
|
||||
NetworkInfo.DetailedState.SUSPENDED,
|
||||
};
|
||||
|
||||
LinkProperties oldLp = new LinkProperties(mNai.linkProperties);
|
||||
for (int type : supportedTypes) {
|
||||
mNai.networkInfo.setType(type);
|
||||
for (NetworkInfo.DetailedState state : supportedDetailedStates) {
|
||||
mNai.networkInfo.setDetailedState(state, "reason", "extraInfo");
|
||||
String msg = String.format("requiresClat expected for type=%d state=%s",
|
||||
type, state);
|
||||
|
||||
mNai.linkProperties.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
|
||||
assertRequiresClat(false, mNai);
|
||||
|
||||
mNai.linkProperties.addLinkAddress(new LinkAddress("fc00::1/64"));
|
||||
assertRequiresClat(false, mNai);
|
||||
|
||||
mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64"));
|
||||
assertRequiresClat(true, mNai);
|
||||
|
||||
mMisc.skip464xlat = true;
|
||||
String errorMsg = msg + String.format(" skip464xlat=%b", mMisc.skip464xlat);
|
||||
assertFalse(errorMsg, Nat464Xlat.requiresClat(mNai));
|
||||
assertRequiresClat(false, mNai);
|
||||
|
||||
mMisc.skip464xlat = false;
|
||||
errorMsg = msg + String.format(" skip464xlat=%b", mMisc.skip464xlat);
|
||||
assertTrue(errorMsg, Nat464Xlat.requiresClat(mNai));
|
||||
assertRequiresClat(true, mNai);
|
||||
|
||||
mNai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.2/24"));
|
||||
assertRequiresClat(false, mNai);
|
||||
|
||||
mNai.linkProperties = new LinkProperties(oldLp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,11 +150,13 @@ public class Nat464XlatTest {
|
||||
Nat464Xlat nat = makeNat464Xlat();
|
||||
ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
|
||||
|
||||
nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
|
||||
|
||||
// ConnectivityService starts clat.
|
||||
nat.start();
|
||||
|
||||
verify(mNms).registerObserver(eq(nat));
|
||||
verify(mNetd).clatdStart(eq(BASE_IFACE));
|
||||
verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
|
||||
|
||||
// Stacked interface up notification arrives.
|
||||
nat.interfaceLinkStateChanged(STACKED_IFACE, true);
|
||||
@@ -165,10 +190,12 @@ public class Nat464XlatTest {
|
||||
ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
|
||||
InOrder inOrder = inOrder(mNetd, mConnectivity);
|
||||
|
||||
nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
|
||||
|
||||
// ConnectivityService starts clat.
|
||||
nat.start();
|
||||
|
||||
inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE));
|
||||
inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
|
||||
|
||||
// Stacked interface up notification arrives.
|
||||
nat.interfaceLinkStateChanged(STACKED_IFACE, true);
|
||||
@@ -205,7 +232,7 @@ public class Nat464XlatTest {
|
||||
// ConnectivityService starts clatd again.
|
||||
nat.start();
|
||||
|
||||
inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE));
|
||||
inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
|
||||
|
||||
if (!interfaceRemovedFirst) {
|
||||
// Stacked interface removed notification arrives and is ignored.
|
||||
@@ -252,11 +279,13 @@ public class Nat464XlatTest {
|
||||
Nat464Xlat nat = makeNat464Xlat();
|
||||
ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
|
||||
|
||||
nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
|
||||
|
||||
// ConnectivityService starts clat.
|
||||
nat.start();
|
||||
|
||||
verify(mNms).registerObserver(eq(nat));
|
||||
verify(mNetd).clatdStart(eq(BASE_IFACE));
|
||||
verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
|
||||
|
||||
// Stacked interface up notification arrives.
|
||||
nat.interfaceLinkStateChanged(STACKED_IFACE, true);
|
||||
@@ -289,11 +318,13 @@ public class Nat464XlatTest {
|
||||
public void testStopBeforeClatdStarts() throws Exception {
|
||||
Nat464Xlat nat = makeNat464Xlat();
|
||||
|
||||
nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
|
||||
|
||||
// ConnectivityService starts clat.
|
||||
nat.start();
|
||||
|
||||
verify(mNms).registerObserver(eq(nat));
|
||||
verify(mNetd).clatdStart(eq(BASE_IFACE));
|
||||
verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
|
||||
|
||||
// ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
|
||||
nat.stop();
|
||||
@@ -320,11 +351,13 @@ public class Nat464XlatTest {
|
||||
public void testStopAndClatdNeverStarts() throws Exception {
|
||||
Nat464Xlat nat = makeNat464Xlat();
|
||||
|
||||
nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
|
||||
|
||||
// ConnectivityService starts clat.
|
||||
nat.start();
|
||||
|
||||
verify(mNms).registerObserver(eq(nat));
|
||||
verify(mNetd).clatdStart(eq(BASE_IFACE));
|
||||
verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
|
||||
|
||||
// ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
|
||||
nat.stop();
|
||||
|
||||
Reference in New Issue
Block a user