Merge "Support changing the NAT64 prefix without removing it." into rvc-dev

This commit is contained in:
Lorenzo Colitti
2020-04-17 07:26:08 +00:00
committed by Android (Google) Code Review
2 changed files with 50 additions and 9 deletions

View File

@@ -81,6 +81,9 @@ public class Nat464Xlat extends BaseNetworkObserver {
RUNNING, // start() called, and the stacked iface is known to be up. RUNNING, // start() called, and the stacked iface is known to be up.
} }
/** NAT64 prefix currently in use. Only valid in STARTING or RUNNING states. */
private IpPrefix mNat64PrefixInUse;
/** NAT64 prefix (if any) discovered from DNS via RFC 7050. */
private IpPrefix mNat64PrefixFromDns; private IpPrefix mNat64PrefixFromDns;
private String mBaseIface; private String mBaseIface;
private String mIface; private String mIface;
@@ -178,9 +181,10 @@ public class Nat464Xlat extends BaseNetworkObserver {
return; return;
} }
mNat64PrefixInUse = getNat64Prefix();
String addrStr = null; String addrStr = null;
try { try {
addrStr = mNetd.clatdStart(baseIface, getNat64Prefix().toString()); addrStr = mNetd.clatdStart(baseIface, mNat64PrefixInUse.toString());
} catch (RemoteException | ServiceSpecificException e) { } catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error starting clatd on " + baseIface + ": " + e); Slog.e(TAG, "Error starting clatd on " + baseIface + ": " + e);
} }
@@ -211,12 +215,13 @@ public class Nat464Xlat extends BaseNetworkObserver {
} catch (RemoteException | IllegalStateException e) { } catch (RemoteException | IllegalStateException e) {
Slog.e(TAG, "Error unregistering clatd observer on " + mBaseIface + ": " + e); Slog.e(TAG, "Error unregistering clatd observer on " + mBaseIface + ": " + e);
} }
mNat64PrefixInUse = null;
mIface = null; mIface = null;
mBaseIface = null; mBaseIface = null;
if (requiresClat(mNetwork)) { if (requiresClat(mNetwork)) {
mState = State.DISCOVERING; mState = State.DISCOVERING;
} else { } else {
stopPrefixDiscovery(); stopPrefixDiscovery(); // Enters IDLE state.
} }
} }
@@ -274,19 +279,32 @@ public class Nat464Xlat extends BaseNetworkObserver {
private void startPrefixDiscovery() { private void startPrefixDiscovery() {
try { try {
mDnsResolver.startPrefix64Discovery(getNetId()); mDnsResolver.startPrefix64Discovery(getNetId());
mState = State.DISCOVERING;
} catch (RemoteException | ServiceSpecificException e) { } catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e); Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e);
} }
mState = State.DISCOVERING;
} }
private void stopPrefixDiscovery() { private void stopPrefixDiscovery() {
try { try {
mDnsResolver.stopPrefix64Discovery(getNetId()); mDnsResolver.stopPrefix64Discovery(getNetId());
mState = State.IDLE;
} catch (RemoteException | ServiceSpecificException e) { } catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e); Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e);
} }
mState = State.IDLE;
}
private void maybeHandleNat64PrefixChange() {
final IpPrefix newPrefix = getNat64Prefix();
if (!Objects.equals(mNat64PrefixInUse, newPrefix)) {
Slog.d(TAG, "NAT64 prefix changed from " + mNat64PrefixInUse + " to "
+ newPrefix);
stop();
// It's safe to call update here, even though this method is called from update, because
// stop() is guaranteed to have moved out of STARTING and RUNNING, which are the only
// states in which this method can be called.
update();
}
} }
/** /**
@@ -325,11 +343,11 @@ public class Nat464Xlat extends BaseNetworkObserver {
// Stop clatd and go back into DISCOVERING or idle. // Stop clatd and go back into DISCOVERING or idle.
if (!shouldStartClat(mNetwork)) { if (!shouldStartClat(mNetwork)) {
stop(); stop();
break;
} }
// Only necessary while clat is actually started.
maybeHandleNat64PrefixChange();
break; break;
// TODO: support the NAT64 prefix changing after it's been discovered. There is
// no need to support this at the moment because it cannot happen without
// changes to the Dns64Configuration code in netd.
} }
} }
@@ -347,6 +365,8 @@ public class Nat464Xlat extends BaseNetworkObserver {
* has no idea that 464xlat is running on top of it. * has no idea that 464xlat is running on top of it.
*/ */
public void fixupLinkProperties(@NonNull LinkProperties oldLp, @NonNull LinkProperties lp) { public void fixupLinkProperties(@NonNull LinkProperties oldLp, @NonNull LinkProperties lp) {
// This must be done even if clatd is not running, because otherwise shouldStartClat would
// never return true.
lp.setNat64Prefix(getNat64Prefix()); lp.setNat64Prefix(getNat64Prefix());
if (!isRunning()) { if (!isRunning()) {

View File

@@ -5969,6 +5969,9 @@ public class ConnectivityServiceTest {
final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64"); final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
final String kNat64PrefixString = "2001:db8:64:64:64:64::"; final String kNat64PrefixString = "2001:db8:64:64:64:64::";
final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96); final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
final String kOtherNat64PrefixString = "64:ff9b::";
final IpPrefix kOtherNat64Prefix = new IpPrefix(
InetAddress.getByName(kOtherNat64PrefixString), 96);
final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(), final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(),
MOBILE_IFNAME); MOBILE_IFNAME);
final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME); final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
@@ -6082,6 +6085,24 @@ public class ConnectivityServiceTest {
} }
reset(mMockNetd); reset(mMockNetd);
// Change the NAT64 prefix without first removing it.
// Expect clatd to be stopped and started with the new prefix.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
kOtherNat64PrefixString, 96);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getStackedLinks().size() == 0);
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
assertRoutesRemoved(cellNetId, stackedDefault);
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString());
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix));
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getStackedLinks().size() == 1);
assertRoutesAdded(cellNetId, stackedDefault);
reset(mMockNetd);
// Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
// linkproperties are cleaned up. // linkproperties are cleaned up.
cellLp.addLinkAddress(myIpv4); cellLp.addLinkAddress(myIpv4);
@@ -6096,7 +6117,7 @@ public class ConnectivityServiceTest {
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork()); LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
LinkProperties expected = new LinkProperties(cellLp); LinkProperties expected = new LinkProperties(cellLp);
expected.setNat64Prefix(kNat64Prefix); expected.setNat64Prefix(kOtherNat64Prefix);
assertEquals(expected, actualLpAfterIpv4); assertEquals(expected, actualLpAfterIpv4);
assertEquals(0, actualLpAfterIpv4.getStackedLinks().size()); assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
assertRoutesRemoved(cellNetId, stackedDefault); assertRoutesRemoved(cellNetId, stackedDefault);
@@ -6115,7 +6136,7 @@ public class ConnectivityServiceTest {
// Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone. // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
kNat64PrefixString, 96); kOtherNat64PrefixString, 96);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getNat64Prefix() == null); (lp) -> lp.getNat64Prefix() == null);