Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f8e8077 authored by Yan Yan's avatar Yan Yan Committed by Automerger Merge Worker
Browse files

Merge "Maximize VCN MTU when using IPv6" am: 6d70c7f3

parents 76a96802 6d70c7f3
Loading
Loading
Loading
Loading
+103 −14
Original line number Diff line number Diff line
@@ -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;
@@ -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();
@@ -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.
     *
@@ -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);
@@ -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:
@@ -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);
@@ -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);
@@ -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)
@@ -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);
@@ -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;
@@ -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(
@@ -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);
                }
            }
        }
@@ -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.
@@ -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();
@@ -2139,7 +2215,8 @@ public class VcnGatewayConnection extends StateMachine {
                MtuUtils.getMtu(
                        ikeTunnelParams.getTunnelModeChildSessionParams().getSaProposals(),
                        gatewayConnectionConfig.getMaxMtu(),
                        underlyingMtu));
                        underlyingMtu,
                        ikeConnectionInfo.getLocalAddress() instanceof Inet4Address));

        return lp;
    }
@@ -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
@@ -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. */
@@ -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();
+22 −5
Original line number Diff line number Diff line
@@ -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;
@@ -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;
        }
@@ -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);
    }
}
+14 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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),
@@ -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())));
@@ -269,6 +280,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
                .when(mMockChildSessionConfig)
                .getInternalDnsServers();

        getIkeSessionCallback().onOpened(mIkeSessionConfiguration);
        getChildSessionCallback().onOpened(mMockChildSessionConfig);
    }

@@ -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);
+4 −2
Original line number Diff line number Diff line
@@ -213,7 +213,8 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
                        VcnGatewayConnectionConfigTest.buildTestConfig(),
                        tunnelIface,
                        childSessionConfig,
                        record);
                        record,
                        mIkeConnectionInfo);

        verify(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE);

@@ -226,7 +227,8 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
                        VcnGatewayConnectionConfigTest.buildTestConfig(),
                        tunnelIface,
                        childSessionConfig,
                        record);
                        record,
                        mIkeConnectionInfo);

        verify(mDeps, times(2)).getUnderlyingIfaceMtu(LOOPBACK_IFACE);

+16 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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 =
@@ -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;

@@ -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