diff --git a/Vcn/tests/cts/src/android/net/vcn/cts/VcnManagerTest.java b/Vcn/tests/cts/src/android/net/vcn/cts/VcnManagerTest.java index 08ca86ee23..6626fb2e43 100644 --- a/Vcn/tests/cts/src/android/net/vcn/cts/VcnManagerTest.java +++ b/Vcn/tests/cts/src/android/net/vcn/cts/VcnManagerTest.java @@ -207,6 +207,13 @@ public class VcnManagerTest extends VcnTestBase { .build()); } + private VcnConfig buildVcnConfig(VcnGatewayConnectionConfig gatewayConfig) { + return new VcnConfig.Builder(mContext) + .setIsTestModeProfile() + .addGatewayConnectionConfig(gatewayConfig) + .build(); + } + private VcnConfig buildVcnConfig() { return buildVcnConfigBase().build(); } @@ -1454,4 +1461,84 @@ public class VcnManagerTest extends VcnTestBase { verifyEnterSafeModeImmediately( newVcnConfig(false /* isSafeModeEnabled */), false /* isSafeModeExpected */); } + + // Test for b/391977557 + @Test + public void testExitSafeModeAfterReprovision() throws Exception { + final int subId = verifyAndGetValidDataSubId(); + + // Create a VcnGatewayConnectionConfig with a big retry timer to avoid retry and sending IKE + // INIT requests after entering safe mode + final VcnGatewayConnectionConfig.Builder gatewayConfigBuilder = + VcnGatewayConnectionConfigTest.buildVcnGatewayConnectionConfigBase() + .setRetryIntervalsMillis(new long[] {TimeUnit.MINUTES.toMillis(100)}); + + // Create two different VcnConfigs that will trigger the previous safe mode exit issue + // b/391977557 + final VcnConfig vcnConfig = buildVcnConfig(gatewayConfigBuilder.setMaxMtu(1500).build()); + final VcnConfig vcnConfigNew = buildVcnConfig(gatewayConfigBuilder.setMaxMtu(1600).build()); + + // Generated by forcing IKE to use Test Mode (RandomnessFactory#mIsTestModeEnabled) and + // capturing IKE packets with a live server. + final String ikeInitFailRespHex = + "46B8ECA1E0D72A180000000000000000292022200000000000000024000000080000000E"; + + final NetworkRequest cellNetworkReq = + new NetworkRequest.Builder() + .addTransportType(TRANSPORT_CELLULAR) + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .build(); + final VcnTestNetworkCallback cellNetworkCbPostSafeMode = new VcnTestNetworkCallback(); + + try (TestNetworkWrapper testNetworkWrapper = + createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) { + verifyUnderlyingCellAndRunTest( + subId, + (subGrp, cellNetwork, cellNetworkCb) -> { + mVcnManager.setVcnConfig(subGrp, vcnConfig); + + // Inject an IKE INIT FAIL response to fail the IKE setup + testNetworkWrapper.ikeTunUtils.awaitReqAndInjectResp( + IKE_DETERMINISTIC_INITIATOR_SPI, + 0 /* expectedMsgId */, + false /* expectedUseEncap */, + ikeInitFailRespHex); + + waitForSafeMode(testNetworkWrapper); + verifyVcnStatus(subGrp, VCN_STATUS_CODE_SAFE_MODE); + + // Register a NetworkCallback to detect when a cell network becomes + // available. This callback also acts as a signaler to proceed with the test + // because, if b/391977557 exists, its symptom (the withdrawal of all + // existing NetworkRequests from VCN) will have *already completed* by + // the time a cell network becomes available. + mConnectivityManager.registerNetworkCallback( + cellNetworkReq, cellNetworkCbPostSafeMode); + assertNotNull( + "No cell network found after entering safe mode", + cellNetworkCbPostSafeMode.waitForAvailable()); + + // Before verifying new IKE setup triggered by reprovision, clear the IKE + // requests generated from the previous setup. Because the failed VCN + // connection is configured to never retry, it's safe to conclude that any + // new IKE requests are generated by the second setup. + testNetworkWrapper.ikeTunUtils.reset(); + mVcnManager.setVcnConfig(subGrp, vcnConfigNew); + + injectAndVerifyIkeSessionNegotiationPackets(testNetworkWrapper.ikeTunUtils); + + // Because the VCN network established by the test will never pass the + // system network validation, VCN will never really exit safe mode in the + // test. However, the establishment of the VCN network provides enough + // confidence that in real case the VCN will be able to exit safe mode. + final Network vcnNetwork = cellNetworkCbPostSafeMode.waitForAvailable(); + assertNotNull("VCN network did not come up", vcnNetwork); + + clearVcnConfigsAndVerifyNetworkTeardown( + subGrp, cellNetworkCbPostSafeMode, vcnNetwork); + + mConnectivityManager.unregisterNetworkCallback(cellNetworkCbPostSafeMode); + }); + } + } }