Add VCN gateway option to enable data stall handling
This commit allows caller to enable VCN's ability of handling data stall by setting a VCN gateway option. Bug: 261499808 Test: atest FrameworksVcnTests (new tests), CtsVcnTestCases Change-Id: If37b26faf851153d64face66d10201d7eecad685
This commit is contained in:
@@ -42,6 +42,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
@@ -130,6 +131,33 @@ public final class VcnGatewayConnectionConfig {
|
||||
})
|
||||
public @interface VcnSupportedCapability {}
|
||||
|
||||
/**
|
||||
* Perform mobility update to attempt recovery from suspected data stalls.
|
||||
*
|
||||
* <p>If set, the gatway connection will monitor the data stall detection of the VCN network.
|
||||
* When there is a suspected data stall, the gateway connection will attempt recovery by
|
||||
* performing a mobility update on the underlying IKE session.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY = 0;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(
|
||||
prefix = {"VCN_GATEWAY_OPTION_"},
|
||||
value = {
|
||||
// TODO: b/261499808 Add VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY
|
||||
// when it is exposed
|
||||
})
|
||||
public @interface VcnGatewayOption {}
|
||||
|
||||
private static final Set<Integer> ALLOWED_GATEWAY_OPTIONS = new ArraySet<>();
|
||||
|
||||
static {
|
||||
ALLOWED_GATEWAY_OPTIONS.add(VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY);
|
||||
}
|
||||
|
||||
private static final int DEFAULT_MAX_MTU = 1500;
|
||||
|
||||
/**
|
||||
@@ -201,6 +229,9 @@ public final class VcnGatewayConnectionConfig {
|
||||
private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs";
|
||||
@NonNull private final long[] mRetryIntervalsMs;
|
||||
|
||||
private static final String GATEWAY_OPTIONS_KEY = "mGatewayOptions";
|
||||
@NonNull private final Set<Integer> mGatewayOptions;
|
||||
|
||||
/** Builds a VcnGatewayConnectionConfig with the specified parameters. */
|
||||
private VcnGatewayConnectionConfig(
|
||||
@NonNull String gatewayConnectionName,
|
||||
@@ -208,12 +239,14 @@ public final class VcnGatewayConnectionConfig {
|
||||
@NonNull Set<Integer> exposedCapabilities,
|
||||
@NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
|
||||
@NonNull long[] retryIntervalsMs,
|
||||
@IntRange(from = MIN_MTU_V6) int maxMtu) {
|
||||
@IntRange(from = MIN_MTU_V6) int maxMtu,
|
||||
@NonNull Set<Integer> gatewayOptions) {
|
||||
mGatewayConnectionName = gatewayConnectionName;
|
||||
mTunnelConnectionParams = tunnelConnectionParams;
|
||||
mExposedCapabilities = new TreeSet(exposedCapabilities);
|
||||
mRetryIntervalsMs = retryIntervalsMs;
|
||||
mMaxMtu = maxMtu;
|
||||
mGatewayOptions = Collections.unmodifiableSet(new HashSet(gatewayOptions));
|
||||
|
||||
mUnderlyingNetworkTemplates = new ArrayList<>(underlyingNetworkTemplates);
|
||||
if (mUnderlyingNetworkTemplates.isEmpty()) {
|
||||
@@ -256,6 +289,20 @@ public final class VcnGatewayConnectionConfig {
|
||||
VcnUnderlyingNetworkTemplate::fromPersistableBundle);
|
||||
}
|
||||
|
||||
final PersistableBundle gatewayOptionsBundle = in.getPersistableBundle(GATEWAY_OPTIONS_KEY);
|
||||
|
||||
if (gatewayOptionsBundle == null) {
|
||||
// GATEWAY_OPTIONS_KEY was added in Android U. Thus VcnGatewayConnectionConfig created
|
||||
// on old platforms will not have this data and will be assigned with the default value
|
||||
mGatewayOptions = Collections.emptySet();
|
||||
} else {
|
||||
mGatewayOptions =
|
||||
new HashSet<>(
|
||||
PersistableBundleUtils.toList(
|
||||
gatewayOptionsBundle,
|
||||
PersistableBundleUtils.INTEGER_DESERIALIZER));
|
||||
}
|
||||
|
||||
mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
|
||||
mMaxMtu = in.getInt(MAX_MTU_KEY);
|
||||
|
||||
@@ -279,6 +326,10 @@ public final class VcnGatewayConnectionConfig {
|
||||
|
||||
Preconditions.checkArgument(
|
||||
mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
|
||||
|
||||
for (int option : mGatewayOptions) {
|
||||
validateGatewayOption(option);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkValidCapability(int capability) {
|
||||
@@ -315,6 +366,12 @@ public final class VcnGatewayConnectionConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private static void validateGatewayOption(int option) {
|
||||
if (!ALLOWED_GATEWAY_OPTIONS.contains(option)) {
|
||||
throw new IllegalArgumentException("Invalid vcn gateway option: " + option);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured Gateway Connection name.
|
||||
*
|
||||
@@ -398,6 +455,18 @@ public final class VcnGatewayConnectionConfig {
|
||||
return mMaxMtu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given VCN gateway option is enabled.
|
||||
*
|
||||
* @param option the option to check.
|
||||
* @throws IllegalArgumentException if the provided option is invalid.
|
||||
* @hide
|
||||
*/
|
||||
public boolean hasGatewayOption(@VcnGatewayOption int option) {
|
||||
validateGatewayOption(option);
|
||||
return mGatewayOptions.contains(option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this config to a PersistableBundle.
|
||||
*
|
||||
@@ -418,11 +487,16 @@ public final class VcnGatewayConnectionConfig {
|
||||
PersistableBundleUtils.fromList(
|
||||
mUnderlyingNetworkTemplates,
|
||||
VcnUnderlyingNetworkTemplate::toPersistableBundle);
|
||||
final PersistableBundle gatewayOptionsBundle =
|
||||
PersistableBundleUtils.fromList(
|
||||
new ArrayList<>(mGatewayOptions),
|
||||
PersistableBundleUtils.INTEGER_SERIALIZER);
|
||||
|
||||
result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
|
||||
result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
|
||||
result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
|
||||
result.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, networkTemplatesBundle);
|
||||
result.putPersistableBundle(GATEWAY_OPTIONS_KEY, gatewayOptionsBundle);
|
||||
result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
|
||||
result.putInt(MAX_MTU_KEY, mMaxMtu);
|
||||
|
||||
@@ -437,7 +511,8 @@ public final class VcnGatewayConnectionConfig {
|
||||
mExposedCapabilities,
|
||||
mUnderlyingNetworkTemplates,
|
||||
Arrays.hashCode(mRetryIntervalsMs),
|
||||
mMaxMtu);
|
||||
mMaxMtu,
|
||||
mGatewayOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -452,7 +527,8 @@ public final class VcnGatewayConnectionConfig {
|
||||
&& mExposedCapabilities.equals(rhs.mExposedCapabilities)
|
||||
&& mUnderlyingNetworkTemplates.equals(rhs.mUnderlyingNetworkTemplates)
|
||||
&& Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
|
||||
&& mMaxMtu == rhs.mMaxMtu;
|
||||
&& mMaxMtu == rhs.mMaxMtu
|
||||
&& mGatewayOptions.equals(rhs.mGatewayOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -470,6 +546,8 @@ public final class VcnGatewayConnectionConfig {
|
||||
@NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
|
||||
private int mMaxMtu = DEFAULT_MAX_MTU;
|
||||
|
||||
@NonNull private final Set<Integer> mGatewayOptions = new ArraySet<>();
|
||||
|
||||
// TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent.
|
||||
// Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS
|
||||
// when on Cell.
|
||||
@@ -627,6 +705,36 @@ public final class VcnGatewayConnectionConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the specified VCN gateway option.
|
||||
*
|
||||
* @param option the option to be enabled
|
||||
* @return this {@link Builder} instance, for chaining
|
||||
* @throws IllegalArgumentException if the provided option is invalid
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public Builder addGatewayOption(@VcnGatewayOption int option) {
|
||||
validateGatewayOption(option);
|
||||
mGatewayOptions.add(option);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets (disables) the specified VCN gateway option.
|
||||
*
|
||||
* @param option the option to be disabled
|
||||
* @return this {@link Builder} instance, for chaining
|
||||
* @throws IllegalArgumentException if the provided option is invalid
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public Builder removeGatewayOption(@VcnGatewayOption int option) {
|
||||
validateGatewayOption(option);
|
||||
mGatewayOptions.remove(option);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and validates the VcnGatewayConnectionConfig.
|
||||
*
|
||||
@@ -640,7 +748,8 @@ public final class VcnGatewayConnectionConfig {
|
||||
mExposedCapabilities,
|
||||
mUnderlyingNetworkTemplates,
|
||||
mRetryIntervalsMs,
|
||||
mMaxMtu);
|
||||
mMaxMtu,
|
||||
mGatewayOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@ package android.net.vcn;
|
||||
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
|
||||
import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES;
|
||||
import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_TEMPLATES_KEY;
|
||||
import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -42,7 +44,9 @@ import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -79,6 +83,9 @@ public class VcnGatewayConnectionConfigTest {
|
||||
};
|
||||
public static final int MAX_MTU = 1360;
|
||||
|
||||
private static final Set<Integer> GATEWAY_OPTIONS =
|
||||
Collections.singleton(VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY);
|
||||
|
||||
public static final IkeTunnelConnectionParams TUNNEL_CONNECTION_PARAMS =
|
||||
TunnelConnectionParamsUtilsTest.buildTestParams();
|
||||
|
||||
@@ -109,10 +116,16 @@ public class VcnGatewayConnectionConfigTest {
|
||||
TUNNEL_CONNECTION_PARAMS);
|
||||
}
|
||||
|
||||
private static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(
|
||||
VcnGatewayConnectionConfig.Builder builder, int... exposedCaps) {
|
||||
private static VcnGatewayConnectionConfig buildTestConfigWithExposedCapsAndOptions(
|
||||
VcnGatewayConnectionConfig.Builder builder,
|
||||
Set<Integer> gatewayOptions,
|
||||
int... exposedCaps) {
|
||||
builder.setRetryIntervalsMillis(RETRY_INTERVALS_MS).setMaxMtu(MAX_MTU);
|
||||
|
||||
for (int option : gatewayOptions) {
|
||||
builder.addGatewayOption(option);
|
||||
}
|
||||
|
||||
for (int caps : exposedCaps) {
|
||||
builder.addExposedCapability(caps);
|
||||
}
|
||||
@@ -120,11 +133,27 @@ public class VcnGatewayConnectionConfigTest {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(
|
||||
VcnGatewayConnectionConfig.Builder builder, int... exposedCaps) {
|
||||
return buildTestConfigWithExposedCapsAndOptions(
|
||||
builder, Collections.emptySet(), exposedCaps);
|
||||
}
|
||||
|
||||
// Public for use in VcnGatewayConnectionTest
|
||||
public static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(int... exposedCaps) {
|
||||
return buildTestConfigWithExposedCaps(newBuilder(), exposedCaps);
|
||||
}
|
||||
|
||||
private static VcnGatewayConnectionConfig buildTestConfigWithGatewayOptions(
|
||||
VcnGatewayConnectionConfig.Builder builder, Set<Integer> gatewayOptions) {
|
||||
return buildTestConfigWithExposedCapsAndOptions(builder, gatewayOptions, EXPOSED_CAPS);
|
||||
}
|
||||
|
||||
private static VcnGatewayConnectionConfig buildTestConfigWithGatewayOptions(
|
||||
Set<Integer> gatewayOptions) {
|
||||
return buildTestConfigWithExposedCapsAndOptions(newBuilder(), gatewayOptions, EXPOSED_CAPS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderRequiresNonNullGatewayConnectionName() {
|
||||
try {
|
||||
@@ -210,6 +239,15 @@ public class VcnGatewayConnectionConfigTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderRequiresValidOption() {
|
||||
try {
|
||||
newBuilder().addGatewayOption(-1);
|
||||
fail("Expected exception due to the invalid VCN gateway option");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderAndGetters() {
|
||||
final VcnGatewayConnectionConfig config = buildTestConfig();
|
||||
@@ -225,6 +263,20 @@ public class VcnGatewayConnectionConfigTest {
|
||||
|
||||
assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis());
|
||||
assertEquals(MAX_MTU, config.getMaxMtu());
|
||||
|
||||
assertFalse(
|
||||
config.hasGatewayOption(
|
||||
VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderAndGettersWithOptions() {
|
||||
final VcnGatewayConnectionConfig config =
|
||||
buildTestConfigWithGatewayOptions(GATEWAY_OPTIONS);
|
||||
|
||||
for (int option : GATEWAY_OPTIONS) {
|
||||
assertTrue(config.hasGatewayOption(option));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -234,6 +286,14 @@ public class VcnGatewayConnectionConfigTest {
|
||||
assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistableBundleWithOptions() {
|
||||
final VcnGatewayConnectionConfig config =
|
||||
buildTestConfigWithGatewayOptions(GATEWAY_OPTIONS);
|
||||
|
||||
assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePersistableBundleWithoutVcnUnderlyingNetworkTemplates() {
|
||||
PersistableBundle configBundle = buildTestConfig().toPersistableBundle();
|
||||
@@ -318,4 +378,27 @@ public class VcnGatewayConnectionConfigTest {
|
||||
assertNotEquals(UNDERLYING_NETWORK_TEMPLATES, networkTemplatesNotEqual);
|
||||
assertNotEquals(config, configNotEqual);
|
||||
}
|
||||
|
||||
private static VcnGatewayConnectionConfig buildConfigWithGatewayOptionsForEqualityTest(
|
||||
Set<Integer> gatewayOptions) {
|
||||
return buildTestConfigWithGatewayOptions(
|
||||
new VcnGatewayConnectionConfig.Builder(
|
||||
"buildConfigWithGatewayOptionsForEqualityTest", TUNNEL_CONNECTION_PARAMS),
|
||||
gatewayOptions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVcnGatewayOptionsEquality() throws Exception {
|
||||
final VcnGatewayConnectionConfig config =
|
||||
buildConfigWithGatewayOptionsForEqualityTest(GATEWAY_OPTIONS);
|
||||
|
||||
final VcnGatewayConnectionConfig configEqual =
|
||||
buildConfigWithGatewayOptionsForEqualityTest(GATEWAY_OPTIONS);
|
||||
|
||||
final VcnGatewayConnectionConfig configNotEqual =
|
||||
buildConfigWithGatewayOptionsForEqualityTest(Collections.emptySet());
|
||||
|
||||
assertEquals(config, configEqual);
|
||||
assertNotEquals(config, configNotEqual);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user