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

Commit 6d70c7f3 authored by Yan Yan's avatar Yan Yan Committed by Gerrit Code Review
Browse files

Merge "Maximize VCN MTU when using IPv6"

parents 865dcdbf eb00e3c7
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