Loading services/core/java/com/android/server/vcn/VcnGatewayConnection.java +103 −14 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import android.net.ipsec.ike.ChildSessionParams; import android.net.ipsec.ike.IkeSession; import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionConfiguration; import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.ipsec.ike.exceptions.IkeException; Loading Loading @@ -509,6 +510,42 @@ public class VcnGatewayConnection extends StateMachine { } } /** * Sent when an IKE session connection information has changed. * * <p>This signal is always fired before EVENT_SETUP_COMPLETED and EVENT_MIGRATION_COMPLETED. * * <p>Only relevant in the Connecting and Connected state. * * @param arg1 The session token for the IKE Session whose connection information has changed, * used to prevent out-of-date signals from propagating. * @param obj @NonNull An EventIkeConnectionInfoChangedInfo instance with relevant data. */ private static final int EVENT_IKE_CONNECTION_INFO_CHANGED = 12; private static class EventIkeConnectionInfoChangedInfo implements EventInfo { @NonNull public final IkeSessionConnectionInfo ikeConnectionInfo; EventIkeConnectionInfoChangedInfo(@NonNull IkeSessionConnectionInfo ikeConnectionInfo) { this.ikeConnectionInfo = ikeConnectionInfo; } @Override public int hashCode() { return Objects.hash(ikeConnectionInfo); } @Override public boolean equals(@Nullable Object other) { if (!(other instanceof EventIkeConnectionInfoChangedInfo)) { return false; } final EventIkeConnectionInfoChangedInfo rhs = (EventIkeConnectionInfoChangedInfo) other; return Objects.equals(ikeConnectionInfo, rhs.ikeConnectionInfo); } } @VisibleForTesting(visibility = Visibility.PRIVATE) @NonNull final DisconnectedState mDisconnectedState = new DisconnectedState(); Loading Loading @@ -623,6 +660,14 @@ public class VcnGatewayConnection extends StateMachine { */ private UnderlyingNetworkRecord mUnderlying; /** * The current IKE Session connection information * * <p>Set in Connected and Migrating states, always @NonNull in Connected, Migrating * states, @Nullable otherwise. */ private IkeSessionConnectionInfo mIkeConnectionInfo; /** * The active IKE session. * Loading Loading @@ -1197,6 +1242,14 @@ public class VcnGatewayConnection extends StateMachine { exceptionMessage); } private void ikeConnectionInfoChanged( int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { sendMessageAndAcquireWakeLock( EVENT_IKE_CONNECTION_INFO_CHANGED, token, new EventIkeConnectionInfoChangedInfo(ikeConnectionInfo)); } private void sessionClosed(int token, @Nullable Exception exception) { if (exception != null) { notifyStatusCallbackForSessionClosed(exception); Loading Loading @@ -1313,7 +1366,8 @@ public class VcnGatewayConnection extends StateMachine { case EVENT_TEARDOWN_TIMEOUT_EXPIRED: // Fallthrough case EVENT_SUBSCRIPTIONS_CHANGED: // Fallthrough case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: // Fallthrough case EVENT_MIGRATION_COMPLETED: case EVENT_MIGRATION_COMPLETED: // Fallthrough case EVENT_IKE_CONNECTION_INFO_CHANGED: logUnexpectedEvent(msg.what); break; default: Loading Loading @@ -1592,6 +1646,7 @@ public class VcnGatewayConnection extends StateMachine { transitionTo(mDisconnectingState); break; case EVENT_SETUP_COMPLETED: // fallthrough case EVENT_IKE_CONNECTION_INFO_CHANGED: // fallthrough case EVENT_TRANSFORM_CREATED: // Child setup complete; move to ConnectedState for NetworkAgent registration deferMessage(msg); Loading @@ -1614,12 +1669,17 @@ public class VcnGatewayConnection extends StateMachine { protected void updateNetworkAgent( @NonNull IpSecTunnelInterface tunnelIface, @NonNull VcnNetworkAgent agent, @NonNull VcnChildSessionConfiguration childConfig) { @NonNull VcnChildSessionConfiguration childConfig, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { final NetworkCapabilities caps = buildNetworkCapabilities(mConnectionConfig, mUnderlying, mIsMobileDataEnabled); final LinkProperties lp = buildConnectedLinkProperties( mConnectionConfig, tunnelIface, childConfig, mUnderlying); mConnectionConfig, tunnelIface, childConfig, mUnderlying, ikeConnectionInfo); agent.sendNetworkCapabilities(caps); agent.sendLinkProperties(lp); Loading @@ -1630,12 +1690,17 @@ public class VcnGatewayConnection extends StateMachine { protected VcnNetworkAgent buildNetworkAgent( @NonNull IpSecTunnelInterface tunnelIface, @NonNull VcnChildSessionConfiguration childConfig) { @NonNull VcnChildSessionConfiguration childConfig, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { final NetworkCapabilities caps = buildNetworkCapabilities(mConnectionConfig, mUnderlying, mIsMobileDataEnabled); final LinkProperties lp = buildConnectedLinkProperties( mConnectionConfig, tunnelIface, childConfig, mUnderlying); mConnectionConfig, tunnelIface, childConfig, mUnderlying, ikeConnectionInfo); final NetworkAgentConfig nac = new NetworkAgentConfig.Builder() .setLegacyType(ConnectivityManager.TYPE_MOBILE) Loading Loading @@ -1838,7 +1903,11 @@ public class VcnGatewayConnection extends StateMachine { mChildConfig = ((EventSetupCompletedInfo) msg.obj).childSessionConfig; setupInterfaceAndNetworkAgent( mCurrentToken, mTunnelIface, mChildConfig, oldChildConfig); mCurrentToken, mTunnelIface, mChildConfig, oldChildConfig, mIkeConnectionInfo); break; case EVENT_DISCONNECT_REQUESTED: handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj); Loading @@ -1852,6 +1921,10 @@ public class VcnGatewayConnection extends StateMachine { handleMigrationCompleted(migrationCompletedInfo); break; case EVENT_IKE_CONNECTION_INFO_CHANGED: mIkeConnectionInfo = ((EventIkeConnectionInfoChangedInfo) msg.obj).ikeConnectionInfo; break; default: logUnhandledMessage(msg); break; Loading @@ -1875,7 +1948,7 @@ public class VcnGatewayConnection extends StateMachine { migrationCompletedInfo.outTransform, IpSecManager.DIRECTION_OUT); updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig); updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig, mIkeConnectionInfo); // Trigger re-validation after migration events. mConnectivityManager.reportNetworkConnectivity( Loading Loading @@ -1906,7 +1979,8 @@ public class VcnGatewayConnection extends StateMachine { // Network not yet set up, or child not yet connected. if (mNetworkAgent != null && mChildConfig != null) { // If only network properties changed and agent is active, update properties updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig); updateNetworkAgent( mTunnelIface, mNetworkAgent, mChildConfig, mIkeConnectionInfo); } } } Loading @@ -1915,13 +1989,14 @@ public class VcnGatewayConnection extends StateMachine { int token, @NonNull IpSecTunnelInterface tunnelIface, @NonNull VcnChildSessionConfiguration childConfig, @NonNull VcnChildSessionConfiguration oldChildConfig) { @NonNull VcnChildSessionConfiguration oldChildConfig, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { setupInterface(token, tunnelIface, childConfig, oldChildConfig); if (mNetworkAgent == null) { mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig); mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig, ikeConnectionInfo); } else { updateNetworkAgent(tunnelIface, mNetworkAgent, childConfig); updateNetworkAgent(tunnelIface, mNetworkAgent, childConfig, ikeConnectionInfo); // mNetworkAgent not null, so the VCN Network has already been established. Clear // the failed attempt counter and safe mode alarm since this transition is complete. Loading Loading @@ -2098,7 +2173,8 @@ public class VcnGatewayConnection extends StateMachine { @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig, @NonNull IpSecTunnelInterface tunnelIface, @NonNull VcnChildSessionConfiguration childConfig, @Nullable UnderlyingNetworkRecord underlying) { @Nullable UnderlyingNetworkRecord underlying, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { final IkeTunnelConnectionParams ikeTunnelParams = gatewayConnectionConfig.getTunnelConnectionParams(); final LinkProperties lp = new LinkProperties(); Loading Loading @@ -2139,7 +2215,8 @@ public class VcnGatewayConnection extends StateMachine { MtuUtils.getMtu( ikeTunnelParams.getTunnelModeChildSessionParams().getSaProposals(), gatewayConnectionConfig.getMaxMtu(), underlyingMtu)); underlyingMtu, ikeConnectionInfo.getLocalAddress() instanceof Inet4Address)); return lp; } Loading @@ -2154,7 +2231,7 @@ public class VcnGatewayConnection extends StateMachine { @Override public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) { logDbg("IkeOpened for token " + mToken); // Nothing to do here. ikeConnectionInfoChanged(mToken, ikeSessionConfig.getIkeSessionConnectionInfo()); } @Override Loading @@ -2174,6 +2251,13 @@ public class VcnGatewayConnection extends StateMachine { logInfo("IkeError for token " + mToken, exception); // Non-fatal, log and continue. } @Override public void onIkeSessionConnectionInfoChanged( @NonNull IkeSessionConnectionInfo connectionInfo) { logDbg("onIkeSessionConnectionInfoChanged for token " + mToken); ikeConnectionInfoChanged(mToken, connectionInfo); } } /** Implementation of ChildSessionCallback, exposed for testing. */ Loading Loading @@ -2349,6 +2433,11 @@ public class VcnGatewayConnection extends StateMachine { mUnderlying = record; } @VisibleForTesting(visibility = Visibility.PRIVATE) IkeSessionConnectionInfo getIkeConnectionInfo() { return mIkeConnectionInfo; } @VisibleForTesting(visibility = Visibility.PRIVATE) boolean isQuitting() { return mIsQuitting.getValue(); Loading services/core/java/com/android/server/vcn/util/MtuUtils.java +22 −5 Original line number Diff line number Diff line Loading @@ -51,9 +51,20 @@ public class MtuUtils { /** * Max ESP overhead possible * * <p>60 (Outer IPv4 + options) + 8 (UDP encap) + 4 (SPI) + 4 (Seq) + 2 (Pad + NextHeader) * <p>60 (Outer IPv4 + options) + 8 (UDP encap) + 4 (SPI) + 4 (Seq) + 2 (Pad Length + Next * Header). Note: Payload data, Pad Length and Next Header will need to be padded to be multiple * of the block size of a cipher, and at the same time be aligned on a 4-byte boundary. */ private static final int GENERIC_ESP_OVERHEAD_MAX = 78; private static final int GENERIC_ESP_OVERHEAD_MAX_V4 = 78; /** * Max ESP overhead possible * * <p>40 (Outer IPv6) + 4 (SPI) + 4 (Seq) + 2 (Pad Length + Next Header). Note: Payload data, * Pad Length and Next Header will need to be padded to be multiple of the block size of a * cipher, and at the same time be aligned on a 4-byte boundary. */ private static final int GENERIC_ESP_OVERHEAD_MAX_V6 = 50; /** Maximum overheads of authentication algorithms, keyed on IANA-defined constants */ private static final Map<Integer, Integer> AUTH_ALGORITHM_OVERHEAD; Loading Loading @@ -108,7 +119,10 @@ public class MtuUtils { * </ul> */ public static int getMtu( @NonNull List<ChildSaProposal> childProposals, int maxMtu, int underlyingMtu) { @NonNull List<ChildSaProposal> childProposals, int maxMtu, int underlyingMtu, boolean isIpv4) { if (underlyingMtu <= 0) { return IPV6_MIN_MTU; } Loading Loading @@ -145,10 +159,13 @@ public class MtuUtils { } } final int genericEspOverheadMax = isIpv4 ? GENERIC_ESP_OVERHEAD_MAX_V4 : GENERIC_ESP_OVERHEAD_MAX_V6; // Return minimum of maxMtu, and the adjusted MTUs based on algorithms. final int combinedModeMtu = underlyingMtu - maxAuthCryptOverhead - GENERIC_ESP_OVERHEAD_MAX; final int combinedModeMtu = underlyingMtu - maxAuthCryptOverhead - genericEspOverheadMax; final int normalModeMtu = underlyingMtu - maxCryptOverhead - maxAuthOverhead - GENERIC_ESP_OVERHEAD_MAX; underlyingMtu - maxCryptOverhead - maxAuthOverhead - genericEspOverheadMax; return Math.min(Math.min(maxMtu, combinedModeMtu), normalModeMtu); } } tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +14 −1 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.net.LinkProperties; import android.net.NetworkAgent; import android.net.NetworkCapabilities; import android.net.ipsec.ike.ChildSaProposal; import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.ipsec.ike.exceptions.IkeException; import android.net.ipsec.ike.exceptions.IkeInternalException; import android.net.ipsec.ike.exceptions.IkeProtocolException; Loading Loading @@ -216,14 +217,23 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection @Test public void testMigration() throws Exception { triggerChildOpened(); mTestLooper.dispatchAll(); assertEquals(mIkeConnectionInfo, mGatewayConnection.getIkeConnectionInfo()); mGatewayConnection .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2); final IkeSessionConnectionInfo newIkeConnectionInfo = new IkeSessionConnectionInfo( TEST_ADDR_V4, TEST_ADDR_V4_2, TEST_UNDERLYING_NETWORK_RECORD_2.network); getIkeSessionCallback().onIkeSessionConnectionInfoChanged(newIkeConnectionInfo); getChildSessionCallback() .onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform()); mTestLooper.dispatchAll(); assertEquals(newIkeConnectionInfo, mGatewayConnection.getIkeConnectionInfo()); verify(mIpSecSvc, times(2)) .setNetworkForTunnelInterface( eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), Loading @@ -246,7 +256,8 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection MtuUtils.getMtu( saProposals, mConfig.getMaxMtu(), TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.getMtu()); TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.getMtu(), true /* isIpv4 */); verify(mNetworkAgent).sendLinkProperties( argThat(lp -> expectedMtu == lp.getMtu() && TEST_TCP_BUFFER_SIZES_2.equals(lp.getTcpBufferSizes()))); Loading @@ -269,6 +280,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection .when(mMockChildSessionConfig) .getInternalDnsServers(); getIkeSessionCallback().onOpened(mIkeSessionConfiguration); getChildSessionCallback().onOpened(mMockChildSessionConfig); } Loading Loading @@ -298,6 +310,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState()); assertEquals(mIkeConnectionInfo, mGatewayConnection.getIkeConnectionInfo()); final ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class); Loading tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java +4 −2 Original line number Diff line number Diff line Loading @@ -213,7 +213,8 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { VcnGatewayConnectionConfigTest.buildTestConfig(), tunnelIface, childSessionConfig, record); record, mIkeConnectionInfo); verify(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE); Loading @@ -226,7 +227,8 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { VcnGatewayConnectionConfigTest.buildTestConfig(), tunnelIface, childSessionConfig, record); record, mIkeConnectionInfo); verify(mDeps, times(2)).getUnderlyingIfaceMtu(LOOPBACK_IFACE); Loading tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +16 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.ipsec.ike.ChildSessionCallback; import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionConfiguration; import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; Loading Loading @@ -80,6 +82,13 @@ public class VcnGatewayConnectionTestBase { doReturn(TEST_SUB_GRP).when(TEST_SUB_INFO).getGroupUuid(); } protected static final InetAddress TEST_ADDR = InetAddresses.parseNumericAddress("2001:db8::1"); protected static final InetAddress TEST_ADDR_2 = InetAddresses.parseNumericAddress("2001:db8::2"); protected static final InetAddress TEST_ADDR_V4 = InetAddresses.parseNumericAddress("192.0.2.1"); protected static final InetAddress TEST_ADDR_V4_2 = InetAddresses.parseNumericAddress("192.0.2.2"); protected static final InetAddress TEST_DNS_ADDR = InetAddresses.parseNumericAddress("2001:DB8:0:1::"); protected static final InetAddress TEST_DNS_ADDR_2 = Loading Loading @@ -148,6 +157,9 @@ public class VcnGatewayConnectionTestBase { @NonNull protected final IpSecService mIpSecSvc; @NonNull protected final ConnectivityManager mConnMgr; @NonNull protected final IkeSessionConnectionInfo mIkeConnectionInfo; @NonNull protected final IkeSessionConfiguration mIkeSessionConfiguration; protected VcnIkeSession mMockIkeSession; protected VcnGatewayConnection mGatewayConnection; Loading @@ -173,6 +185,10 @@ public class VcnGatewayConnectionTestBase { VcnTestUtils.setupSystemService( mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); mIkeConnectionInfo = new IkeSessionConnectionInfo(TEST_ADDR, TEST_ADDR_2, mock(Network.class)); mIkeSessionConfiguration = new IkeSessionConfiguration.Builder(mIkeConnectionInfo).build(); doReturn(mContext).when(mVcnContext).getContext(); doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper(); doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider(); Loading Loading
services/core/java/com/android/server/vcn/VcnGatewayConnection.java +103 −14 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import android.net.ipsec.ike.ChildSessionParams; import android.net.ipsec.ike.IkeSession; import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionConfiguration; import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.ipsec.ike.exceptions.IkeException; Loading Loading @@ -509,6 +510,42 @@ public class VcnGatewayConnection extends StateMachine { } } /** * Sent when an IKE session connection information has changed. * * <p>This signal is always fired before EVENT_SETUP_COMPLETED and EVENT_MIGRATION_COMPLETED. * * <p>Only relevant in the Connecting and Connected state. * * @param arg1 The session token for the IKE Session whose connection information has changed, * used to prevent out-of-date signals from propagating. * @param obj @NonNull An EventIkeConnectionInfoChangedInfo instance with relevant data. */ private static final int EVENT_IKE_CONNECTION_INFO_CHANGED = 12; private static class EventIkeConnectionInfoChangedInfo implements EventInfo { @NonNull public final IkeSessionConnectionInfo ikeConnectionInfo; EventIkeConnectionInfoChangedInfo(@NonNull IkeSessionConnectionInfo ikeConnectionInfo) { this.ikeConnectionInfo = ikeConnectionInfo; } @Override public int hashCode() { return Objects.hash(ikeConnectionInfo); } @Override public boolean equals(@Nullable Object other) { if (!(other instanceof EventIkeConnectionInfoChangedInfo)) { return false; } final EventIkeConnectionInfoChangedInfo rhs = (EventIkeConnectionInfoChangedInfo) other; return Objects.equals(ikeConnectionInfo, rhs.ikeConnectionInfo); } } @VisibleForTesting(visibility = Visibility.PRIVATE) @NonNull final DisconnectedState mDisconnectedState = new DisconnectedState(); Loading Loading @@ -623,6 +660,14 @@ public class VcnGatewayConnection extends StateMachine { */ private UnderlyingNetworkRecord mUnderlying; /** * The current IKE Session connection information * * <p>Set in Connected and Migrating states, always @NonNull in Connected, Migrating * states, @Nullable otherwise. */ private IkeSessionConnectionInfo mIkeConnectionInfo; /** * The active IKE session. * Loading Loading @@ -1197,6 +1242,14 @@ public class VcnGatewayConnection extends StateMachine { exceptionMessage); } private void ikeConnectionInfoChanged( int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { sendMessageAndAcquireWakeLock( EVENT_IKE_CONNECTION_INFO_CHANGED, token, new EventIkeConnectionInfoChangedInfo(ikeConnectionInfo)); } private void sessionClosed(int token, @Nullable Exception exception) { if (exception != null) { notifyStatusCallbackForSessionClosed(exception); Loading Loading @@ -1313,7 +1366,8 @@ public class VcnGatewayConnection extends StateMachine { case EVENT_TEARDOWN_TIMEOUT_EXPIRED: // Fallthrough case EVENT_SUBSCRIPTIONS_CHANGED: // Fallthrough case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: // Fallthrough case EVENT_MIGRATION_COMPLETED: case EVENT_MIGRATION_COMPLETED: // Fallthrough case EVENT_IKE_CONNECTION_INFO_CHANGED: logUnexpectedEvent(msg.what); break; default: Loading Loading @@ -1592,6 +1646,7 @@ public class VcnGatewayConnection extends StateMachine { transitionTo(mDisconnectingState); break; case EVENT_SETUP_COMPLETED: // fallthrough case EVENT_IKE_CONNECTION_INFO_CHANGED: // fallthrough case EVENT_TRANSFORM_CREATED: // Child setup complete; move to ConnectedState for NetworkAgent registration deferMessage(msg); Loading @@ -1614,12 +1669,17 @@ public class VcnGatewayConnection extends StateMachine { protected void updateNetworkAgent( @NonNull IpSecTunnelInterface tunnelIface, @NonNull VcnNetworkAgent agent, @NonNull VcnChildSessionConfiguration childConfig) { @NonNull VcnChildSessionConfiguration childConfig, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { final NetworkCapabilities caps = buildNetworkCapabilities(mConnectionConfig, mUnderlying, mIsMobileDataEnabled); final LinkProperties lp = buildConnectedLinkProperties( mConnectionConfig, tunnelIface, childConfig, mUnderlying); mConnectionConfig, tunnelIface, childConfig, mUnderlying, ikeConnectionInfo); agent.sendNetworkCapabilities(caps); agent.sendLinkProperties(lp); Loading @@ -1630,12 +1690,17 @@ public class VcnGatewayConnection extends StateMachine { protected VcnNetworkAgent buildNetworkAgent( @NonNull IpSecTunnelInterface tunnelIface, @NonNull VcnChildSessionConfiguration childConfig) { @NonNull VcnChildSessionConfiguration childConfig, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { final NetworkCapabilities caps = buildNetworkCapabilities(mConnectionConfig, mUnderlying, mIsMobileDataEnabled); final LinkProperties lp = buildConnectedLinkProperties( mConnectionConfig, tunnelIface, childConfig, mUnderlying); mConnectionConfig, tunnelIface, childConfig, mUnderlying, ikeConnectionInfo); final NetworkAgentConfig nac = new NetworkAgentConfig.Builder() .setLegacyType(ConnectivityManager.TYPE_MOBILE) Loading Loading @@ -1838,7 +1903,11 @@ public class VcnGatewayConnection extends StateMachine { mChildConfig = ((EventSetupCompletedInfo) msg.obj).childSessionConfig; setupInterfaceAndNetworkAgent( mCurrentToken, mTunnelIface, mChildConfig, oldChildConfig); mCurrentToken, mTunnelIface, mChildConfig, oldChildConfig, mIkeConnectionInfo); break; case EVENT_DISCONNECT_REQUESTED: handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj); Loading @@ -1852,6 +1921,10 @@ public class VcnGatewayConnection extends StateMachine { handleMigrationCompleted(migrationCompletedInfo); break; case EVENT_IKE_CONNECTION_INFO_CHANGED: mIkeConnectionInfo = ((EventIkeConnectionInfoChangedInfo) msg.obj).ikeConnectionInfo; break; default: logUnhandledMessage(msg); break; Loading @@ -1875,7 +1948,7 @@ public class VcnGatewayConnection extends StateMachine { migrationCompletedInfo.outTransform, IpSecManager.DIRECTION_OUT); updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig); updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig, mIkeConnectionInfo); // Trigger re-validation after migration events. mConnectivityManager.reportNetworkConnectivity( Loading Loading @@ -1906,7 +1979,8 @@ public class VcnGatewayConnection extends StateMachine { // Network not yet set up, or child not yet connected. if (mNetworkAgent != null && mChildConfig != null) { // If only network properties changed and agent is active, update properties updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig); updateNetworkAgent( mTunnelIface, mNetworkAgent, mChildConfig, mIkeConnectionInfo); } } } Loading @@ -1915,13 +1989,14 @@ public class VcnGatewayConnection extends StateMachine { int token, @NonNull IpSecTunnelInterface tunnelIface, @NonNull VcnChildSessionConfiguration childConfig, @NonNull VcnChildSessionConfiguration oldChildConfig) { @NonNull VcnChildSessionConfiguration oldChildConfig, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { setupInterface(token, tunnelIface, childConfig, oldChildConfig); if (mNetworkAgent == null) { mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig); mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig, ikeConnectionInfo); } else { updateNetworkAgent(tunnelIface, mNetworkAgent, childConfig); updateNetworkAgent(tunnelIface, mNetworkAgent, childConfig, ikeConnectionInfo); // mNetworkAgent not null, so the VCN Network has already been established. Clear // the failed attempt counter and safe mode alarm since this transition is complete. Loading Loading @@ -2098,7 +2173,8 @@ public class VcnGatewayConnection extends StateMachine { @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig, @NonNull IpSecTunnelInterface tunnelIface, @NonNull VcnChildSessionConfiguration childConfig, @Nullable UnderlyingNetworkRecord underlying) { @Nullable UnderlyingNetworkRecord underlying, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { final IkeTunnelConnectionParams ikeTunnelParams = gatewayConnectionConfig.getTunnelConnectionParams(); final LinkProperties lp = new LinkProperties(); Loading Loading @@ -2139,7 +2215,8 @@ public class VcnGatewayConnection extends StateMachine { MtuUtils.getMtu( ikeTunnelParams.getTunnelModeChildSessionParams().getSaProposals(), gatewayConnectionConfig.getMaxMtu(), underlyingMtu)); underlyingMtu, ikeConnectionInfo.getLocalAddress() instanceof Inet4Address)); return lp; } Loading @@ -2154,7 +2231,7 @@ public class VcnGatewayConnection extends StateMachine { @Override public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) { logDbg("IkeOpened for token " + mToken); // Nothing to do here. ikeConnectionInfoChanged(mToken, ikeSessionConfig.getIkeSessionConnectionInfo()); } @Override Loading @@ -2174,6 +2251,13 @@ public class VcnGatewayConnection extends StateMachine { logInfo("IkeError for token " + mToken, exception); // Non-fatal, log and continue. } @Override public void onIkeSessionConnectionInfoChanged( @NonNull IkeSessionConnectionInfo connectionInfo) { logDbg("onIkeSessionConnectionInfoChanged for token " + mToken); ikeConnectionInfoChanged(mToken, connectionInfo); } } /** Implementation of ChildSessionCallback, exposed for testing. */ Loading Loading @@ -2349,6 +2433,11 @@ public class VcnGatewayConnection extends StateMachine { mUnderlying = record; } @VisibleForTesting(visibility = Visibility.PRIVATE) IkeSessionConnectionInfo getIkeConnectionInfo() { return mIkeConnectionInfo; } @VisibleForTesting(visibility = Visibility.PRIVATE) boolean isQuitting() { return mIsQuitting.getValue(); Loading
services/core/java/com/android/server/vcn/util/MtuUtils.java +22 −5 Original line number Diff line number Diff line Loading @@ -51,9 +51,20 @@ public class MtuUtils { /** * Max ESP overhead possible * * <p>60 (Outer IPv4 + options) + 8 (UDP encap) + 4 (SPI) + 4 (Seq) + 2 (Pad + NextHeader) * <p>60 (Outer IPv4 + options) + 8 (UDP encap) + 4 (SPI) + 4 (Seq) + 2 (Pad Length + Next * Header). Note: Payload data, Pad Length and Next Header will need to be padded to be multiple * of the block size of a cipher, and at the same time be aligned on a 4-byte boundary. */ private static final int GENERIC_ESP_OVERHEAD_MAX = 78; private static final int GENERIC_ESP_OVERHEAD_MAX_V4 = 78; /** * Max ESP overhead possible * * <p>40 (Outer IPv6) + 4 (SPI) + 4 (Seq) + 2 (Pad Length + Next Header). Note: Payload data, * Pad Length and Next Header will need to be padded to be multiple of the block size of a * cipher, and at the same time be aligned on a 4-byte boundary. */ private static final int GENERIC_ESP_OVERHEAD_MAX_V6 = 50; /** Maximum overheads of authentication algorithms, keyed on IANA-defined constants */ private static final Map<Integer, Integer> AUTH_ALGORITHM_OVERHEAD; Loading Loading @@ -108,7 +119,10 @@ public class MtuUtils { * </ul> */ public static int getMtu( @NonNull List<ChildSaProposal> childProposals, int maxMtu, int underlyingMtu) { @NonNull List<ChildSaProposal> childProposals, int maxMtu, int underlyingMtu, boolean isIpv4) { if (underlyingMtu <= 0) { return IPV6_MIN_MTU; } Loading Loading @@ -145,10 +159,13 @@ public class MtuUtils { } } final int genericEspOverheadMax = isIpv4 ? GENERIC_ESP_OVERHEAD_MAX_V4 : GENERIC_ESP_OVERHEAD_MAX_V6; // Return minimum of maxMtu, and the adjusted MTUs based on algorithms. final int combinedModeMtu = underlyingMtu - maxAuthCryptOverhead - GENERIC_ESP_OVERHEAD_MAX; final int combinedModeMtu = underlyingMtu - maxAuthCryptOverhead - genericEspOverheadMax; final int normalModeMtu = underlyingMtu - maxCryptOverhead - maxAuthOverhead - GENERIC_ESP_OVERHEAD_MAX; underlyingMtu - maxCryptOverhead - maxAuthOverhead - genericEspOverheadMax; return Math.min(Math.min(maxMtu, combinedModeMtu), normalModeMtu); } }
tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +14 −1 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.net.LinkProperties; import android.net.NetworkAgent; import android.net.NetworkCapabilities; import android.net.ipsec.ike.ChildSaProposal; import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.ipsec.ike.exceptions.IkeException; import android.net.ipsec.ike.exceptions.IkeInternalException; import android.net.ipsec.ike.exceptions.IkeProtocolException; Loading Loading @@ -216,14 +217,23 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection @Test public void testMigration() throws Exception { triggerChildOpened(); mTestLooper.dispatchAll(); assertEquals(mIkeConnectionInfo, mGatewayConnection.getIkeConnectionInfo()); mGatewayConnection .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2); final IkeSessionConnectionInfo newIkeConnectionInfo = new IkeSessionConnectionInfo( TEST_ADDR_V4, TEST_ADDR_V4_2, TEST_UNDERLYING_NETWORK_RECORD_2.network); getIkeSessionCallback().onIkeSessionConnectionInfoChanged(newIkeConnectionInfo); getChildSessionCallback() .onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform()); mTestLooper.dispatchAll(); assertEquals(newIkeConnectionInfo, mGatewayConnection.getIkeConnectionInfo()); verify(mIpSecSvc, times(2)) .setNetworkForTunnelInterface( eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), Loading @@ -246,7 +256,8 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection MtuUtils.getMtu( saProposals, mConfig.getMaxMtu(), TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.getMtu()); TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.getMtu(), true /* isIpv4 */); verify(mNetworkAgent).sendLinkProperties( argThat(lp -> expectedMtu == lp.getMtu() && TEST_TCP_BUFFER_SIZES_2.equals(lp.getTcpBufferSizes()))); Loading @@ -269,6 +280,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection .when(mMockChildSessionConfig) .getInternalDnsServers(); getIkeSessionCallback().onOpened(mIkeSessionConfiguration); getChildSessionCallback().onOpened(mMockChildSessionConfig); } Loading Loading @@ -298,6 +310,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection mTestLooper.dispatchAll(); assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState()); assertEquals(mIkeConnectionInfo, mGatewayConnection.getIkeConnectionInfo()); final ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class); Loading
tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java +4 −2 Original line number Diff line number Diff line Loading @@ -213,7 +213,8 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { VcnGatewayConnectionConfigTest.buildTestConfig(), tunnelIface, childSessionConfig, record); record, mIkeConnectionInfo); verify(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE); Loading @@ -226,7 +227,8 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { VcnGatewayConnectionConfigTest.buildTestConfig(), tunnelIface, childSessionConfig, record); record, mIkeConnectionInfo); verify(mDeps, times(2)).getUnderlyingIfaceMtu(LOOPBACK_IFACE); Loading
tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +16 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.ipsec.ike.ChildSessionCallback; import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionConfiguration; import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; Loading Loading @@ -80,6 +82,13 @@ public class VcnGatewayConnectionTestBase { doReturn(TEST_SUB_GRP).when(TEST_SUB_INFO).getGroupUuid(); } protected static final InetAddress TEST_ADDR = InetAddresses.parseNumericAddress("2001:db8::1"); protected static final InetAddress TEST_ADDR_2 = InetAddresses.parseNumericAddress("2001:db8::2"); protected static final InetAddress TEST_ADDR_V4 = InetAddresses.parseNumericAddress("192.0.2.1"); protected static final InetAddress TEST_ADDR_V4_2 = InetAddresses.parseNumericAddress("192.0.2.2"); protected static final InetAddress TEST_DNS_ADDR = InetAddresses.parseNumericAddress("2001:DB8:0:1::"); protected static final InetAddress TEST_DNS_ADDR_2 = Loading Loading @@ -148,6 +157,9 @@ public class VcnGatewayConnectionTestBase { @NonNull protected final IpSecService mIpSecSvc; @NonNull protected final ConnectivityManager mConnMgr; @NonNull protected final IkeSessionConnectionInfo mIkeConnectionInfo; @NonNull protected final IkeSessionConfiguration mIkeSessionConfiguration; protected VcnIkeSession mMockIkeSession; protected VcnGatewayConnection mGatewayConnection; Loading @@ -173,6 +185,10 @@ public class VcnGatewayConnectionTestBase { VcnTestUtils.setupSystemService( mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); mIkeConnectionInfo = new IkeSessionConnectionInfo(TEST_ADDR, TEST_ADDR_2, mock(Network.class)); mIkeSessionConfiguration = new IkeSessionConfiguration.Builder(mIkeConnectionInfo).build(); doReturn(mContext).when(mVcnContext).getContext(); doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper(); doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider(); Loading