Merge changes I2d6f80f0,I9c26852d
* changes: Use device option to control BPF offload features Add tether BPF offload config to device config and resource
This commit is contained in:
@@ -55,6 +55,12 @@
|
|||||||
<item>"bt-pan"</item>
|
<item>"bt-pan"</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Use the BPF offload for tethering when the kernel has support. True by default.
|
||||||
|
If the device doesn't want to support tether BPF offload, this should be false.
|
||||||
|
Note that this setting could be override by device config.
|
||||||
|
-->
|
||||||
|
<bool translatable="false" name="config_tether_enable_bpf_offload">true</bool>
|
||||||
|
|
||||||
<!-- Use the old dnsmasq DHCP server for tethering instead of the framework implementation. -->
|
<!-- Use the old dnsmasq DHCP server for tethering instead of the framework implementation. -->
|
||||||
<bool translatable="false" name="config_tether_enable_legacy_dhcp_server">false</bool>
|
<bool translatable="false" name="config_tether_enable_legacy_dhcp_server">false</bool>
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,11 @@
|
|||||||
<item type="array" name="config_tether_wifi_p2p_regexs"/>
|
<item type="array" name="config_tether_wifi_p2p_regexs"/>
|
||||||
<item type="array" name="config_tether_bluetooth_regexs"/>
|
<item type="array" name="config_tether_bluetooth_regexs"/>
|
||||||
<item type="array" name="config_tether_dhcp_range"/>
|
<item type="array" name="config_tether_dhcp_range"/>
|
||||||
|
<!-- Use the BPF offload for tethering when the kernel has support. True by default.
|
||||||
|
If the device doesn't want to support tether BPF offload, this should be false.
|
||||||
|
Note that this setting could be override by device config.
|
||||||
|
-->
|
||||||
|
<item type="bool" name="config_tether_enable_bpf_offload"/>
|
||||||
<item type="bool" name="config_tether_enable_legacy_dhcp_server"/>
|
<item type="bool" name="config_tether_enable_legacy_dhcp_server"/>
|
||||||
<item type="integer" name="config_tether_offload_poll_interval"/>
|
<item type="integer" name="config_tether_offload_poll_interval"/>
|
||||||
<item type="array" name="config_tether_upstream_types"/>
|
<item type="array" name="config_tether_upstream_types"/>
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ public class IpServer extends StateMachine {
|
|||||||
private final int mInterfaceType;
|
private final int mInterfaceType;
|
||||||
private final LinkProperties mLinkProperties;
|
private final LinkProperties mLinkProperties;
|
||||||
private final boolean mUsingLegacyDhcp;
|
private final boolean mUsingLegacyDhcp;
|
||||||
|
private final boolean mUsingBpfOffload;
|
||||||
|
|
||||||
private final Dependencies mDeps;
|
private final Dependencies mDeps;
|
||||||
|
|
||||||
@@ -304,7 +305,8 @@ public class IpServer extends StateMachine {
|
|||||||
|
|
||||||
public IpServer(
|
public IpServer(
|
||||||
String ifaceName, Looper looper, int interfaceType, SharedLog log,
|
String ifaceName, Looper looper, int interfaceType, SharedLog log,
|
||||||
INetd netd, Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
|
INetd netd, Callback callback, boolean usingLegacyDhcp, boolean usingBpfOffload,
|
||||||
|
Dependencies deps) {
|
||||||
super(ifaceName, looper);
|
super(ifaceName, looper);
|
||||||
mLog = log.forSubComponent(ifaceName);
|
mLog = log.forSubComponent(ifaceName);
|
||||||
mNetd = netd;
|
mNetd = netd;
|
||||||
@@ -314,6 +316,7 @@ public class IpServer extends StateMachine {
|
|||||||
mInterfaceType = interfaceType;
|
mInterfaceType = interfaceType;
|
||||||
mLinkProperties = new LinkProperties();
|
mLinkProperties = new LinkProperties();
|
||||||
mUsingLegacyDhcp = usingLegacyDhcp;
|
mUsingLegacyDhcp = usingLegacyDhcp;
|
||||||
|
mUsingBpfOffload = usingBpfOffload;
|
||||||
mDeps = deps;
|
mDeps = deps;
|
||||||
resetLinkProperties();
|
resetLinkProperties();
|
||||||
mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
|
mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||||
@@ -321,8 +324,15 @@ public class IpServer extends StateMachine {
|
|||||||
|
|
||||||
mIpNeighborMonitor = mDeps.getIpNeighborMonitor(getHandler(), mLog,
|
mIpNeighborMonitor = mDeps.getIpNeighborMonitor(getHandler(), mLog,
|
||||||
new MyNeighborEventConsumer());
|
new MyNeighborEventConsumer());
|
||||||
if (!mIpNeighborMonitor.start()) {
|
|
||||||
mLog.e("Failed to create IpNeighborMonitor on " + mIfaceName);
|
// IP neighbor monitor monitors the neighbor event for adding/removing offload
|
||||||
|
// forwarding rules per client. If BPF offload is not supported, don't start listening
|
||||||
|
// neighbor events. See updateIpv6ForwardingRules, addIpv6ForwardingRule,
|
||||||
|
// removeIpv6ForwardingRule.
|
||||||
|
if (mUsingBpfOffload) {
|
||||||
|
if (!mIpNeighborMonitor.start()) {
|
||||||
|
mLog.e("Failed to create IpNeighborMonitor on " + mIfaceName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mInitialState = new InitialState();
|
mInitialState = new InitialState();
|
||||||
@@ -715,12 +725,12 @@ public class IpServer extends StateMachine {
|
|||||||
final String upstreamIface = v6only.getInterfaceName();
|
final String upstreamIface = v6only.getInterfaceName();
|
||||||
|
|
||||||
params = new RaParams();
|
params = new RaParams();
|
||||||
// We advertise an mtu lower by 16, which is the closest multiple of 8 >= 14,
|
// When BPF offload is enabled, we advertise an mtu lower by 16, which is the closest
|
||||||
// the ethernet header size. This makes kernel ebpf tethering offload happy.
|
// multiple of 8 >= 14, the ethernet header size. This makes kernel ebpf tethering
|
||||||
// This hack should be reverted once we have the kernel fixed up.
|
// offload happy. This hack should be reverted once we have the kernel fixed up.
|
||||||
// Note: this will automatically clamp to at least 1280 (ipv6 minimum mtu)
|
// Note: this will automatically clamp to at least 1280 (ipv6 minimum mtu)
|
||||||
// see RouterAdvertisementDaemon.java putMtu()
|
// see RouterAdvertisementDaemon.java putMtu()
|
||||||
params.mtu = v6only.getMtu() - 16;
|
params.mtu = mUsingBpfOffload ? v6only.getMtu() - 16 : v6only.getMtu();
|
||||||
params.hasDefaultRoute = v6only.hasIpv6DefaultRoute();
|
params.hasDefaultRoute = v6only.hasIpv6DefaultRoute();
|
||||||
|
|
||||||
if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface);
|
if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface);
|
||||||
@@ -844,6 +854,11 @@ public class IpServer extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addIpv6ForwardingRule(Ipv6ForwardingRule rule) {
|
private void addIpv6ForwardingRule(Ipv6ForwardingRule rule) {
|
||||||
|
// Theoretically, we don't need this check because IP neighbor monitor doesn't start if BPF
|
||||||
|
// offload is disabled. Add this check just in case.
|
||||||
|
// TODO: Perhaps remove this protection check.
|
||||||
|
if (!mUsingBpfOffload) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel());
|
mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel());
|
||||||
mIpv6ForwardingRules.put(rule.address, rule);
|
mIpv6ForwardingRules.put(rule.address, rule);
|
||||||
@@ -853,6 +868,11 @@ public class IpServer extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule, boolean removeFromMap) {
|
private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule, boolean removeFromMap) {
|
||||||
|
// Theoretically, we don't need this check because IP neighbor monitor doesn't start if BPF
|
||||||
|
// offload is disabled. Add this check just in case.
|
||||||
|
// TODO: Perhaps remove this protection check.
|
||||||
|
if (!mUsingBpfOffload) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel());
|
mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel());
|
||||||
if (removeFromMap) {
|
if (removeFromMap) {
|
||||||
|
|||||||
@@ -2296,7 +2296,7 @@ public class Tethering {
|
|||||||
final TetherState tetherState = new TetherState(
|
final TetherState tetherState = new TetherState(
|
||||||
new IpServer(iface, mLooper, interfaceType, mLog, mNetd,
|
new IpServer(iface, mLooper, interfaceType, mLog, mNetd,
|
||||||
makeControlCallback(), mConfig.enableLegacyDhcpServer,
|
makeControlCallback(), mConfig.enableLegacyDhcpServer,
|
||||||
mDeps.getIpServerDependencies()));
|
mConfig.enableBpfOffload, mDeps.getIpServerDependencies()));
|
||||||
mTetherStates.put(iface, tetherState);
|
mTetherStates.put(iface, tetherState);
|
||||||
tetherState.ipServer.start();
|
tetherState.ipServer.start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,12 @@ public class TetheringConfiguration {
|
|||||||
|
|
||||||
private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
|
private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override enabling BPF offload configuration for tethering.
|
||||||
|
*/
|
||||||
|
public static final String OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD =
|
||||||
|
"override_tether_enable_bpf_offload";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
|
* Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
|
||||||
*/
|
*/
|
||||||
@@ -95,6 +101,8 @@ public class TetheringConfiguration {
|
|||||||
public final String[] legacyDhcpRanges;
|
public final String[] legacyDhcpRanges;
|
||||||
public final String[] defaultIPv4DNS;
|
public final String[] defaultIPv4DNS;
|
||||||
public final boolean enableLegacyDhcpServer;
|
public final boolean enableLegacyDhcpServer;
|
||||||
|
// TODO: Add to TetheringConfigurationParcel if required.
|
||||||
|
public final boolean enableBpfOffload;
|
||||||
|
|
||||||
public final String[] provisioningApp;
|
public final String[] provisioningApp;
|
||||||
public final String provisioningAppNoUi;
|
public final String provisioningAppNoUi;
|
||||||
@@ -124,11 +132,12 @@ public class TetheringConfiguration {
|
|||||||
isDunRequired = checkDunRequired(ctx);
|
isDunRequired = checkDunRequired(ctx);
|
||||||
|
|
||||||
chooseUpstreamAutomatically = getResourceBoolean(
|
chooseUpstreamAutomatically = getResourceBoolean(
|
||||||
res, R.bool.config_tether_upstream_automatic);
|
res, R.bool.config_tether_upstream_automatic, false /** default value */);
|
||||||
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
|
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
|
||||||
|
|
||||||
legacyDhcpRanges = getLegacyDhcpRanges(res);
|
legacyDhcpRanges = getLegacyDhcpRanges(res);
|
||||||
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
|
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
|
||||||
|
enableBpfOffload = getEnableBpfOffload(res);
|
||||||
enableLegacyDhcpServer = getEnableLegacyDhcpServer(res);
|
enableLegacyDhcpServer = getEnableLegacyDhcpServer(res);
|
||||||
|
|
||||||
provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app);
|
provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app);
|
||||||
@@ -208,6 +217,9 @@ public class TetheringConfiguration {
|
|||||||
pw.print("provisioningAppNoUi: ");
|
pw.print("provisioningAppNoUi: ");
|
||||||
pw.println(provisioningAppNoUi);
|
pw.println(provisioningAppNoUi);
|
||||||
|
|
||||||
|
pw.print("enableBpfOffload: ");
|
||||||
|
pw.println(enableBpfOffload);
|
||||||
|
|
||||||
pw.print("enableLegacyDhcpServer: ");
|
pw.print("enableLegacyDhcpServer: ");
|
||||||
pw.println(enableLegacyDhcpServer);
|
pw.println(enableLegacyDhcpServer);
|
||||||
}
|
}
|
||||||
@@ -228,6 +240,7 @@ public class TetheringConfiguration {
|
|||||||
toIntArray(preferredUpstreamIfaceTypes)));
|
toIntArray(preferredUpstreamIfaceTypes)));
|
||||||
sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
|
sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
|
||||||
sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
|
sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
|
||||||
|
sj.add(String.format("enableBpfOffload:%s", enableBpfOffload));
|
||||||
sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
|
sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
|
||||||
return String.format("TetheringConfiguration{%s}", sj.toString());
|
return String.format("TetheringConfiguration{%s}", sj.toString());
|
||||||
}
|
}
|
||||||
@@ -332,11 +345,11 @@ public class TetheringConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean getResourceBoolean(Resources res, int resId) {
|
private static boolean getResourceBoolean(Resources res, int resId, boolean defaultValue) {
|
||||||
try {
|
try {
|
||||||
return res.getBoolean(resId);
|
return res.getBoolean(resId);
|
||||||
} catch (Resources.NotFoundException e404) {
|
} catch (Resources.NotFoundException e404) {
|
||||||
return false;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,8 +370,29 @@ public class TetheringConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean getEnableBpfOffload(final Resources res) {
|
||||||
|
// Get BPF offload config
|
||||||
|
// Priority 1: Device config
|
||||||
|
// Priority 2: Resource config
|
||||||
|
// Priority 3: Default value
|
||||||
|
final boolean resourceValue = getResourceBoolean(
|
||||||
|
res, R.bool.config_tether_enable_bpf_offload, true /** default value */);
|
||||||
|
|
||||||
|
// Due to the limitation of static mock for testing, using #getProperty directly instead
|
||||||
|
// of getDeviceConfigBoolean. getDeviceConfigBoolean is not invoked because it uses
|
||||||
|
// #getBoolean to get the boolean device config. The test can't know that the returned
|
||||||
|
// boolean value comes from device config or default value (because of null property
|
||||||
|
// string). Because the test would like to verify null property boolean string case,
|
||||||
|
// use DeviceConfig.getProperty here. See also the test case testBpfOffload{*} in
|
||||||
|
// TetheringConfigurationTest.java.
|
||||||
|
final String value = DeviceConfig.getProperty(
|
||||||
|
NAMESPACE_CONNECTIVITY, OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD);
|
||||||
|
return (value != null) ? Boolean.parseBoolean(value) : resourceValue;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean getEnableLegacyDhcpServer(final Resources res) {
|
private boolean getEnableLegacyDhcpServer(final Resources res) {
|
||||||
return getResourceBoolean(res, R.bool.config_tether_enable_legacy_dhcp_server)
|
return getResourceBoolean(
|
||||||
|
res, R.bool.config_tether_enable_legacy_dhcp_server, false /** default value */)
|
||||||
|| getDeviceConfigBoolean(TETHER_ENABLE_LEGACY_DHCP_SERVER);
|
|| getDeviceConfigBoolean(TETHER_ENABLE_LEGACY_DHCP_SERVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ public class IpServerTest {
|
|||||||
private static final String BLUETOOTH_IFACE_ADDR = "192.168.42.1";
|
private static final String BLUETOOTH_IFACE_ADDR = "192.168.42.1";
|
||||||
private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
|
private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
|
||||||
private static final int DHCP_LEASE_TIME_SECS = 3600;
|
private static final int DHCP_LEASE_TIME_SECS = 3600;
|
||||||
|
private static final boolean DEFAULT_USING_BPF_OFFLOAD = true;
|
||||||
|
|
||||||
private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
|
private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
|
||||||
IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
|
IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
|
||||||
@@ -130,10 +131,11 @@ public class IpServerTest {
|
|||||||
private NeighborEventConsumer mNeighborEventConsumer;
|
private NeighborEventConsumer mNeighborEventConsumer;
|
||||||
|
|
||||||
private void initStateMachine(int interfaceType) throws Exception {
|
private void initStateMachine(int interfaceType) throws Exception {
|
||||||
initStateMachine(interfaceType, false /* usingLegacyDhcp */);
|
initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initStateMachine(int interfaceType, boolean usingLegacyDhcp) throws Exception {
|
private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
|
||||||
|
boolean usingBpfOffload) throws Exception {
|
||||||
doAnswer(inv -> {
|
doAnswer(inv -> {
|
||||||
final IDhcpServerCallbacks cb = inv.getArgument(2);
|
final IDhcpServerCallbacks cb = inv.getArgument(2);
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
@@ -165,7 +167,7 @@ public class IpServerTest {
|
|||||||
|
|
||||||
mIpServer = new IpServer(
|
mIpServer = new IpServer(
|
||||||
IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd,
|
IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd,
|
||||||
mCallback, usingLegacyDhcp, mDependencies);
|
mCallback, usingLegacyDhcp, usingBpfOffload, mDependencies);
|
||||||
mIpServer.start();
|
mIpServer.start();
|
||||||
mNeighborEventConsumer = neighborCaptor.getValue();
|
mNeighborEventConsumer = neighborCaptor.getValue();
|
||||||
|
|
||||||
@@ -179,12 +181,13 @@ public class IpServerTest {
|
|||||||
|
|
||||||
private void initTetheredStateMachine(int interfaceType, String upstreamIface)
|
private void initTetheredStateMachine(int interfaceType, String upstreamIface)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
initTetheredStateMachine(interfaceType, upstreamIface, false);
|
initTetheredStateMachine(interfaceType, upstreamIface, false,
|
||||||
|
DEFAULT_USING_BPF_OFFLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initTetheredStateMachine(int interfaceType, String upstreamIface,
|
private void initTetheredStateMachine(int interfaceType, String upstreamIface,
|
||||||
boolean usingLegacyDhcp) throws Exception {
|
boolean usingLegacyDhcp, boolean usingBpfOffload) throws Exception {
|
||||||
initStateMachine(interfaceType, usingLegacyDhcp);
|
initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload);
|
||||||
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||||
if (upstreamIface != null) {
|
if (upstreamIface != null) {
|
||||||
LinkProperties lp = new LinkProperties();
|
LinkProperties lp = new LinkProperties();
|
||||||
@@ -204,7 +207,8 @@ public class IpServerTest {
|
|||||||
when(mDependencies.getIpNeighborMonitor(any(), any(), any()))
|
when(mDependencies.getIpNeighborMonitor(any(), any(), any()))
|
||||||
.thenReturn(mIpNeighborMonitor);
|
.thenReturn(mIpNeighborMonitor);
|
||||||
mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
|
mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
|
||||||
mNetd, mCallback, false /* usingLegacyDhcp */, mDependencies);
|
mNetd, mCallback, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD,
|
||||||
|
mDependencies);
|
||||||
mIpServer.start();
|
mIpServer.start();
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
verify(mCallback).updateInterfaceState(
|
verify(mCallback).updateInterfaceState(
|
||||||
@@ -494,7 +498,8 @@ public class IpServerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doesNotStartDhcpServerIfDisabled() throws Exception {
|
public void doesNotStartDhcpServerIfDisabled() throws Exception {
|
||||||
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */);
|
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */,
|
||||||
|
DEFAULT_USING_BPF_OFFLOAD);
|
||||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
||||||
|
|
||||||
verify(mDependencies, never()).makeDhcpServer(any(), any(), any());
|
verify(mDependencies, never()).makeDhcpServer(any(), any(), any());
|
||||||
@@ -577,7 +582,8 @@ public class IpServerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addRemoveipv6ForwardingRules() throws Exception {
|
public void addRemoveipv6ForwardingRules() throws Exception {
|
||||||
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */);
|
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
|
||||||
|
DEFAULT_USING_BPF_OFFLOAD);
|
||||||
|
|
||||||
final int myIfindex = TEST_IFACE_PARAMS.index;
|
final int myIfindex = TEST_IFACE_PARAMS.index;
|
||||||
final int notMyIfindex = myIfindex - 1;
|
final int notMyIfindex = myIfindex - 1;
|
||||||
@@ -678,6 +684,53 @@ public class IpServerTest {
|
|||||||
reset(mNetd);
|
reset(mNetd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void enableDisableUsingBpfOffload() throws Exception {
|
||||||
|
final int myIfindex = TEST_IFACE_PARAMS.index;
|
||||||
|
final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
|
||||||
|
final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a");
|
||||||
|
final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00");
|
||||||
|
|
||||||
|
reset(mNetd);
|
||||||
|
|
||||||
|
// Expect that rules can be only added/removed when the BPF offload config is enabled.
|
||||||
|
// Note that the usingBpfOffload false case is not a realistic test case. Because IP
|
||||||
|
// neighbor monitor doesn't start if BPF offload is disabled, there should have no
|
||||||
|
// neighbor event listening. This is used for testing the protection check just in case.
|
||||||
|
// TODO: Perhaps remove this test once we don't need this check anymore.
|
||||||
|
for (boolean usingBpfOffload : new boolean[]{true, false}) {
|
||||||
|
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
|
||||||
|
usingBpfOffload);
|
||||||
|
|
||||||
|
// A neighbor is added.
|
||||||
|
recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
|
||||||
|
if (usingBpfOffload) {
|
||||||
|
verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neigh, macA));
|
||||||
|
} else {
|
||||||
|
verify(mNetd, never()).tetherOffloadRuleAdd(any());
|
||||||
|
}
|
||||||
|
reset(mNetd);
|
||||||
|
|
||||||
|
// A neighbor is deleted.
|
||||||
|
recvDelNeigh(myIfindex, neigh, NUD_STALE, macA);
|
||||||
|
if (usingBpfOffload) {
|
||||||
|
verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neigh, macNull));
|
||||||
|
} else {
|
||||||
|
verify(mNetd, never()).tetherOffloadRuleRemove(any());
|
||||||
|
}
|
||||||
|
reset(mNetd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doesNotStartIpNeighborMonitorIfBpfOffloadDisabled() throws Exception {
|
||||||
|
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
|
||||||
|
false /* usingBpfOffload */);
|
||||||
|
|
||||||
|
// IP neighbor monitor doesn't start if BPF offload is disabled.
|
||||||
|
verify(mIpNeighborMonitor, never()).start();
|
||||||
|
}
|
||||||
|
|
||||||
private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
|
private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
|
||||||
verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
|
verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
|
||||||
verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
|
verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ public class TetheringConfigurationTest {
|
|||||||
.thenReturn(new String[0]);
|
.thenReturn(new String[0]);
|
||||||
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
|
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
|
||||||
false);
|
false);
|
||||||
|
initializeBpfOffloadConfiguration(true, null /* unset */);
|
||||||
|
|
||||||
mHasTelephonyManager = true;
|
mHasTelephonyManager = true;
|
||||||
mMockContext = new MockContext(mContext);
|
mMockContext = new MockContext(mContext);
|
||||||
mEnableLegacyDhcpServer = false;
|
mEnableLegacyDhcpServer = false;
|
||||||
@@ -278,6 +280,50 @@ public class TetheringConfigurationTest {
|
|||||||
assertFalse(upstreamIterator.hasNext());
|
assertFalse(upstreamIterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeBpfOffloadConfiguration(
|
||||||
|
final boolean fromRes, final String fromDevConfig) {
|
||||||
|
when(mResources.getBoolean(R.bool.config_tether_enable_bpf_offload)).thenReturn(fromRes);
|
||||||
|
doReturn(fromDevConfig).when(
|
||||||
|
() -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
|
||||||
|
eq(TetheringConfiguration.OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBpfOffloadEnabledByResource() {
|
||||||
|
initializeBpfOffloadConfiguration(true, null /* unset */);
|
||||||
|
final TetheringConfiguration enableByRes =
|
||||||
|
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
|
||||||
|
assertTrue(enableByRes.enableBpfOffload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBpfOffloadEnabledByDeviceConfigOverride() {
|
||||||
|
for (boolean res : new boolean[]{true, false}) {
|
||||||
|
initializeBpfOffloadConfiguration(res, "true");
|
||||||
|
final TetheringConfiguration enableByDevConOverride =
|
||||||
|
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
|
||||||
|
assertTrue(enableByDevConOverride.enableBpfOffload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBpfOffloadDisabledByResource() {
|
||||||
|
initializeBpfOffloadConfiguration(false, null /* unset */);
|
||||||
|
final TetheringConfiguration disableByRes =
|
||||||
|
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
|
||||||
|
assertFalse(disableByRes.enableBpfOffload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBpfOffloadDisabledByDeviceConfigOverride() {
|
||||||
|
for (boolean res : new boolean[]{true, false}) {
|
||||||
|
initializeBpfOffloadConfiguration(res, "false");
|
||||||
|
final TetheringConfiguration disableByDevConOverride =
|
||||||
|
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
|
||||||
|
assertFalse(disableByDevConOverride.enableBpfOffload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNewDhcpServerDisabled() {
|
public void testNewDhcpServerDisabled() {
|
||||||
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
|
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
|
||||||
|
|||||||
Reference in New Issue
Block a user