diff options
6 files changed, 235 insertions, 37 deletions
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index cefd8efe9658..05df22f124ed 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -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(); @@ -624,6 +661,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. * * <p>Set in Connecting or Migrating States, always @NonNull in Connecting, Connected, and @@ -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. */ @@ -2350,6 +2434,11 @@ public class VcnGatewayConnection extends StateMachine { } @VisibleForTesting(visibility = Visibility.PRIVATE) + IkeSessionConnectionInfo getIkeConnectionInfo() { + return mIkeConnectionInfo; + } + + @VisibleForTesting(visibility = Visibility.PRIVATE) boolean isQuitting() { return mIsQuitting.getValue(); } diff --git a/services/core/java/com/android/server/vcn/util/MtuUtils.java b/services/core/java/com/android/server/vcn/util/MtuUtils.java index 5d40cca3e19d..356c71f5f26a 100644 --- a/services/core/java/com/android/server/vcn/util/MtuUtils.java +++ b/services/core/java/com/android/server/vcn/util/MtuUtils.java @@ -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); } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 841b81c2a282..15d4f1097108 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -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); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java index b9dfda38a01c..6a9a1e22cab1 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java @@ -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); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index 5628321b5975..3d95a9b32d4a 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -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(); diff --git a/tests/vcn/java/com/android/server/vcn/util/MtuUtilsTest.java b/tests/vcn/java/com/android/server/vcn/util/MtuUtilsTest.java index 29511f780bf6..e9e70783ebe9 100644 --- a/tests/vcn/java/com/android/server/vcn/util/MtuUtilsTest.java +++ b/tests/vcn/java/com/android/server/vcn/util/MtuUtilsTest.java @@ -46,34 +46,85 @@ import java.util.List; @RunWith(AndroidJUnit4.class) @SmallTest public class MtuUtilsTest { + private void verifyUnderlyingMtuZero(boolean isIpv4) { + assertEquals( + IPV6_MIN_MTU, + getMtu(emptyList(), ETHER_MTU /* maxMtu */, 0 /* underlyingMtu */, isIpv4)); + } + + @Test + public void testUnderlyingMtuZeroV4() { + verifyUnderlyingMtuZero(true /* isIpv4 */); + } + @Test - public void testUnderlyingMtuZero() { + public void testUnderlyingMtuZeroV6() { + verifyUnderlyingMtuZero(false /* isIpv4 */); + } + + private void verifyClampsToMaxMtu(boolean isIpv4) { assertEquals( - IPV6_MIN_MTU, getMtu(emptyList(), ETHER_MTU /* maxMtu */, 0 /* underlyingMtu */)); + 0, getMtu(emptyList(), 0 /* maxMtu */, IPV6_MIN_MTU /* underlyingMtu */, isIpv4)); } @Test - public void testClampsToMaxMtu() { - assertEquals(0, getMtu(emptyList(), 0 /* maxMtu */, IPV6_MIN_MTU /* underlyingMtu */)); + public void testClampsToMaxMtuV4() { + verifyClampsToMaxMtu(true /* isIpv4 */); } @Test - public void testNormalModeAlgorithmLessThanUnderlyingMtu() { - final List<ChildSaProposal> saProposals = - Arrays.asList( - new ChildSaProposal.Builder() - .addEncryptionAlgorithm( - ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256) - .addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128) - .build()); + public void testClampsToMaxMtuV6() { + verifyClampsToMaxMtu(false /* isIpv4 */); + } + + private List<ChildSaProposal> buildChildSaProposalsWithNormalModeAlgo() { + return Arrays.asList( + new ChildSaProposal.Builder() + .addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256) + .addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128) + .build()); + } + private void verifyNormalModeAlgorithmLessThanUnderlyingMtu(boolean isIpv4) { final int actualMtu = - getMtu(saProposals, ETHER_MTU /* maxMtu */, ETHER_MTU /* underlyingMtu */); + getMtu( + buildChildSaProposalsWithNormalModeAlgo(), + ETHER_MTU /* maxMtu */, + ETHER_MTU /* underlyingMtu */, + isIpv4); assertTrue(ETHER_MTU > actualMtu); } @Test - public void testCombinedModeAlgorithmLessThanUnderlyingMtu() { + public void testNormalModeAlgorithmLessThanUnderlyingMtuV4() { + verifyNormalModeAlgorithmLessThanUnderlyingMtu(true /* isIpv4 */); + } + + @Test + public void testNormalModeAlgorithmLessThanUnderlyingMtuV6() { + verifyNormalModeAlgorithmLessThanUnderlyingMtu(false /* isIpv4 */); + } + + @Test + public void testMtuIpv4LessThanMtuIpv6() { + final int actualMtuV4 = + getMtu( + buildChildSaProposalsWithNormalModeAlgo(), + ETHER_MTU /* maxMtu */, + ETHER_MTU /* underlyingMtu */, + true /* isIpv4 */); + + final int actualMtuV6 = + getMtu( + buildChildSaProposalsWithNormalModeAlgo(), + ETHER_MTU /* maxMtu */, + ETHER_MTU /* underlyingMtu */, + false /* isIpv4 */); + + assertTrue(actualMtuV4 < actualMtuV6); + } + + private void verifyCombinedModeAlgorithmLessThanUnderlyingMtu(boolean isIpv4) { final List<ChildSaProposal> saProposals = Arrays.asList( new ChildSaProposal.Builder() @@ -86,7 +137,17 @@ public class MtuUtilsTest { .build()); final int actualMtu = - getMtu(saProposals, ETHER_MTU /* maxMtu */, ETHER_MTU /* underlyingMtu */); + getMtu(saProposals, ETHER_MTU /* maxMtu */, ETHER_MTU /* underlyingMtu */, isIpv4); assertTrue(ETHER_MTU > actualMtu); } + + @Test + public void testCombinedModeAlgorithmLessThanUnderlyingMtuV4() { + verifyCombinedModeAlgorithmLessThanUnderlyingMtu(true /* isIpv4 */); + } + + @Test + public void testCombinedModeAlgorithmLessThanUnderlyingMtuV6() { + verifyCombinedModeAlgorithmLessThanUnderlyingMtu(false /* isIpv4 */); + } } |