Support learning the NAT64 prefix from two different sources.

The NAT64 prefix from the RA always takes precedence over the
NAT64 prefix from DNS discovery, because it is detected faster,
and detecting it does not require sending any packets.

Bug: 150648313
Test: new unit test
Merged-In: Ic7452431d2d9aea1ae59b67a9d8383c6cc5b3902
Change-Id: Ic7452431d2d9aea1ae59b67a9d8383c6cc5b3902
This commit is contained in:
Lorenzo Colitti
2020-04-20 11:37:18 +00:00
parent 78ab633b8f
commit 4308bfc4f0
4 changed files with 179 additions and 24 deletions

View File

@@ -6179,6 +6179,95 @@ public class ConnectivityServiceTest {
mCm.unregisterNetworkCallback(networkCallback);
}
private void expectNat64PrefixChange(TestableNetworkCallback callback,
TestNetworkAgentWrapper agent, IpPrefix prefix) {
callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix));
}
@Test
public void testNat64PrefixMultipleSources() throws Exception {
final String iface = "wlan0";
final String pref64FromRaStr = "64:ff9b::";
final String pref64FromDnsStr = "2001:db8:64::";
final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96);
final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96);
final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96");
final NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_INTERNET)
.build();
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerNetworkCallback(request, callback);
final LinkProperties baseLp = new LinkProperties();
baseLp.setInterfaceName(iface);
baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464"));
reset(mMockNetd, mMockDnsResolver);
InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
// If a network already has a NAT64 prefix on connect, clatd is started immediately and
// prefix discovery is never started.
LinkProperties lp = new LinkProperties(baseLp);
lp.setNat64Prefix(pref64FromRa);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
mCellNetworkAgent.connect(false);
final Network network = mCellNetworkAgent.getNetwork();
int netId = network.getNetId();
callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
callback.assertNoCallback();
assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
// If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
lp.setNat64Prefix(null);
mCellNetworkAgent.sendLinkProperties(lp);
expectNat64PrefixChange(callback, mCellNetworkAgent, null);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
pref64FromDnsStr, 96);
expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
// If the RA prefix reappears, clatd is restarted and prefix discovery is stopped.
lp.setNat64Prefix(pref64FromRa);
mCellNetworkAgent.sendLinkProperties(lp);
expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
// If the RA prefix changes, clatd is restarted and prefix discovery is not started.
lp.setNat64Prefix(newPref64FromRa);
mCellNetworkAgent.sendLinkProperties(lp);
expectNat64PrefixChange(callback, mCellNetworkAgent, newPref64FromRa);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString());
inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
// If the RA prefix changes to the same value, nothing happens.
lp.setNat64Prefix(newPref64FromRa);
mCellNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
inOrder.verify(mMockNetd, never()).clatdStop(iface);
inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
// The transition between no prefix and DNS prefix is tested in testStackedLinkProperties.
callback.assertNoCallback();
mCellNetworkAgent.disconnect();
mCm.unregisterNetworkCallback(callback);
}
@Test
public void testDataActivityTracking() throws Exception {
final TestNetworkCallback networkCallback = new TestNetworkCallback();

View File

@@ -60,6 +60,7 @@ public class Nat464XlatTest {
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";
static final String OTHER_NAT64_PREFIX = "2001:db8:0:64::/96";
static final int NETID = 42;
@Mock ConnectivityService mConnectivity;
@@ -139,7 +140,7 @@ public class Nat464XlatTest {
for (NetworkInfo.DetailedState state : supportedDetailedStates) {
mNai.networkInfo.setDetailedState(state, "reason", "extraInfo");
mNai.linkProperties.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
mNai.linkProperties.setNat64Prefix(new IpPrefix(OTHER_NAT64_PREFIX));
assertRequiresClat(false, mNai);
assertShouldStartClat(false, mNai);
@@ -398,6 +399,47 @@ public class Nat464XlatTest {
verifyNoMoreInteractions(mNetd, mNms, mConnectivity);
}
@Test
public void testNat64PrefixPreference() throws Exception {
final IpPrefix prefixFromDns = new IpPrefix(NAT64_PREFIX);
final IpPrefix prefixFromRa = new IpPrefix(OTHER_NAT64_PREFIX);
Nat464Xlat nat = makeNat464Xlat();
final LinkProperties emptyLp = new LinkProperties();
LinkProperties fixedupLp;
fixedupLp = new LinkProperties();
nat.setNat64PrefixFromDns(prefixFromDns);
nat.fixupLinkProperties(emptyLp, fixedupLp);
assertEquals(prefixFromDns, fixedupLp.getNat64Prefix());
fixedupLp = new LinkProperties();
nat.setNat64PrefixFromRa(prefixFromRa);
nat.fixupLinkProperties(emptyLp, fixedupLp);
assertEquals(prefixFromRa, fixedupLp.getNat64Prefix());
fixedupLp = new LinkProperties();
nat.setNat64PrefixFromRa(null);
nat.fixupLinkProperties(emptyLp, fixedupLp);
assertEquals(prefixFromDns, fixedupLp.getNat64Prefix());
fixedupLp = new LinkProperties();
nat.setNat64PrefixFromRa(prefixFromRa);
nat.fixupLinkProperties(emptyLp, fixedupLp);
assertEquals(prefixFromRa, fixedupLp.getNat64Prefix());
fixedupLp = new LinkProperties();
nat.setNat64PrefixFromDns(null);
nat.fixupLinkProperties(emptyLp, fixedupLp);
assertEquals(prefixFromRa, fixedupLp.getNat64Prefix());
fixedupLp = new LinkProperties();
nat.setNat64PrefixFromRa(null);
nat.fixupLinkProperties(emptyLp, fixedupLp);
assertEquals(null, fixedupLp.getNat64Prefix());
}
static void assertIdle(Nat464Xlat nat) {
assertTrue("Nat464Xlat was not IDLE", !nat.isStarted());
}