diff --git a/Tethering/res/values/config.xml b/Tethering/res/values/config.xml index 0412a49e2d..bfec5bc041 100644 --- a/Tethering/res/values/config.xml +++ b/Tethering/res/values/config.xml @@ -78,6 +78,12 @@ false + + 0 + diff --git a/Tethering/res/values/overlayable.xml b/Tethering/res/values/overlayable.xml index 91fbd7d148..7bd905c988 100644 --- a/Tethering/res/values/overlayable.xml +++ b/Tethering/res/values/overlayable.xml @@ -32,6 +32,7 @@ + diff --git a/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java index aaaec17bf9..8d58945476 100644 --- a/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java +++ b/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java @@ -185,6 +185,16 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { return this; } + /** Set leases subnet prefix length. If the value is smaller than server address prefix length, + * this configuration will be ignored. + * + *

If not set, the default value is zero. + */ + public DhcpServingParamsParcelExt setLeasesSubnetPrefixLength(int prefixLength) { + this.leasesSubnetPrefixLength = prefixLength; + return this; + } + private static int[] toIntArray(@NonNull Collection addrs) { int[] res = new int[addrs.size()]; int i = 0; diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java index acd2625b19..c718f4c9a0 100644 --- a/Tethering/src/android/net/ip/IpServer.java +++ b/Tethering/src/android/net/ip/IpServer.java @@ -241,6 +241,7 @@ public class IpServer extends StateMachine { private final LinkProperties mLinkProperties; private final boolean mUsingLegacyDhcp; private final boolean mUsingBpfOffload; + private final int mP2pLeasesSubnetPrefixLength; private final Dependencies mDeps; @@ -299,6 +300,7 @@ public class IpServer extends StateMachine { mLinkProperties = new LinkProperties(); mUsingLegacyDhcp = config.useLegacyDhcpServer(); mUsingBpfOffload = config.isBpfOffloadEnabled(); + mP2pLeasesSubnetPrefixLength = config.getP2pLeasesSubnetPrefixLength(); mPrivateAddressCoordinator = addressCoordinator; mDeps = deps; resetLinkProperties(); @@ -527,6 +529,9 @@ public class IpServer extends StateMachine { @Nullable Inet4Address clientAddr) { final boolean changePrefixOnDecline = (mInterfaceType == TetheringManager.TETHERING_NCM && clientAddr == null); + final int subnetPrefixLength = mInterfaceType == TetheringManager.TETHERING_WIFI_P2P + ? mP2pLeasesSubnetPrefixLength : 0 /* default value */; + return new DhcpServingParamsParcelExt() .setDefaultRouters(defaultRouter) .setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS) @@ -534,7 +539,8 @@ public class IpServer extends StateMachine { .setServerAddr(serverAddr) .setMetered(true) .setSingleClientAddr(clientAddr) - .setChangePrefixOnDecline(changePrefixOnDecline); + .setChangePrefixOnDecline(changePrefixOnDecline) + .setLeasesSubnetPrefixLength(subnetPrefixLength); // TODO: also advertise link MTU } diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java index eaf85899a1..f9f3ed9cc9 100644 --- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java +++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java @@ -149,6 +149,7 @@ public class TetheringConfiguration { // TODO: Add to TetheringConfigurationParcel if required. private final boolean mEnableBpfOffload; private final boolean mEnableWifiP2pDedicatedIp; + private final int mP2pLeasesSubnetPrefixLength; private final int mUsbTetheringFunction; protected final ContentResolver mContentResolver; @@ -214,9 +215,27 @@ public class TetheringConfiguration { R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip, false /* defaultValue */); + mP2pLeasesSubnetPrefixLength = getP2pLeasesSubnetPrefixLengthFromRes(res, configLog); + configLog.log(toString()); } + private int getP2pLeasesSubnetPrefixLengthFromRes(final Resources res, final SharedLog log) { + if (!mEnableWifiP2pDedicatedIp) return 0; + + int prefixLength = getResourceInteger(res, + R.integer.config_p2p_leases_subnet_prefix_length, 0 /* default value */); + + // DhcpLeaseRepository ignores the first and last addresses of the range so the max prefix + // length is 30. + if (prefixLength < 0 || prefixLength > 30) { + log.e("Invalid p2p leases subnet prefix length configuration: " + prefixLength); + return 0; + } + + return prefixLength; + } + /** Check whether using legacy dhcp server. */ public boolean useLegacyDhcpServer() { return mEnableLegacyDhcpServer; @@ -272,6 +291,15 @@ public class TetheringConfiguration { return mEnableWifiP2pDedicatedIp; } + /** + * Get subnet prefix length of dhcp leases for wifi p2p. + * This feature only support when wifi p2p use dedicated address. If + * #shouldEnableWifiP2pDedicatedIp is false, this method would always return 0. + */ + public int getP2pLeasesSubnetPrefixLength() { + return mP2pLeasesSubnetPrefixLength; + } + /** Does the dumping.*/ public void dump(PrintWriter pw) { pw.print("activeDataSubId: "); @@ -310,6 +338,9 @@ public class TetheringConfiguration { pw.print("enableWifiP2pDedicatedIp: "); pw.println(mEnableWifiP2pDedicatedIp); + pw.print("p2pLeasesSubnetPrefixLength: "); + pw.println(mP2pLeasesSubnetPrefixLength); + pw.print("mUsbTetheringFunction: "); pw.println(isUsingNcm() ? "NCM" : "RNDIS"); } diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java index 6488421464..43f1eaa7d7 100644 --- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java @@ -156,6 +156,8 @@ public class IpServerTest { private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24; private static final int DHCP_LEASE_TIME_SECS = 3600; private static final boolean DEFAULT_USING_BPF_OFFLOAD = true; + private static final int DEFAULT_SUBNET_PREFIX_LENGTH = 0; + private static final int P2P_SUBNET_PREFIX_LENGTH = 25; private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams( IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */); @@ -230,6 +232,7 @@ public class IpServerTest { when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(usingBpfOffload); when(mTetherConfig.useLegacyDhcpServer()).thenReturn(usingLegacyDhcp); + when(mTetherConfig.getP2pLeasesSubnetPrefixLength()).thenReturn(P2P_SUBNET_PREFIX_LENGTH); mIpServer = new IpServer( IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mBpfCoordinator, mCallback, mTetherConfig, mAddressCoordinator, mDependencies); @@ -1312,6 +1315,12 @@ public class IpServerTest { if (mIpServer.interfaceType() == TETHERING_NCM) { assertTrue(params.changePrefixOnDecline); } + + if (mIpServer.interfaceType() == TETHERING_WIFI_P2P) { + assertEquals(P2P_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength); + } else { + assertEquals(DEFAULT_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength); + } } private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception { diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java index e8bb31554a..7fcf2b2ae1 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java @@ -616,4 +616,35 @@ public class TetheringConfigurationTest { assertArrayEquals(ncmRegexs, cfg.tetherableNcmRegexs); } + @Test + public void testP2pLeasesSubnetPrefixLength() throws Exception { + when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip)) + .thenReturn(true); + + final int defaultSubnetPrefixLength = 0; + final TetheringConfiguration defaultCfg = + new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertEquals(defaultSubnetPrefixLength, defaultCfg.getP2pLeasesSubnetPrefixLength()); + + final int prefixLengthTooSmall = -1; + when(mResources.getInteger(R.integer.config_p2p_leases_subnet_prefix_length)).thenReturn( + prefixLengthTooSmall); + final TetheringConfiguration tooSmallCfg = + new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertEquals(defaultSubnetPrefixLength, tooSmallCfg.getP2pLeasesSubnetPrefixLength()); + + final int prefixLengthTooLarge = 31; + when(mResources.getInteger(R.integer.config_p2p_leases_subnet_prefix_length)).thenReturn( + prefixLengthTooLarge); + final TetheringConfiguration tooLargeCfg = + new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertEquals(defaultSubnetPrefixLength, tooLargeCfg.getP2pLeasesSubnetPrefixLength()); + + final int p2pLeasesSubnetPrefixLength = 27; + when(mResources.getInteger(R.integer.config_p2p_leases_subnet_prefix_length)).thenReturn( + p2pLeasesSubnetPrefixLength); + final TetheringConfiguration p2pCfg = + new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID); + assertEquals(p2pLeasesSubnetPrefixLength, p2pCfg.getP2pLeasesSubnetPrefixLength()); + } }