Add kill switch flag for ARP offload in APF
Bug: 346920511
Test: atest NetworkStackTests:android.net.apf.ApfNewTest
Change-Id: I571fdae02cd9d5681b09e279f3267de709df7e1f
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 5eff449..cd82334 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -190,6 +190,7 @@
public boolean shouldHandleLightDoze;
public long minMetricsSessionDurationMs;
public boolean hasClatInterface;
+ public boolean shouldHandleArpOffload;
}
/** A wrapper class of {@link SystemClock} to be mocked in unit tests. */
@@ -287,6 +288,7 @@
// and PIO valid lifetimes.
private final int mAcceptRaMinLft;
private final boolean mShouldHandleLightDoze;
+ private final boolean mShouldHandleArpOffload;
private final NetworkQuirkMetrics mNetworkQuirkMetrics;
private final IpClientRaInfoMetrics mIpClientRaInfoMetrics;
@@ -390,6 +392,7 @@
mMinRdnssLifetimeSec = config.minRdnssLifetimeSec;
mAcceptRaMinLft = config.acceptRaMinLft;
mShouldHandleLightDoze = config.shouldHandleLightDoze;
+ mShouldHandleArpOffload = config.shouldHandleArpOffload;
mDependencies = dependencies;
mNetworkQuirkMetrics = networkQuirkMetrics;
mIpClientRaInfoMetrics = dependencies.getIpClientRaInfoMetrics();
@@ -1631,7 +1634,7 @@
Counter.DROPPED_ARP_OTHER_HOST);
ApfV6Generator v6Gen = tryToConvertToApfV6Generator(gen);
- if (v6Gen != null) {
+ if (v6Gen != null && mShouldHandleArpOffload) {
// Ethernet requires that all packets be at least 60 bytes long
v6Gen.addAllocate(60)
.addPacketCopy(ETHER_SRC_ADDR_OFFSET, ETHER_ADDR_LEN)
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index 304b038..75e1cce 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -46,6 +46,7 @@
import static com.android.net.module.util.NetworkStackConstants.VENDOR_SPECIFIC_IE_ID;
import static com.android.networkstack.apishim.ConstantsShim.IFA_F_MANAGETEMPADDR;
import static com.android.networkstack.apishim.ConstantsShim.IFA_F_NOPREFIXROUTE;
+import static com.android.networkstack.util.NetworkStackUtils.APF_HANDLE_ARP_OFFLOAD_FORCE_DISABLE;
import static com.android.networkstack.util.NetworkStackUtils.APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE;
import static com.android.networkstack.util.NetworkStackUtils.APF_NEW_RA_FILTER_VERSION;
import static com.android.networkstack.util.NetworkStackUtils.APF_POLLING_COUNTERS_VERSION;
@@ -711,6 +712,7 @@
private final boolean mApfShouldHandleLightDoze;
private final boolean mEnableApfPollingCounters;
private final boolean mPopulateLinkAddressLifetime;
+ private final boolean mApfShouldHandleArpOffload;
private InterfaceParams mInterfaceParams;
@@ -957,6 +959,8 @@
// Light doze mode status checking API is only available at T or later releases.
mApfShouldHandleLightDoze = SdkLevel.isAtLeastT() && mDependencies.isFeatureNotChickenedOut(
mContext, APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE);
+ mApfShouldHandleArpOffload = mDependencies.isFeatureNotChickenedOut(
+ mContext, APF_HANDLE_ARP_OFFLOAD_FORCE_DISABLE);
mPopulateLinkAddressLifetime = mDependencies.isFeatureEnabled(context,
IPCLIENT_POPULATE_LINK_ADDRESS_LIFETIME_VERSION);
@@ -2563,6 +2567,7 @@
apfConfig.acceptRaMinLft = 0;
}
apfConfig.shouldHandleLightDoze = mApfShouldHandleLightDoze;
+ apfConfig.shouldHandleArpOffload = mApfShouldHandleArpOffload;
apfConfig.minMetricsSessionDurationMs = mApfCounterPollingIntervalMs;
apfConfig.hasClatInterface = mHasSeenClatInterface;
return mDependencies.maybeCreateApfFilter(mContext, apfConfig, mInterfaceParams,
diff --git a/src/com/android/networkstack/util/NetworkStackUtils.java b/src/com/android/networkstack/util/NetworkStackUtils.java
index 5446119..ac2832b 100755
--- a/src/com/android/networkstack/util/NetworkStackUtils.java
+++ b/src/com/android/networkstack/util/NetworkStackUtils.java
@@ -300,6 +300,12 @@
public static final String IGNORE_TCP_INFO_FOR_BLOCKED_UIDS =
"ignore_tcp_info_for_blocked_uids";
+ /**
+ * Kill switch flag to disable the feature of handle arp offload in Apf.
+ */
+ public static final String APF_HANDLE_ARP_OFFLOAD_FORCE_DISABLE =
+ "apf_handle_arp_offload_force_disable";
+
static {
System.loadLibrary("networkstackutilsjni");
}
diff --git a/tests/unit/src/android/net/apf/ApfNewTest.kt b/tests/unit/src/android/net/apf/ApfNewTest.kt
index 58820e6..6863fb9 100644
--- a/tests/unit/src/android/net/apf/ApfNewTest.kt
+++ b/tests/unit/src/android/net/apf/ApfNewTest.kt
@@ -31,6 +31,7 @@
import android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_OTHER_HOST
import android.net.apf.ApfCounterTracker.Counter.PASSED_ALLOCATE_FAILURE
import android.net.apf.ApfCounterTracker.Counter.PASSED_ARP
+import android.net.apf.ApfCounterTracker.Counter.PASSED_ARP_REQUEST
import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV4
import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV4_FROM_DHCPV4_SERVER
import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_ICMP
@@ -1916,6 +1917,41 @@
}
@Test
+ fun testArpOffloadDisabled() {
+ val apfConfig = getDefaultConfig()
+ apfConfig.shouldHandleArpOffload = false
+ val apfFilter =
+ ApfFilter(
+ context,
+ apfConfig,
+ ifParams,
+ ipClientCallback,
+ metrics,
+ dependencies
+ )
+ verify(ipClientCallback, times(2)).installPacketFilter(any())
+ val linkAddress = LinkAddress(InetAddress.getByAddress(hostIpv4Address), 24)
+ val lp = LinkProperties()
+ lp.addLinkAddress(linkAddress)
+ apfFilter.setLinkProperties(lp)
+ val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java)
+ verify(ipClientCallback, times(3)).installPacketFilter(programCaptor.capture())
+ val program = programCaptor.value
+ val receivedArpPacketBuf = ArpPacket.buildArpPacket(
+ arpBroadcastMacAddress,
+ senderMacAddress,
+ hostIpv4Address,
+ HexDump.hexStringToByteArray("000000000000"),
+ senderIpv4Address,
+ ARP_REQUEST.toShort()
+ )
+ val receivedArpPacket = ByteArray(ARP_ETHER_IPV4_LEN)
+ receivedArpPacketBuf.get(receivedArpPacket)
+ verifyProgramRun(APF_VERSION_6, program, receivedArpPacket, PASSED_ARP_REQUEST)
+ apfFilter.shutdown()
+ }
+
+ @Test
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun testNsFilterNoIPv6() {
`when`(dependencies.getAnycast6Addresses(any())).thenReturn(listOf())
@@ -2332,6 +2368,7 @@
config.multicastFilter = false
config.ieee802_3Filter = false
config.ethTypeBlackList = IntArray(0)
+ config.shouldHandleArpOffload = true
return config
}
}