diff options
author | Dheeraj Shetty <shettydheeraj@google.com> | 2020-04-20 13:27:29 -0700 |
---|---|---|
committer | Dheeraj Shetty <shettydheeraj@google.com> | 2020-04-24 08:50:53 -0700 |
commit | fe1329b1637308e570acc9656388425334722460 (patch) | |
tree | 9ce2f3b5d08bac17489ba92339576a0b44911bff | |
parent | 6d2920b94b1dabf1a988bb2b520db0aff2248a23 (diff) | |
download | ike-fe1329b1637308e570acc9656388425334722460.tar.gz |
Use user configured retransmission timeouts
Test: atest FrameworksIkeTests(New tests added)
Bug: 151947025
Change-Id: I19aabba8c250e68d4c504dd158f43259b0408579
5 files changed, 37 insertions, 98 deletions
diff --git a/src/java/android/net/ipsec/ike/IkeSessionParams.java b/src/java/android/net/ipsec/ike/IkeSessionParams.java index 80f6639f..9880ff42 100644 --- a/src/java/android/net/ipsec/ike/IkeSessionParams.java +++ b/src/java/android/net/ipsec/ike/IkeSessionParams.java @@ -93,7 +93,6 @@ public final class IkeSessionParams { * request that the remote (also) use an EAP-only authentication flow. * * <p>@see {@link Builder#setAuthEap(X509Certificate, EapSessionConfig)} - * */ public static final int IKE_OPTION_EAP_ONLY_AUTH = 1; @@ -350,9 +349,7 @@ public final class IkeSessionParams { Inet6Address getAddress(); } - /** - * This class contains common information of an IKEv2 authentication configuration. - */ + /** This class contains common information of an IKEv2 authentication configuration. */ public abstract static class IkeAuthConfig { /** @hide */ @IkeAuthMethod public final int mAuthMethod; @@ -864,10 +861,11 @@ public final class IkeSessionParams { * Sets the retransmission timeout list in milliseconds. * * <p>Configures the retransmission by providing an array of relative retransmission - * timeouts in milliseconds, where the array length represents the maximum retransmission - * attempts before terminating the IKE Session. Each element in the array MUST be a value - * from 500 ms to 1800000 ms (30 minutes). The length of the array MUST NOT exceed 10. This - * retransmission timeout list defaults to {0.5s, 1s, 2s, 4s, 8s} + * timeouts in milliseconds, where each timeout is the waiting time before next retry, + * except the last timeout is the waiting time before terminating the IKE Session. Each + * element in the array MUST be a value from 500 ms to 1800000 ms (30 minutes). The length + * of the array MUST NOT exceed 10. This retransmission timeout list defaults to {0.5s, 1s, + * 2s, 4s, 8s} * * @param retransTimeoutMillisList the array of relative retransmission timeout in * milliseconds. @@ -877,6 +875,7 @@ public final class IkeSessionParams { public Builder setRetransmissionTimeoutsMillis(@NonNull int[] retransTimeoutMillisList) { boolean isValid = true; if (retransTimeoutMillisList == null + || retransTimeoutMillisList.length == 0 || retransTimeoutMillisList.length > IKE_RETRANS_MAX_ATTEMPTS_MAX) { isValid = false; } @@ -943,14 +942,15 @@ public final class IkeSessionParams { if ((mIkeOptions & getOptionBitValue(IKE_OPTION_EAP_ONLY_AUTH)) != 0) { if (!(mLocalAuthConfig instanceof IkeAuthEapConfig)) { - throw new IllegalArgumentException("If IKE_OPTION_EAP_ONLY_AUTH is set," - + " eap authentication needs to be configured."); + throw new IllegalArgumentException( + "If IKE_OPTION_EAP_ONLY_AUTH is set," + + " eap authentication needs to be configured."); } IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) mLocalAuthConfig; if (!ikeAuthEapConfig.getEapConfig().areAllMethodsEapOnlySafe()) { - throw new IllegalArgumentException("Only EAP-only safe method allowed" - + " when using EAP-only option."); + throw new IllegalArgumentException( + "Only EAP-only safe method allowed" + " when using EAP-only option."); } } diff --git a/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java b/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java index 4a6ffb28..6dcc6d26 100644 --- a/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java +++ b/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java @@ -1827,7 +1827,7 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { } private EncryptedRetransmitter(IkeSaRecord ikeSaRecord, IkeMessage msg) { - super(getHandler(), msg); + super(getHandler(), msg, mIkeSessionParams.getRetransmissionTimeoutsMillis()); mIkeSaRecord = ikeSaRecord; @@ -2959,7 +2959,7 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { private class UnencryptedRetransmitter extends Retransmitter { private UnencryptedRetransmitter(IkeMessage msg) { - super(getHandler(), msg); + super(getHandler(), msg, mIkeSessionParams.getRetransmissionTimeoutsMillis()); retransmit(); } diff --git a/src/java/com/android/internal/net/ipsec/ike/utils/Retransmitter.java b/src/java/com/android/internal/net/ipsec/ike/utils/Retransmitter.java index 778d6859..2b656d3b 100644 --- a/src/java/com/android/internal/net/ipsec/ike/utils/Retransmitter.java +++ b/src/java/com/android/internal/net/ipsec/ike/utils/Retransmitter.java @@ -19,7 +19,6 @@ import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_RETR import android.os.Handler; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.ipsec.ike.message.IkeMessage; /** @@ -30,34 +29,15 @@ import com.android.internal.net.ipsec.ike.message.IkeMessage; * instance of this class. */ public abstract class Retransmitter { - private static IBackoffTimeoutCalculator sBackoffTimeoutCalculator = - new BackoffTimeoutCalculator(); - - /* - * Retransmit parameters - * - * (Re)transmission count | Relative timeout | Absolute timeout - * -------------------------+-------------------+------------------ - * 0 | 500ms | 500ms - * 1 | 1s | 1.5s - * 2 | 2s | 3.5s - * 3 | 4s | 7.5s - * 4 | 8s | 15.5s - * 5 | 16s | 31.5s - * - * TODO: Add retransmitter configurability - */ - static final double RETRANSMIT_BACKOFF_FACTOR = 2.0; - static final long RETRANSMIT_TIMEOUT_MS = 500L; - static final int RETRANSMIT_MAX_ATTEMPTS = 5; - private final Handler mHandler; private final IkeMessage mRetransmitMsg; private int mRetransmitCount = 0; + private int[] mRetransmissionTimeouts; - public Retransmitter(Handler handler, IkeMessage msg) { + public Retransmitter(Handler handler, IkeMessage msg, int[] retransmissionTimeouts) { mHandler = handler; mRetransmitMsg = msg; + mRetransmissionTimeouts = retransmissionTimeouts; } /** @@ -69,14 +49,14 @@ public abstract class Retransmitter { } // If the failed iteration is beyond the max attempts, clean up and shut down. - if (mRetransmitCount > RETRANSMIT_MAX_ATTEMPTS) { + if (mRetransmitCount >= mRetransmissionTimeouts.length) { handleRetransmissionFailure(); return; } send(mRetransmitMsg); - long timeout = sBackoffTimeoutCalculator.getExponentialBackoffTimeout(mRetransmitCount++); + long timeout = mRetransmissionTimeouts[mRetransmitCount++]; mHandler.sendMessageDelayed(mHandler.obtainMessage(CMD_RETRANSMIT, this), timeout); } @@ -105,35 +85,4 @@ public abstract class Retransmitter { * <p>For Retransmitter-internal use only. */ protected abstract void handleRetransmissionFailure(); - - /** - * IBackoffTimeoutCalculator provides interface for calculating retransmission backoff timeout. - * - * <p>IBackoffTimeoutCalculator exists so that the interface is injectable for testing. - */ - @VisibleForTesting - public interface IBackoffTimeoutCalculator { - /** Calculate retransmission backoff timeout */ - long getExponentialBackoffTimeout(int retransmitCount); - } - - private static final class BackoffTimeoutCalculator implements IBackoffTimeoutCalculator { - @Override - public long getExponentialBackoffTimeout(int retransmitCount) { - double expBackoffFactor = Math.pow(RETRANSMIT_BACKOFF_FACTOR, retransmitCount); - return (long) (RETRANSMIT_TIMEOUT_MS * expBackoffFactor); - } - } - - /** Sets IBackoffTimeoutCalculator */ - @VisibleForTesting - public static void setBackoffTimeoutCalculator(IBackoffTimeoutCalculator calculator) { - sBackoffTimeoutCalculator = calculator; - } - - /** Resets BackoffTimeoutCalculator of retransmitter */ - @VisibleForTesting - public static void resetBackoffTimeoutCalculator() { - sBackoffTimeoutCalculator = new BackoffTimeoutCalculator(); - } } diff --git a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java index 7dff7515..bb4c6c26 100644 --- a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java +++ b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java @@ -150,8 +150,6 @@ import com.android.internal.net.ipsec.ike.message.IkeTestUtils; import com.android.internal.net.ipsec.ike.message.IkeTsPayload; import com.android.internal.net.ipsec.ike.testutils.CertUtils; import com.android.internal.net.ipsec.ike.utils.IkeSecurityParameterIndex; -import com.android.internal.net.ipsec.ike.utils.Retransmitter; -import com.android.internal.net.ipsec.ike.utils.Retransmitter.IBackoffTimeoutCalculator; import com.android.internal.net.ipsec.ike.utils.State; import com.android.internal.net.utils.Log; @@ -275,15 +273,10 @@ public final class IkeSessionStateMachineTest extends IkeSessionTestBase { private static final int CHILD_SPI_LOCAL = 0x2ad4c0a2; private static final int CHILD_SPI_REMOTE = 0xcae7019f; - private static final int DUMMY_UDP_ENCAP_RESOURCE_ID = 0x3234; - private static final int UDP_ENCAP_PORT = 34567; - private static final int EAP_SIM_SUB_ID = 1; private static final int PAYLOAD_TYPE_UNSUPPORTED = 127; - private static final long RETRANSMIT_BACKOFF_TIMEOUT_MS = 5000L; - private IkeUdpEncapSocket mSpyIkeUdpEncapSocket; private IkeUdp4Socket mSpyIkeUdp4Socket; private IkeUdp6Socket mSpyIkeUdp6Socket; @@ -307,7 +300,6 @@ public final class IkeSessionStateMachineTest extends IkeSessionTestBase { private IIkeMessageHelper mMockIkeMessageHelper; private ISaRecordHelper mMockSaRecordHelper; - private IBackoffTimeoutCalculator mMockBackoffTimeoutCalculator; private ChildSessionStateMachine mMockChildSessionStateMachine; private IChildSessionFactoryHelper mMockChildSessionFactoryHelper; @@ -692,13 +684,6 @@ public final class IkeSessionStateMachineTest extends IkeSessionTestBase { mMockChildSessionFactoryHelper); setupChildStateMachineFactory(mMockChildSessionStateMachine); - // Inject longer retransmission timeout - mMockBackoffTimeoutCalculator = mock(IBackoffTimeoutCalculator.class); - doReturn(RETRANSMIT_BACKOFF_TIMEOUT_MS) - .when(mMockBackoffTimeoutCalculator) - .getExponentialBackoffTimeout(anyInt()); - Retransmitter.setBackoffTimeoutCalculator(mMockBackoffTimeoutCalculator); - // Setup state machine mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsPsk(mPsk)); @@ -727,7 +712,6 @@ public final class IkeSessionStateMachineTest extends IkeSessionTestBase { mSpyRemoteInitIkeSaRecord.close(); IkeManager.resetIkeLog(); - Retransmitter.resetBackoffTimeoutCalculator(); IkeMessage.setIkeMessageHelper(new IkeMessageHelper()); SaRecord.setSaRecordHelper(new SaRecordHelper()); ChildSessionStateMachineFactory.setChildSessionFactoryHelper( @@ -796,7 +780,9 @@ public final class IkeSessionStateMachineTest extends IkeSessionTestBase { .setRemoteIdentification( new IkeIpv4AddrIdentification((Inet4Address) REMOTE_ADDRESS)) .addPcscfServerRequest(AF_INET) - .addPcscfServerRequest(AF_INET6); + .addPcscfServerRequest(AF_INET6) + .setRetransmissionTimeoutsMillis( + new int[] {5000, 10000, 20000, 30000, 40000, 50000}); } private IkeSessionParams buildIkeSessionParamsPsk(byte[] psk) throws Exception { diff --git a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/utils/RetransmitterTest.java b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/utils/RetransmitterTest.java index 63552910..76999519 100644 --- a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/utils/RetransmitterTest.java +++ b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/utils/RetransmitterTest.java @@ -42,13 +42,15 @@ public final class RetransmitterTest { private Handler mMockHandler; private IkeMessage mMockIkeMessage; private TestRetransmitter mRetransmitter; + private static final int[] IKE_RETRANS_TIMEOUT_MS_LIST = + new int[] {500, 1000, 2000, 4000, 8000}; private class TestRetransmitter extends Retransmitter { int mSendCallCount; // Defaults to 0 boolean mFailed; // Defaults to false - TestRetransmitter(Handler handler, IkeMessage message) { - super(handler, message); + TestRetransmitter(Handler handler, IkeMessage message, int[] retransmissionTimeouts) { + super(handler, message, retransmissionTimeouts); } @Override @@ -70,7 +72,8 @@ public final class RetransmitterTest { doReturn(mockMessage).when(mMockHandler).obtainMessage(eq(CMD_RETRANSMIT), anyObject()); mMockIkeMessage = mock(IkeMessage.class); - mRetransmitter = new TestRetransmitter(mMockHandler, mMockIkeMessage); + mRetransmitter = + new TestRetransmitter(mMockHandler, mMockIkeMessage, IKE_RETRANS_TIMEOUT_MS_LIST); } @Test @@ -79,18 +82,16 @@ public final class RetransmitterTest { assertEquals(1, mRetransmitter.mSendCallCount); verify(mMockHandler).obtainMessage(eq(CMD_RETRANSMIT), eq(mRetransmitter)); verify(mMockHandler) - .sendMessageDelayed(any(Message.class), eq(Retransmitter.RETRANSMIT_TIMEOUT_MS)); + .sendMessageDelayed( + any(Message.class), eq((long) (IKE_RETRANS_TIMEOUT_MS_LIST[0]))); } @Test - public void testRetransmitQueuesExponentialRetransmit() throws Exception { + public void testRetransmitUserConfiguredRetransmit() throws Exception { mRetransmitter.retransmit(); - for (int i = 0; i <= Retransmitter.RETRANSMIT_MAX_ATTEMPTS; i++) { - long expectedTimeout = - (long) - (Retransmitter.RETRANSMIT_TIMEOUT_MS - * Math.pow(Retransmitter.RETRANSMIT_BACKOFF_FACTOR, i)); + for (int i = 0; i < IKE_RETRANS_TIMEOUT_MS_LIST.length; i++) { + long expectedTimeout = (long) IKE_RETRANS_TIMEOUT_MS_LIST[i]; assertEquals(i + 1, mRetransmitter.mSendCallCount); assertFalse(mRetransmitter.mFailed); @@ -114,10 +115,13 @@ public final class RetransmitterTest { mRetransmitter.retransmit(); // Exhaust all retransmit attempts - for (int i = 0; i <= Retransmitter.RETRANSMIT_MAX_ATTEMPTS; i++) { + for (int i = 0; i < IKE_RETRANS_TIMEOUT_MS_LIST.length - 1; i++) { mRetransmitter.retransmit(); } + assertFalse(mRetransmitter.mFailed); + // Trigger the last retransmission + mRetransmitter.retransmit(); assertTrue(mRetransmitter.mFailed); } |