Snap for 12032681 from 355c72b7022d4416fc9d227055ea40ffac4d1b17 to mainline-media-release Change-Id: Ie35b13bf6982337ba801d88a1319151dc6ca81ad
diff --git a/Android.bp b/Android.bp index 2dcaa6b..3712ba6 100644 --- a/Android.bp +++ b/Android.bp
@@ -78,7 +78,7 @@ java_defaults { name: "NetworkStackReleaseTargetSdk", min_sdk_version: "30", - target_sdk_version: "34", + target_sdk_version: "35", } java_defaults {
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index b595a9e..451d8c3 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml
@@ -21,6 +21,6 @@ <string name="notification_channel_name_network_venue_info" msgid="6526543187249265733">"اطلاعات محل شبکه"</string> <string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"اعلانهایی که نمایش داده میشوند تا نشان دهند شبکه صفحه اطلاعات محل دارد"</string> <string name="connected" msgid="4563643884927480998">"متصل"</string> - <string name="tap_for_info" msgid="6849746325626883711">"متصل شد / برای مشاهده وبسایت ضربه بزنید"</string> + <string name="tap_for_info" msgid="6849746325626883711">"متصل شد / برای مشاهده وبسایت تکضرب بزنید"</string> <string name="application_label" msgid="1322847171305285454">"مدیر شبکه"</string> </resources>
diff --git a/src/android/net/apf/ApfConstants.java b/src/android/net/apf/ApfConstants.java index fe2cfd8..09be67b 100644 --- a/src/android/net/apf/ApfConstants.java +++ b/src/android/net/apf/ApfConstants.java
@@ -65,7 +65,40 @@ public static final int ICMP6_CHECKSUM_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN + 2; public static final int ICMP6_NS_TARGET_IP_OFFSET = ICMP6_TYPE_OFFSET + 8; public static final int ICMP6_NS_OPTION_TYPE_OFFSET = ICMP6_NS_TARGET_IP_OFFSET + 16; + // From RFC4861: + public static final int ICMP6_RA_HEADER_LEN = 16; + public static final int ICMP6_RA_CHECKSUM_OFFSET = + ETH_HEADER_LEN + IPV6_HEADER_LEN + 2; + public static final int ICMP6_RA_CHECKSUM_LEN = 2; + public static final int ICMP6_RA_OPTION_OFFSET = + ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; + public static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = + ETH_HEADER_LEN + IPV6_HEADER_LEN + 6; + public static final int ICMP6_RA_ROUTER_LIFETIME_LEN = 2; + // Prefix information option. + public static final int ICMP6_PREFIX_OPTION_TYPE = 3; + public static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4; + public static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN = 4; + public static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN = 4; + // From RFC4861: source link-layer address + public static final int ICMP6_SOURCE_LL_ADDRESS_OPTION_TYPE = 1; + // From RFC4861: mtu size option + public static final int ICMP6_MTU_OPTION_TYPE = 5; + // From RFC6106: Recursive DNS Server option + public static final int ICMP6_RDNSS_OPTION_TYPE = 25; + // From RFC6106: DNS Search List option + public static final int ICMP6_DNSSL_OPTION_TYPE = 31; + // From RFC8910: Captive-Portal option + public static final int ICMP6_CAPTIVE_PORTAL_OPTION_TYPE = 37; + // From RFC8781: PREF64 option + public static final int ICMP6_PREF64_OPTION_TYPE = 38; + + // From RFC4191: Route Information option + public static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24; + // Above three options all have the same format: + public static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4; + public static final int ICMP6_4_BYTE_LIFETIME_LEN = 4; public static final int IPPROTO_HOPOPTS = 0; // NOTE: this must be added to the IPv4 header length in MemorySlot.IPV4_HEADER_SIZE
diff --git a/src/android/net/apf/ApfCounterTracker.java b/src/android/net/apf/ApfCounterTracker.java index e86aab1..f5416c5 100644 --- a/src/android/net/apf/ApfCounterTracker.java +++ b/src/android/net/apf/ApfCounterTracker.java
@@ -63,8 +63,10 @@ PASSED_IPV4_UNICAST, PASSED_IPV6_ICMP, PASSED_IPV6_NON_ICMP, - PASSED_IPV6_NS_MULTIPLE_OPTIONS, + PASSED_IPV6_NS_DAD, PASSED_IPV6_NS_NO_ADDRESS, + PASSED_IPV6_NS_NO_SLLA_OPTION, + PASSED_IPV6_NS_TENTATIVE, PASSED_IPV6_UNICAST_NON_ICMP, PASSED_NON_IP_UNICAST, PASSED_MDNS, @@ -83,6 +85,7 @@ DROPPED_IPV6_NON_ICMP_MULTICAST, DROPPED_IPV6_NS_INVALID, DROPPED_IPV6_NS_OTHER_HOST, + DROPPED_IPV6_NS_REPLIED_NON_DAD, DROPPED_802_3_FRAME, DROPPED_ETHERTYPE_NOT_ALLOWED, DROPPED_IPV4_KEEPALIVE_ACK,
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java index 07d4a7b..92c25e7 100644 --- a/src/android/net/apf/ApfFilter.java +++ b/src/android/net/apf/ApfFilter.java
@@ -36,10 +36,28 @@ import static android.net.apf.ApfConstants.ETH_TYPE_MAX; import static android.net.apf.ApfConstants.ETH_TYPE_MIN; import static android.net.apf.ApfConstants.FIXED_ARP_REPLY_HEADER; +import static android.net.apf.ApfConstants.ICMP6_4_BYTE_LIFETIME_LEN; +import static android.net.apf.ApfConstants.ICMP6_4_BYTE_LIFETIME_OFFSET; +import static android.net.apf.ApfConstants.ICMP6_CAPTIVE_PORTAL_OPTION_TYPE; import static android.net.apf.ApfConstants.ICMP6_CHECKSUM_OFFSET; import static android.net.apf.ApfConstants.ICMP6_CODE_OFFSET; +import static android.net.apf.ApfConstants.ICMP6_DNSSL_OPTION_TYPE; +import static android.net.apf.ApfConstants.ICMP6_MTU_OPTION_TYPE; import static android.net.apf.ApfConstants.ICMP6_NS_OPTION_TYPE_OFFSET; import static android.net.apf.ApfConstants.ICMP6_NS_TARGET_IP_OFFSET; +import static android.net.apf.ApfConstants.ICMP6_PREF64_OPTION_TYPE; +import static android.net.apf.ApfConstants.ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN; +import static android.net.apf.ApfConstants.ICMP6_PREFIX_OPTION_TYPE; +import static android.net.apf.ApfConstants.ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN; +import static android.net.apf.ApfConstants.ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET; +import static android.net.apf.ApfConstants.ICMP6_RA_CHECKSUM_LEN; +import static android.net.apf.ApfConstants.ICMP6_RA_CHECKSUM_OFFSET; +import static android.net.apf.ApfConstants.ICMP6_RA_OPTION_OFFSET; +import static android.net.apf.ApfConstants.ICMP6_RA_ROUTER_LIFETIME_LEN; +import static android.net.apf.ApfConstants.ICMP6_RA_ROUTER_LIFETIME_OFFSET; +import static android.net.apf.ApfConstants.ICMP6_RDNSS_OPTION_TYPE; +import static android.net.apf.ApfConstants.ICMP6_ROUTE_INFO_OPTION_TYPE; +import static android.net.apf.ApfConstants.ICMP6_SOURCE_LL_ADDRESS_OPTION_TYPE; import static android.net.apf.ApfConstants.ICMP6_TYPE_OFFSET; import static android.net.apf.ApfConstants.IPPROTO_HOPOPTS; import static android.net.apf.ApfConstants.IPV4_ANY_HOST_ADDRESS; @@ -60,6 +78,7 @@ import static android.net.apf.ApfConstants.IPV6_PAYLOAD_LEN_OFFSET; import static android.net.apf.ApfConstants.IPV6_SOLICITED_NODES_PREFIX; import static android.net.apf.ApfConstants.IPV6_SRC_ADDR_OFFSET; +import static android.net.apf.ApfConstants.IPV6_UNSPECIFIED_ADDRESS; import static android.net.apf.ApfConstants.MDNS_PORT; import static android.net.apf.ApfConstants.TCP_HEADER_SIZE_OFFSET; import static android.net.apf.ApfConstants.TCP_UDP_DESTINATION_PORT_OFFSET; @@ -68,7 +87,9 @@ import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_OTHER_HOST; import static android.net.apf.ApfCounterTracker.Counter.FILTER_AGE_16384THS; import static android.net.apf.ApfCounterTracker.Counter.FILTER_AGE_SECONDS; -import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_MULTIPLE_OPTIONS; +import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_DAD; +import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_NO_SLLA_OPTION; +import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_TENTATIVE; import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_NO_ADDRESS; import static android.net.apf.BaseApfGenerator.MemorySlot; import static android.net.apf.BaseApfGenerator.Register.R0; @@ -93,6 +114,7 @@ import static com.android.net.module.util.NetworkStackConstants.ETHER_SRC_ADDR_OFFSET; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NA_HEADER_LEN; +import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_SLLA; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_TLLA; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_TLLA_LEN; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT; @@ -189,10 +211,10 @@ public int[] ethTypeBlackList; public int minRdnssLifetimeSec; public int acceptRaMinLft; - public boolean shouldHandleLightDoze; public long minMetricsSessionDurationMs; public boolean hasClatInterface; public boolean shouldHandleArpOffload; + public boolean shouldHandleNdOffload; } /** A wrapper class of {@link SystemClock} to be mocked in unit tests. */ @@ -291,8 +313,8 @@ // Tracks the value of /proc/sys/ipv6/conf/$iface/accept_ra_min_lft which affects router, RIO, // and PIO valid lifetimes. private final int mAcceptRaMinLft; - private final boolean mShouldHandleLightDoze; private final boolean mShouldHandleArpOffload; + private final boolean mShouldHandleNdOffload; private final NetworkQuirkMetrics mNetworkQuirkMetrics; private final IpClientRaInfoMetrics mIpClientRaInfoMetrics; @@ -309,9 +331,6 @@ if (!SdkLevel.isAtLeastT()) { return false; } - if (!mShouldHandleLightDoze) { - return false; - } return ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED.equals(intent.getAction()); } @@ -322,9 +341,6 @@ if (!SdkLevel.isAtLeastT()) { return false; } - if (!mShouldHandleLightDoze) { - return false; - } return powerManager.isDeviceLightIdleMode(); } @@ -406,8 +422,8 @@ mDrop802_3Frames = config.ieee802_3Filter; mMinRdnssLifetimeSec = config.minRdnssLifetimeSec; mAcceptRaMinLft = config.acceptRaMinLft; - mShouldHandleLightDoze = config.shouldHandleLightDoze; mShouldHandleArpOffload = config.shouldHandleArpOffload; + mShouldHandleNdOffload = config.shouldHandleNdOffload; mDependencies = dependencies; mNetworkQuirkMetrics = networkQuirkMetrics; mIpClientRaInfoMetrics = dependencies.getIpClientRaInfoMetrics(); @@ -434,7 +450,7 @@ startFilter(); // Listen for doze-mode transition changes to enable/disable the IPv6 multicast filter. - mDependencies.addDeviceIdleReceiver(mDeviceIdleReceiver, mShouldHandleLightDoze); + mDependencies.addDeviceIdleReceiver(mDeviceIdleReceiver); mDependencies.onApfFilterCreated(this); // mReceiveThread is created in startFilter() and halted in shutdown(). @@ -452,10 +468,9 @@ } /** Add receiver for detecting doze mode change */ - public void addDeviceIdleReceiver(@NonNull final BroadcastReceiver receiver, - boolean shouldHandleLightDoze) { + public void addDeviceIdleReceiver(@NonNull final BroadcastReceiver receiver) { final IntentFilter intentFilter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED); - if (SdkLevel.isAtLeastT() && shouldHandleLightDoze) { + if (SdkLevel.isAtLeastT()) { intentFilter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED); } mContext.registerReceiver(receiver, intentFilter); @@ -684,41 +699,6 @@ // A class to hold information about an RA. @VisibleForTesting public class Ra { - // From RFC4861: - private static final int ICMP6_RA_HEADER_LEN = 16; - private static final int ICMP6_RA_CHECKSUM_OFFSET = - ETH_HEADER_LEN + IPV6_HEADER_LEN + 2; - private static final int ICMP6_RA_CHECKSUM_LEN = 2; - private static final int ICMP6_RA_OPTION_OFFSET = - ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; - private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = - ETH_HEADER_LEN + IPV6_HEADER_LEN + 6; - private static final int ICMP6_RA_ROUTER_LIFETIME_LEN = 2; - // Prefix information option. - private static final int ICMP6_PREFIX_OPTION_TYPE = 3; - private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4; - private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN = 4; - private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN = 4; - - // From RFC4861: source link-layer address - private static final int ICMP6_SOURCE_LL_ADDRESS_OPTION_TYPE = 1; - // From RFC4861: mtu size option - private static final int ICMP6_MTU_OPTION_TYPE = 5; - // From RFC6106: Recursive DNS Server option - private static final int ICMP6_RDNSS_OPTION_TYPE = 25; - // From RFC6106: DNS Search List option - private static final int ICMP6_DNSSL_OPTION_TYPE = 31; - // From RFC8910: Captive-Portal option - private static final int ICMP6_CAPTIVE_PORTAL_OPTION_TYPE = 37; - // From RFC8781: PREF64 option - private static final int ICMP6_PREF64_OPTION_TYPE = 38; - - // From RFC4191: Route Information option - private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24; - // Above three options all have the same format: - private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4; - private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4; - // Note: mPacket's position() cannot be assumed to be reset. private final ByteBuffer mPacket; @@ -1949,22 +1929,63 @@ v6Gen.addLoad8(R0, ICMP6_CODE_OFFSET) .addCountAndDropIfR0NotEquals(0, DROPPED_IPV6_NS_INVALID); - // target address (ICMPv6 NS/NA payload) is not interface addresses -> drop - v6Gen.addLoadImmediate(R0, ICMP6_NS_TARGET_IP_OFFSET) - .addCountAndDropIfBytesAtR0EqualsNoneOf(allIPv6Addrs, DROPPED_IPV6_NS_OTHER_HOST); + // target address (ICMPv6 NS payload) + // 1) is one of tentative addresses -> pass + // 2) is none of {non-tentative, anycast} addresses -> drop + final List<byte[]> tentativeIPv6Addrs = getIpv6Addresses( + false, /* includeNonTentative */ + true, /* includeTentative */ + false /* includeAnycast */ + ); + v6Gen.addLoadImmediate(R0, ICMP6_NS_TARGET_IP_OFFSET); + if (!tentativeIPv6Addrs.isEmpty()) { + v6Gen.addCountAndPassIfBytesAtR0EqualsAnyOf( + tentativeIPv6Addrs, PASSED_IPV6_NS_TENTATIVE); + } - // Only offload the following cases: - // 1) NS packet with no options. - // 2) NS packet with only one option: nonce. - // 3) NS packet with only one option: SLLA. - // For packets containing more than one option, - // pass the packet to the CPU for processing. - // payload length > 32 - // (8 bytes ICMP6 header + 16 bytes target address + 8 bytes option) -> pass + final List<byte[]> nonTentativeIpv6Addrs = getIpv6Addresses( + true, /* includeNonTentative */ + false, /* includeTentative */ + true /* includeAnycast */ + ); + if (nonTentativeIpv6Addrs.isEmpty()) { + v6Gen.addCountAndDrop(DROPPED_IPV6_NS_OTHER_HOST); + return; + } + v6Gen.addCountAndDropIfBytesAtR0EqualsNoneOf( + nonTentativeIpv6Addrs, DROPPED_IPV6_NS_OTHER_HOST); + + // if source ip is unspecified (::), it's DAD request -> pass + v6Gen.addLoadImmediate(R0, IPV6_SRC_ADDR_OFFSET) + .addCountAndPassIfBytesAtR0Equal(IPV6_UNSPECIFIED_ADDRESS, PASSED_IPV6_NS_DAD); + + // Only offload NUD/Address resolution packets that have SLLA as the their first option. + // For option-less NUD packets or NUD/Address resolution packets where + // the first option is not SLLA, pass them to the kernel for handling. + // if payload len < 32 -> pass v6Gen.addLoad16(R0, IPV6_PAYLOAD_LEN_OFFSET) - .addCountAndPassIfR0GreaterThan(32, PASSED_IPV6_NS_MULTIPLE_OPTIONS); + .addCountAndPassIfR0LessThan(32, PASSED_IPV6_NS_NO_SLLA_OPTION); - v6Gen.addCountAndPass(Counter.PASSED_IPV6_ICMP); + // if the first option is not SLLA -> pass + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | Type | Length |Link-Layer Addr | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + v6Gen.addLoad8(R0, ICMP6_NS_OPTION_TYPE_OFFSET) + .addCountAndPassIfR0NotEquals(ICMPV6_ND_OPTION_SLLA, + PASSED_IPV6_NS_NO_SLLA_OPTION); + + // Src IPv6 address check: + // if multicast address (FF::/8) or loopback address (00::/8) -> drop + v6Gen.addLoad8(R0, IPV6_SRC_ADDR_OFFSET) + .addCountAndDropIfR0IsOneOf(Set.of(0L, 0xffL), DROPPED_IPV6_NS_INVALID); + + // if multicast MAC in SLLA option -> drop + v6Gen.addLoad8(R0, ICMP6_NS_OPTION_TYPE_OFFSET + 2) + .addCountAndDropIfR0AnyBitsSet(1, DROPPED_IPV6_NS_INVALID); + generateNonDadNaTransmitLocked(v6Gen); + v6Gen.addCountAndDrop(Counter.DROPPED_IPV6_NS_REPLIED_NON_DAD); } /** @@ -2001,10 +2022,19 @@ // drop // if ICMPv6 code is not 0: // drop - // if target IP is none of interface unicast IPv6 addresses (incl. anycast): - // drop - // if payload len > 32 (8 bytes ICMP6 header + 16 bytes target address + 8 bytes option): + // if target IP is one of tentative IPv6 addresses: // pass + // if target IP is none of non-tentative IPv6 addresses (incl. anycast): + // drop + // if IPv6 src is unspecified (::): + // pass + // if payload len < 32 (8 bytes ICMP6 header + 16 bytes target address + 8 bytes option): + // pass + // if IPv6 src is multicast address (FF::/8) or loopback address (00::/8): + // drop + // if multicast MAC in SLLA option: + // drop + // transmit NA and drop // if it's ICMPv6 RS to any: // drop // if it's ICMPv6 NA to anything in ff02::/120 @@ -2056,7 +2086,7 @@ // Not ICMPv6 NS -> skip. gen.addLoad8(R0, ICMP6_TYPE_OFFSET); // warning: also used further below. final ApfV6Generator v6Gen = tryToConvertToApfV6Generator(gen); - if (v6Gen != null) { + if (v6Gen != null && mShouldHandleNdOffload) { final String skipNsPacketFilter = v6Gen.getUniqueLabel(); v6Gen.addJumpIfR0NotEquals(ICMPV6_NEIGHBOR_SOLICITATION, skipNsPacketFilter); generateNsFilterLocked(v6Gen);
diff --git a/src/android/net/apf/BaseApfGenerator.java b/src/android/net/apf/BaseApfGenerator.java index 4f4abb9..2eab5ab 100644 --- a/src/android/net/apf/BaseApfGenerator.java +++ b/src/android/net/apf/BaseApfGenerator.java
@@ -22,6 +22,7 @@ import android.annotation.NonNull; +import com.android.internal.annotations.VisibleForTesting; import com.android.net.module.util.ByteUtils; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.HexDump; @@ -41,10 +42,10 @@ public BaseApfGenerator(int version, int ramSize, int clampSize, boolean disableCounterRangeCheck) { - this.mVersion = version; - this.mRamSize = ramSize; - this.mClampSize = clampSize; - this.mDisableCounterRangeCheck = disableCounterRangeCheck; + mVersion = version; + mRamSize = ramSize; + mClampSize = clampSize; + mDisableCounterRangeCheck = disableCounterRangeCheck; } /** @@ -854,7 +855,8 @@ /** * Return a unique label string. */ - protected String getUniqueLabel() { + @VisibleForTesting + public String getUniqueLabel() { return "LABEL_" + mLabelCount++; }
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java index 9dd9dc5..7b9cd73 100644 --- a/src/android/net/ip/IpClient.java +++ b/src/android/net/ip/IpClient.java
@@ -48,8 +48,8 @@ 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_HANDLE_ARP_OFFLOAD; +import static com.android.networkstack.util.NetworkStackUtils.APF_HANDLE_ND_OFFLOAD; import static com.android.networkstack.util.NetworkStackUtils.APF_NEW_RA_FILTER_VERSION; import static com.android.networkstack.util.NetworkStackUtils.APF_POLLING_COUNTERS_VERSION; import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_DHCPV6_PREFIX_DELEGATION_VERSION; @@ -733,10 +733,10 @@ private final boolean mDhcp6PrefixDelegationEnabled; private final boolean mUseNewApfFilter; private final boolean mEnableIpClientIgnoreLowRaLifetime; - private final boolean mApfShouldHandleLightDoze; private final boolean mEnableApfPollingCounters; private final boolean mPopulateLinkAddressLifetime; private final boolean mApfShouldHandleArpOffload; + private final boolean mApfShouldHandleNdOffload; private InterfaceParams mInterfaceParams; @@ -983,11 +983,10 @@ mEnableIpClientIgnoreLowRaLifetime = SdkLevel.isAtLeastV() || mDependencies.isFeatureEnabled(context, IPCLIENT_IGNORE_LOW_RA_LIFETIME_VERSION); - // 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); + mContext, APF_HANDLE_ARP_OFFLOAD); + mApfShouldHandleNdOffload = mDependencies.isFeatureNotChickenedOut( + mContext, APF_HANDLE_ND_OFFLOAD); mPopulateLinkAddressLifetime = mDependencies.isFeatureEnabled(context, IPCLIENT_POPULATE_LINK_ADDRESS_LIFETIME_VERSION); @@ -2606,8 +2605,8 @@ } else { apfConfig.acceptRaMinLft = 0; } - apfConfig.shouldHandleLightDoze = mApfShouldHandleLightDoze; apfConfig.shouldHandleArpOffload = mApfShouldHandleArpOffload; + apfConfig.shouldHandleNdOffload = mApfShouldHandleNdOffload; apfConfig.minMetricsSessionDurationMs = mApfCounterPollingIntervalMs; apfConfig.hasClatInterface = mHasSeenClatInterface; return mDependencies.maybeCreateApfFilter(mContext, apfConfig, mInterfaceParams,
diff --git a/src/com/android/networkstack/netlink/TcpSocketTracker.java b/src/com/android/networkstack/netlink/TcpSocketTracker.java index 4140e64..0d77dca 100644 --- a/src/com/android/networkstack/netlink/TcpSocketTracker.java +++ b/src/com/android/networkstack/netlink/TcpSocketTracker.java
@@ -50,7 +50,6 @@ import android.net.NetworkCapabilities; import android.os.AsyncTask; import android.os.Build; -import android.os.Handler; import android.os.IBinder; import android.os.PowerManager; import android.os.RemoteException; @@ -67,6 +66,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.DeviceConfigUtils; @@ -133,11 +133,10 @@ private int mMinPacketsThreshold = DEFAULT_DATA_STALL_MIN_PACKETS_THRESHOLD; private int mTcpPacketsFailRateThreshold = DEFAULT_TCP_PACKETS_FAIL_PERCENTAGE; - // These variables are initialized when the NetworkMonitor enters DefaultState, - // and can only be accessed on the NetworkMonitor state machine thread after - // the NetworkMonitor state machine has been started. // TODO: Remove doze mode solution since uid networking blocked traffic is filtered out by // the info provided by bpf maps. + private final Object mDozeModeLock = new Object(); + @GuardedBy("mDozeModeLock") private boolean mInDozeMode = false; // These variables are initialized when the NetworkMonitor enters DefaultState, @@ -227,21 +226,9 @@ family, InetDiagMessage.buildInetDiagReqForAliveTcpSockets(family)); } mDependencies.addDeviceConfigChangedListener(mConfigListener); - - mCm = mDependencies.getContext().getSystemService(ConnectivityManager.class); - } - - /** - * Called from NetworkMonitor to notify NetworkMonitor is created. - * This is for initializing TcpSocketTracker from default state. - */ - public void init(@NonNull final Handler handler, @NonNull LinkProperties lp, - @NonNull NetworkCapabilities nc) { mDependencies.addDeviceIdleReceiver(mDeviceIdleReceiver, mShouldDisableInDeepDoze, - mShouldDisableInLightDoze, handler); - setOpportunisticMode(false); - setLinkProperties(lp); - setNetworkCapabilities(nc); + mShouldDisableInLightDoze); + mCm = mDependencies.getContext().getSystemService(ConnectivityManager.class); } @Nullable @@ -267,7 +254,9 @@ // Traffic will be restricted in doze mode. TCP info may not reflect the correct network // behavior. // TODO: Traffic may be restricted by other reason. Get the restriction info from bpf in T+. - if (mInDozeMode) return false; + synchronized (mDozeModeLock) { + if (mInDozeMode) return false; + } FileDescriptor fd = null; @@ -475,8 +464,10 @@ public boolean isDataStallSuspected() { // Skip checking data stall since the traffic will be restricted and it will not be real // network stall. - if (mInDozeMode) return false; - + // TODO: Traffic may be restricted by other reason. Get the restriction info from bpf in T+. + synchronized (mDozeModeLock) { + if (mInDozeMode) return false; + } final boolean ret = (getLatestPacketFailPercentage() >= getTcpPacketsFailRateThreshold()); if (ret) { log("data stall suspected, uids: " + mLatestReportedUids.toString()); @@ -649,9 +640,11 @@ } private void setDozeMode(boolean isEnabled) { - if (mInDozeMode == isEnabled) return; - mInDozeMode = isEnabled; - logd("Doze mode enabled=" + mInDozeMode); + synchronized (mDozeModeLock) { + if (mInDozeMode == isEnabled) return; + mInDozeMode = isEnabled; + logd("Doze mode enabled=" + mInDozeMode); + } } public void setOpportunisticMode(boolean isEnabled) { @@ -755,8 +748,7 @@ /** Add receiver for detecting doze mode change to control TCP detection. */ @TargetApi(Build.VERSION_CODES.TIRAMISU) public void addDeviceIdleReceiver(@NonNull final BroadcastReceiver receiver, - boolean shouldDisableInDeepDoze, boolean shouldDisableInLightDoze, - @NonNull final Handler handler) { + boolean shouldDisableInDeepDoze, boolean shouldDisableInLightDoze) { // No need to register receiver if no related feature is enabled. if (!shouldDisableInDeepDoze && !shouldDisableInLightDoze) return; @@ -767,8 +759,7 @@ if (shouldDisableInLightDoze) { intentFilter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED); } - mContext.registerReceiver(receiver, intentFilter, null /* broadcastPermission */, - handler); + mContext.registerReceiver(receiver, intentFilter); } /** Remove broadcast receiver. */
diff --git a/src/com/android/networkstack/util/NetworkStackUtils.java b/src/com/android/networkstack/util/NetworkStackUtils.java index ac2832b..a7563f4 100755 --- a/src/com/android/networkstack/util/NetworkStackUtils.java +++ b/src/com/android/networkstack/util/NetworkStackUtils.java
@@ -277,12 +277,6 @@ /**** BEGIN Feature Kill Switch Flags ****/ /** - * Kill switch flag to disable the feature of handle light doze mode in Apf. - */ - public static final String APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE = - "apf_handle_light_doze_force_disable"; - - /** * Kill switch flag to disable the feature of skipping Tcp socket info polling when light * doze mode is enabled. */ @@ -302,9 +296,15 @@ /** * Kill switch flag to disable the feature of handle arp offload in Apf. + * Warning: the following flag String is incorrect. The feature that is not chickened out is + * "ARP offload" not "ARP offload force disabled". */ - public static final String APF_HANDLE_ARP_OFFLOAD_FORCE_DISABLE = - "apf_handle_arp_offload_force_disable"; + public static final String APF_HANDLE_ARP_OFFLOAD = "apf_handle_arp_offload_force_disable"; + + /** + * Kill switch flag to disable the feature of handle nd offload in Apf. + */ + public static final String APF_HANDLE_ND_OFFLOAD = "apf_handle_nd_offload"; static { System.loadLibrary("networkstackutilsjni");
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java index e564cd7..895fc54 100755 --- a/src/com/android/server/connectivity/NetworkMonitor.java +++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -987,7 +987,9 @@ final TcpSocketTracker tst = getTcpSocketTracker(); if (tst != null) { // Initialization. - tst.init(getHandler(), mLinkProperties, mNetworkCapabilities); + tst.setOpportunisticMode(false); + tst.setLinkProperties(mLinkProperties); + tst.setNetworkCapabilities(mNetworkCapabilities); } Log.d(TAG, "Starting on network " + mNetwork + " with capport HTTPS URL " + Arrays.toString(mCaptivePortalHttpsUrls)
diff --git a/tests/unit/src/android/net/apf/ApfNewTest.kt b/tests/unit/src/android/net/apf/ApfNewTest.kt index e4e9150..f016c75 100644 --- a/tests/unit/src/android/net/apf/ApfNewTest.kt +++ b/tests/unit/src/android/net/apf/ApfNewTest.kt
@@ -29,14 +29,17 @@ import android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_NON_DHCP4 import android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_INVALID import android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_OTHER_HOST +import android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_REPLIED_NON_DAD 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 -import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_MULTIPLE_OPTIONS +import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_DAD import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_NO_ADDRESS +import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_NO_SLLA_OPTION +import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_TENTATIVE import android.net.apf.ApfCounterTracker.Counter.PASSED_TRANSMIT_FAILURE import android.net.apf.ApfCounterTracker.Counter.TOTAL_PACKETS import android.net.apf.ApfFilter.Dependencies @@ -64,15 +67,23 @@ import com.android.net.module.util.NetworkStackConstants.ARP_ETHER_IPV4_LEN import com.android.net.module.util.NetworkStackConstants.ARP_REPLY import com.android.net.module.util.NetworkStackConstants.ARP_REQUEST +import com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN +import com.android.net.module.util.NetworkStackConstants.ICMPV6_NA_HEADER_LEN +import com.android.net.module.util.NetworkStackConstants.ICMPV6_NS_HEADER_LEN +import com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN import com.android.net.module.util.Struct import com.android.net.module.util.arp.ArpPacket import com.android.net.module.util.structs.EthernetHeader import com.android.net.module.util.structs.Ipv4Header import com.android.net.module.util.structs.UdpHeader import com.android.networkstack.metrics.NetworkQuirkMetrics +import com.android.networkstack.packets.NeighborAdvertisement +import com.android.networkstack.packets.NeighborSolicitation +import com.android.networkstack.util.NetworkStackUtils import com.android.testutils.DevSdkIgnoreRule import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner +import java.net.Inet6Address import java.net.InetAddress import java.nio.ByteBuffer import kotlin.test.assertContentEquals @@ -131,8 +142,12 @@ private val senderIpv4Address = byteArrayOf(10, 0, 0, 2) private val arpBroadcastMacAddress = intArrayOf(0xff, 0xff, 0xff, 0xff, 0xff, 0xff) .map { it.toByte() }.toByteArray() - private val senderMacAddress = intArrayOf(0x01, 0x22, 0x33, 0x44, 0x55, 0x66) - .map { it.toByte() }.toByteArray() + private val senderMacAddress = intArrayOf(0x02, 0x22, 0x33, 0x44, 0x55, 0x66) + .map { it.toByte() }.toByteArray() + private val senderIpv6Address = + // 2001::200:1a:1122:3344 + intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0x1a, 0x11, 0x22, 0x33, 0x44) + .map{ it.toByte() }.toByteArray() private val hostIpv6Addresses = listOf( // 2001::200:1a:3344:1122 intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0x1a, 0x33, 0x44, 0x11, 0x22) @@ -169,8 +184,12 @@ MockitoAnnotations.initMocks(this) // mock anycast6 address from /proc/net/anycast6 `when`(dependencies.getAnycast6Addresses(any())).thenReturn(hostAnycast6Addresses) - // mock host mac address and ethernet multicast addresses from /proc/net/dev_mcast + + // mock ether multicast mac address from /proc/net/dev_mcast `when`(dependencies.getEtherMulticastAddresses(any())).thenReturn(hostMulticastMacAddresses) + + // mock nd traffic class from /proc/sys/net/ipv6/conf/{ifname}/ndisc_tclass + `when`(dependencies.getNdTrafficClass(any())).thenReturn(0) } @After @@ -616,7 +635,7 @@ program ) assertContentEquals( - listOf("0: drop counter=43"), + listOf("0: drop counter=46"), ApfJniUtils.disassembleApf(program).map { it.trim() } ) @@ -665,14 +684,14 @@ byteArrayOf( encodeInstruction(opcode = 14, immLength = 2, register = 1), 1, 0 ) + largeByteArray + byteArrayOf( - encodeInstruction(opcode = 21, immLength = 1, register = 0), 48, 6, 25 + encodeInstruction(opcode = 21, immLength = 1, register = 0), 48, 6, 13 ), program ) assertContentEquals( listOf( "0: data 256, " + "01".repeat(256), - "259: debugbuf size=1561" + "259: debugbuf size=1549" ), ApfJniUtils.disassembleApf(program).map { it.trim() } ) @@ -958,7 +977,7 @@ .generate() assertContentEquals(listOf( "0: data 9, 112233445566778899", - "12: debugbuf size=1788", + "12: debugbuf size=1776", "16: allocate 18", "20: datacopy src=3, len=6", "23: datacopy src=4, len=3", @@ -2002,13 +2021,15 @@ ) verify(ipClientCallback, times(2)).installPacketFilter(any()) - // validate Ethernet dst address check - val lp = LinkProperties() for (addr in hostIpv6Addresses) { lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64)) } + for (addr in hostIpv6TentativeAddresses) { + lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64, IFA_F_TENTATIVE, 0)) + } + apfFilter.setLinkProperties(lp) verify(ipClientCallback, times(3)).installPacketFilter(any()) apfFilter.updateClatInterfaceState(true) @@ -2016,14 +2037,16 @@ verify(ipClientCallback, times(4)).installPacketFilter(programCaptor.capture()) val program = programCaptor.value + // validate Ethernet dst address check // Using scapy to generate IPv6 NS packet: // eth = Ether(src="00:01:02:03:04:05", dst="00:05:04:03:02:01") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // pkt = eth/ip6/icmp6 - val nonHostDstMacNsPkt = "00050403020100010203040586DD6000000000183AFF2001000000000000" + - "0200001A1122334420010000000000000200001A33441122870045290000" + - "000020010000000000000200001A33441122" + // icmp6_opt = ICMPv6NDOptDstLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val nonHostDstMacNsPkt = "00050403020100010203040586DD6000000000203AFF2001000000000000" + + "0200001A1122334420010000000000000200001A3344112287003D170000" + + "000020010000000000000200001A334411220201000102030405" // invalid unicast ether dst -> pass verifyProgramRun( APF_VERSION_6, @@ -2036,48 +2059,52 @@ // eth = Ether(src="00:01:02:03:04:05", dst="33:33:ff:03:02:01") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // pkt = eth/ip6/icmp6 - val nonMcastDstMacNsPkt = "3333ff03020100010203040586DD6000000000183AFF2001000000000000" + - "0200001A1122334420010000000000000200001A33441122870045290000" + - "000020010000000000000200001A33441122" + // icmp6_opt = ICMPv6NDOptDstLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val nonMcastDstMacNsPkt = "3333FF03020100010203040586DD6000000000203AFF20010000000000" + + "000200001A1122334420010000000000000200001A3344112287003D17" + + "0000000020010000000000000200001A334411220201000102030405" // mcast dst mac is not one of solicited mcast mac derived from one of device's ip -> pass verifyProgramRun( - APF_VERSION_6, - program, - HexDump.hexStringToByteArray(nonMcastDstMacNsPkt), - DROPPED_IPV6_NS_OTHER_HOST + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(nonMcastDstMacNsPkt), + DROPPED_IPV6_NS_OTHER_HOST ) // Using scapy to generate IPv6 NS packet: // eth = Ether(src="00:01:02:03:04:05", dst="33:33:ff:44:11:22") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // pkt = eth/ip6/icmp6 - val hostMcastDstMacNsPkt = "3333ff44112200010203040586DD6000000000183AFF2001000000000000" + - "0200001A1122334420010000000000000200001A33441122870045290000" + - "000020010000000000000200001A33441122" - // mcast dst mac is one of solicited mcast mac derived from one of device's ip -> pass + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val hostMcastDstMacNsPkt = "3333FF44112200010203040586DD6000000000203AFF20010000000000" + + "000200001A1122334420010000000000000200001A3344112287003E17" + + "0000000020010000000000000200001A334411220101000102030405" + // mcast dst mac is one of solicited mcast mac derived from one of device's ip + // -> drop and replied verifyProgramRun( - APF_VERSION_6, - program, - HexDump.hexStringToByteArray(hostMcastDstMacNsPkt), - PASSED_IPV6_ICMP + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(hostMcastDstMacNsPkt), + DROPPED_IPV6_NS_REPLIED_NON_DAD ) // Using scapy to generate IPv6 NS packet: // eth = Ether(src="00:01:02:03:04:05", dst="FF:FF:FF:FF:FF:FF") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // pkt = eth/ip6/icmp6 - val broadcastNsPkt = "FFFFFFFFFFFF00010203040586DD6000000000183AFF2001000000000000" + - "0200001A1122334420010000000000000200001A33441122870045290000" + - "000020010000000000000200001A33441122" - // mcast dst mac is broadcast address -> pass + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val broadcastNsPkt = "FFFFFFFFFFFF00010203040586DD6000000000203AFF200100000000000002000" + + "01A1122334420010000000000000200001A3344112287003E1700000000200100" + + "00000000000200001A334411220101000102030405" + // mcast dst mac is broadcast address -> drop and replied verifyProgramRun( - APF_VERSION_6, - program, - HexDump.hexStringToByteArray(broadcastNsPkt), - PASSED_IPV6_ICMP + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(broadcastNsPkt), + DROPPED_IPV6_NS_REPLIED_NON_DAD ) // validate IPv6 dst address check @@ -2086,80 +2113,87 @@ // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // pkt = eth/ip6/icmp6 - val validHostDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF200100000000000" + - "00200001A1122334420010000000000000200001A334411228700452900" + - "00000020010000000000000200001A33441122" - // dst ip is one of device's ip -> Pass + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val validHostDstIpNsPkt = "02030405060700010203040586DD6000000000203AFF200100000000000" + + "00200001A1122334420010000000000000200001A3344112287003E1700" + + "00000020010000000000000200001A334411220101000102030405" + // dst ip is one of device's ip -> drop and replied verifyProgramRun( APF_VERSION_6, program, HexDump.hexStringToByteArray(validHostDstIpNsPkt), - PASSED_IPV6_ICMP + DROPPED_IPV6_NS_REPLIED_NON_DAD ) // Using scapy to generate IPv6 NS packet: // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::100:1b:aabb:ccdd", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::100:1b:aabb:ccdd") - // pkt = eth/ip6/icmp6 - val validHostAnycastDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF20010000" + + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val validHostAnycastDstIpNsPkt = "02030405060700010203040586DD6000000000203AFF20010000" + "000000000200001A1122334420010000000000000100001BAABB" + - "CCDD8700E0C00000000020010000000000000100001BAABBCCDD" - // dst ip is device's anycast address -> Pass + "CCDD8700D9AE0000000020010000000000000100001BAABBCCDD" + + "0101000102030405" + // dst ip is device's anycast address -> drop and replied verifyProgramRun( APF_VERSION_6, program, HexDump.hexStringToByteArray(validHostAnycastDstIpNsPkt), - PASSED_IPV6_ICMP + DROPPED_IPV6_NS_REPLIED_NON_DAD ) // Using scapy to generate IPv6 NS packet: // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:4444:5555", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // pkt = eth/ip6/icmp6 - val nonHostUcastDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF200100000000" + - "00000200001A1122334420010000000000000200001A444455558700" + - "EFF50000000020010000000000000200001A33441122" + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val nonHostUcastDstIpNsPkt = "02030405060700010203040586DD6000000000203AFF2001000000000" + + "0000200001A1122334420010000000000000200001A444455558700E8" + + "E30000000020010000000000000200001A334411220101000102030405" // unicast dst ip is not one of device's ip -> pass verifyProgramRun( - APF_VERSION_6, - program, - HexDump.hexStringToByteArray(nonHostUcastDstIpNsPkt), - DROPPED_IPV6_NS_OTHER_HOST + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(nonHostUcastDstIpNsPkt), + DROPPED_IPV6_NS_OTHER_HOST ) // Using scapy to generate IPv6 NS packet: // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="ff02::1:ff44:1133", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // pkt = eth/ip6/icmp6 - val nonHostMcastDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF200100000000" + - "00000200001A11223344FF0200000000000000000001FF4411338700" + - "9C2E0000000020010000000000000200001A33441122" + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val nonHostMcastDstIpNsPkt = "02030405060700010203040586DD6000000000203AFF2001000000000" + + "0000200001A11223344FF0200000000000000000001FF441133870095" + + "1C0000000020010000000000000200001A334411220101000102030405" // mcast dst ip is not one of solicited mcast ip derived from one of device's ip -> pass verifyProgramRun( - APF_VERSION_6, - program, - HexDump.hexStringToByteArray(nonHostMcastDstIpNsPkt), - DROPPED_IPV6_NS_OTHER_HOST + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(nonHostMcastDstIpNsPkt), + DROPPED_IPV6_NS_OTHER_HOST ) // Using scapy to generate IPv6 NS packet: // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="ff02::1:ff44:1122", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // pkt = eth/ip6/icmp6 - val hostMcastDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF200100000000" + - "00000200001A11223344FF0200000000000000000001FF4411228700" + - "9C2E0000000020010000000000000200001A33441122" - // mcast dst ip is one of solicited mcast ip derived from one of device's ip -> pass + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val hostMcastDstIpNsPkt = "02030405060700010203040586DD6000000000203AFF2001000000000000" + + "0200001A11223344FF0200000000000000000001FF4411228700952D0000" + + "000020010000000000000200001A334411220101000102030405" + // mcast dst ip is one of solicited mcast ip derived from one of device's ip + // -> drop and replied verifyProgramRun( - APF_VERSION_6, - program, - HexDump.hexStringToByteArray(hostMcastDstIpNsPkt), - PASSED_IPV6_ICMP + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(hostMcastDstIpNsPkt), + DROPPED_IPV6_NS_REPLIED_NON_DAD ) // validate IPv6 NS payload check @@ -2184,24 +2218,6 @@ // Using scapy to generate IPv6 NS packet: // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) - // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") - // icmp6_opt_1 = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") - // icmp6_opt_2 = ICMPv6NDOptUnknown(type=14, len=6, data='\x11\x22\x33\x44\x55\x66') - // pkt = eth/ip6/icmp6/icmp6_opt_1/icmp6_opt_2 - val longNsPkt = "02030405060700010203040586DD6000000000283AFF20010000000000000200001A11" + - "22334420010000000000000200001A3344112287009339000000002001000000000000" + - "0200001A3344112201010102030405060E06112233445566" - // payload len > 32 -> pass - verifyProgramRun( - APF_VERSION_6, - program, - HexDump.hexStringToByteArray(longNsPkt), - PASSED_IPV6_NS_MULTIPLE_OPTIONS - ) - - // Using scapy to generate IPv6 NS packet: - // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") - // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:4444:5555") // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") // pkt = eth/ip6/icmp6/icmp6_opt @@ -2250,6 +2266,377 @@ DROPPED_IPV6_NS_INVALID ) + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:1234:5678") + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") + // pkt = eth/ip6/icmp6/icmp6_opt + val tentativeTargetIpNsPkt = "02030405060700010203040586DD6000000000203AFF200100000000" + + "00000200001A1122334420010000000000000200001A334411228700" + + "16CE0000000020010000000000000200001A123456780101010203040506" + // target ip is one of tentative address -> pass + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(tentativeTargetIpNsPkt), + PASSED_IPV6_NS_TENTATIVE + ) + + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1c:2255:6666") + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") + // pkt = eth/ip6/icmp6/icmp6_opt + val invalidTargetIpNsPkt = "02030405060700010203040586DD6000000000203AFF200100000000000" + + "00200001A1122334420010000000000000200001A334411228700F6BC00" + + "00000020010000000000000200001C225566660101010203040506" + // target ip is none of {non-tentative, anycast} -> drop + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(invalidTargetIpNsPkt), + DROPPED_IPV6_NS_OTHER_HOST + ) + + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="::", dst="ff02::1:ff44:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") + // icmp6_opt = ICMPv6NDOptDstLLAddr(lladdr="02:03:04:05:06:07") + // pkt = eth/ip6/icmp6/icmp6_opt + val dadNsPkt = "02030405060700010203040586DD6000000000203AFF000000000000000000000000000" + + "00000FF0200000000000000000001FF4411228700F4A800000000200100000000000002" + + "00001A334411220201020304050607" + // DAD NS request -> pass + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(dadNsPkt), + PASSED_IPV6_NS_DAD + ) + + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") + // pkt = eth/ip6/icmp6 + val noOptionNsPkt = "02030405060700010203040586DD6000000000183AFF2001000000000000020000" + + "1A1122334420010000000000000200001A33441122870045290000000020010000" + + "000000000200001A33441122" + // payload len < 32 -> pass + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(noOptionNsPkt), + PASSED_IPV6_NS_NO_SLLA_OPTION + ) + + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="ff01::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") + // pkt = eth/ip6/icmp6/icmp6_opt + val nonDadMcastSrcIpPkt = "02030405060700010203040586DD6000000000203AFFFF01000000000000" + + "0200001A1122334420010000000000000200001A3344112287005C130000" + + "000020010000000000000200001A334411220101010203040506" + // non-DAD src IPv6 is FF::/8 -> drop + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(nonDadMcastSrcIpPkt), + DROPPED_IPV6_NS_INVALID + ) + + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="0001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") + // pkt = eth/ip6/icmp6/icmp6_opt + val nonDadLoopbackSrcIpPkt = "02030405060700010203040586DD6000000000203AFF0001000000000" + + "0000200001A1122334420010000000000000200001A3344112287005B" + + "140000000020010000000000000200001A334411220101010203040506" + // non-DAD src IPv6 is 00::/8 -> drop + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(nonDadLoopbackSrcIpPkt), + DROPPED_IPV6_NS_INVALID + ) + + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") + // icmp6_opt1 = ICMPv6NDOptDstLLAddr(lladdr="01:02:03:04:05:06") + // icmp6_opt2 = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") + // pkt = eth/ip6/icmp6/icmp6_opt1/icmp6_opt2 + val sllaNotFirstOptionNsPkt = "02030405060700010203040586DD6000000000283AFF200100000000" + + "00000200001A1122334420010000000000000200001A334411228700" + + "2FFF0000000020010000000000000200001A33441122020101020304" + + "05060101010203040506" + // non-DAD with multiple options, SLLA in 2nd option -> pass + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(sllaNotFirstOptionNsPkt), + PASSED_IPV6_NS_NO_SLLA_OPTION + ) + + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") + // icmp6_opt = ICMPv6NDOptDstLLAddr(lladdr="01:02:03:04:05:06") + // pkt = eth/ip6/icmp6/icmp6_opt + val noSllaOptionNsPkt = "02030405060700010203040586DD6000000000203AFF200100000000000002" + + "00001A1122334420010000000000000200001A3344112287003A1400000000" + + "20010000000000000200001A334411220201010203040506" + // non-DAD with one option but not SLLA -> pass + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(noSllaOptionNsPkt), + PASSED_IPV6_NS_NO_SLLA_OPTION + ) + + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") + // pkt = eth/ip6/icmp6/icmp6_opt + val mcastMacSllaOptionNsPkt = "02030405060700010203040586DD6000000000203AFF200100000000" + + "00000200001A1122334420010000000000000200001A334411228700" + + "3B140000000020010000000000000200001A33441122010101020304" + + "0506" + // non-DAD, SLLA is multicast MAC -> drop + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(mcastMacSllaOptionNsPkt), + DROPPED_IPV6_NS_INVALID + ) + apfFilter.shutdown() + } + + // The APFv6 code path is only turned on in V+ + @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @Test + fun testNaTransmit() { + val apfFilter = + ApfFilter( + context, + getDefaultConfig(), + ifParams, + ipClientCallback, + metrics, + dependencies + ) + val lp = LinkProperties() + for (addr in hostIpv6Addresses) { + lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64)) + } + + apfFilter.setLinkProperties(lp) + val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) + verify(ipClientCallback, times(3)).installPacketFilter(programCaptor.capture()) + val program = programCaptor.allValues.last() + val validIpv6Addresses = hostIpv6Addresses + hostAnycast6Addresses + for (addr in validIpv6Addresses) { + // unicast solicited NS request + val receivedUcastNsPacket = generateNsPacket( + senderMacAddress, + apfFilter.mHardwareAddress, + senderIpv6Address, + addr, + addr + ) + + verifyProgramRun( + APF_VERSION_6, + program, + receivedUcastNsPacket, + DROPPED_IPV6_NS_REPLIED_NON_DAD + ) + + val transmittedUcastPacket = ApfJniUtils.getTransmittedPacket() + val expectedUcastNaPacket = generateNaPacket( + apfFilter.mHardwareAddress, + senderMacAddress, + addr, + senderIpv6Address, + 0xe0000000.toInt(), // R=1, S=1, O=1 + addr + ) + + assertContentEquals( + expectedUcastNaPacket, + transmittedUcastPacket + ) + + val solicitedMcastAddr = NetworkStackUtils.ipv6AddressToSolicitedNodeMulticast( + InetAddress.getByAddress(addr) as Inet6Address + )!! + val mcastDa = NetworkStackUtils.ipv6MulticastToEthernetMulticast(solicitedMcastAddr) + .toByteArray() + + // multicast solicited NS request + var receivedMcastNsPacket = generateNsPacket( + senderMacAddress, + mcastDa, + senderIpv6Address, + solicitedMcastAddr.address, + addr + ) + + verifyProgramRun( + APF_VERSION_6, + program, + receivedMcastNsPacket, + DROPPED_IPV6_NS_REPLIED_NON_DAD + ) + + val transmittedMcastPacket = ApfJniUtils.getTransmittedPacket() + val expectedMcastNaPacket = generateNaPacket( + apfFilter.mHardwareAddress, + senderMacAddress, + addr, + senderIpv6Address, + 0xe0000000.toInt(), // R=1, S=1, O=1 + addr + ) + + assertContentEquals( + expectedMcastNaPacket, + transmittedMcastPacket + ) + } + + apfFilter.shutdown() + } + + // The APFv6 code path is only turned on in V+ + @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @Test + fun testNaTransmitWithTclass() { + // mock nd traffic class from /proc/sys/net/ipv6/conf/{ifname}/ndisc_tclass to 20 + `when`(dependencies.getNdTrafficClass(any())).thenReturn(20) + val apfFilter = + ApfFilter( + context, + getDefaultConfig(), + ifParams, + ipClientCallback, + metrics, + dependencies + ) + + val lp = LinkProperties() + for (addr in hostIpv6Addresses) { + lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64)) + } + apfFilter.setLinkProperties(lp) + val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) + verify(ipClientCallback, times(3)).installPacketFilter(programCaptor.capture()) + val program = programCaptor.allValues.last() + // Using scapy to generate IPv6 NS packet: + // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") + // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="ff02::1:ff44:1122", hlim=255, tc=20) + // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") + // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="00:01:02:03:04:05") + // pkt = eth/ip6/icmp6/icmp6_opt + val hostMcastDstIpNsPkt = "02030405060700010203040586DD6140000000203AFF2001000000000000" + + "0200001A11223344FF0200000000000000000001FF4411228700952D0000" + + "000020010000000000000200001A334411220101000102030405" + verifyProgramRun( + APF_VERSION_6, + program, + HexDump.hexStringToByteArray(hostMcastDstIpNsPkt), + DROPPED_IPV6_NS_REPLIED_NON_DAD + ) + + val transmitPkt = ApfJniUtils.getTransmittedPacket() + // Using scapy to generate IPv6 NA packet: + // eth = Ether(src="02:03:04:05:06:07", dst="00:01:02:03:04:05") + // ip6 = IPv6(src="2001::200:1a:3344:1122", dst="2001::200:1a:1122:3344", hlim=255, tc=20) + // icmp6 = ICMPv6ND_NA(tgt="2001::200:1a:3344:1122", R=1, S=1, O=1) + // icmp6_opt = ICMPv6NDOptDstLLAddr(lladdr="02:03:04:05:06:07") + // pkt = eth/ip6/icmp6/icmp6_opt + val expectedNaPacket = "00010203040502030405060786DD6140000000203AFF2001000000000000020" + + "0001A3344112220010000000000000200001A1122334488005610E000000020" + + "010000000000000200001A334411220201020304050607" + assertContentEquals( + HexDump.hexStringToByteArray(expectedNaPacket), + transmitPkt + ) + } + + @Test + fun testNdOffloadDisabled() { + val apfConfig = getDefaultConfig() + apfConfig.shouldHandleNdOffload = false + val apfFilter = + ApfFilter( + context, + apfConfig, + ifParams, + ipClientCallback, + metrics, + dependencies + ) + val lp = LinkProperties() + for (addr in hostIpv6Addresses) { + lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64)) + } + + apfFilter.setLinkProperties(lp) + val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) + verify(ipClientCallback, times(3)).installPacketFilter(programCaptor.capture()) + val program = programCaptor.allValues.last() + val validIpv6Addresses = hostIpv6Addresses + hostAnycast6Addresses + for (addr in validIpv6Addresses) { + // unicast solicited NS request + val receivedUcastNsPacket = generateNsPacket( + senderMacAddress, + apfFilter.mHardwareAddress, + senderIpv6Address, + addr, + addr + ) + + verifyProgramRun( + APF_VERSION_6, + program, + receivedUcastNsPacket, + PASSED_IPV6_ICMP + ) + + val solicitedMcastAddr = NetworkStackUtils.ipv6AddressToSolicitedNodeMulticast( + InetAddress.getByAddress(addr) as Inet6Address + )!! + val mcastDa = NetworkStackUtils.ipv6MulticastToEthernetMulticast(solicitedMcastAddr) + .toByteArray() + + // multicast solicited NS request + var receivedMcastNsPacket = generateNsPacket( + senderMacAddress, + mcastDa, + senderIpv6Address, + solicitedMcastAddr.address, + addr + ) + + verifyProgramRun( + APF_VERSION_6, + program, + receivedMcastNsPacket, + PASSED_IPV6_ICMP + ) + } apfFilter.shutdown() } @@ -2369,6 +2756,53 @@ config.ieee802_3Filter = false config.ethTypeBlackList = IntArray(0) config.shouldHandleArpOffload = true + config.shouldHandleNdOffload = true return config } + + private fun generateNsPacket( + srcMac: ByteArray, + dstMac: ByteArray, + srcIp: ByteArray, + dstIp: ByteArray, + target: ByteArray, + ): ByteArray { + val nsPacketBuf = NeighborSolicitation.build( + MacAddress.fromBytes(srcMac), + MacAddress.fromBytes(dstMac), + InetAddress.getByAddress(srcIp) as Inet6Address, + InetAddress.getByAddress(dstIp) as Inet6Address, + InetAddress.getByAddress(target) as Inet6Address + ) + + val nsPacket = ByteArray( + ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_NS_HEADER_LEN + 8 // option length + ) + nsPacketBuf.get(nsPacket) + return nsPacket + } + + private fun generateNaPacket( + srcMac: ByteArray, + dstMac: ByteArray, + srcIp: ByteArray, + dstIp: ByteArray, + flags: Int, + target: ByteArray, + ): ByteArray { + val naPacketBuf = NeighborAdvertisement.build( + MacAddress.fromBytes(srcMac), + MacAddress.fromBytes(dstMac), + InetAddress.getByAddress(srcIp) as Inet6Address, + InetAddress.getByAddress(dstIp) as Inet6Address, + flags, + InetAddress.getByAddress(target) as Inet6Address + ) + val naPacket = ByteArray( + ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_NA_HEADER_LEN + 8 // lla option length + ) + + naPacketBuf.get(naPacket) + return naPacket + } }
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java index 32ee7c3..9c36df7 100644 --- a/tests/unit/src/android/net/apf/ApfTest.java +++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -47,10 +47,8 @@ import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -1759,32 +1757,14 @@ doTestApfFilterMulticastPingWhileDozing(true /* isLightDozing */); } - @Test - @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) - public void testShouldHandleLightDozeKillSwitch() throws Exception { - final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); - final ApfConfiguration configuration = getDefaultConfig(); - configuration.shouldHandleLightDoze = false; - final ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, - configuration, mNetworkQuirkMetrics, mDependencies); - final ArgumentCaptor<BroadcastReceiver> receiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture(), anyBoolean()); - final BroadcastReceiver receiver = receiverCaptor.getValue(); - doReturn(true).when(mPowerManager).isDeviceLightIdleMode(); - receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED)); - assertFalse(apfFilter.isInDozeMode()); - } - private void doTestApfFilterMulticastPingWhileDozing(boolean isLightDozing) throws Exception { final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); final ApfConfiguration configuration = getDefaultConfig(); - configuration.shouldHandleLightDoze = true; final ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, configuration, mNetworkQuirkMetrics, mDependencies); final ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture(), anyBoolean()); + verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture()); final BroadcastReceiver receiver = receiverCaptor.getValue(); // Construct a multicast ICMPv6 ECHO request.
diff --git a/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java b/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java index e8f14b5..ed423e4 100644 --- a/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java +++ b/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java
@@ -55,8 +55,6 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.os.Build; -import android.os.Handler; -import android.os.Looper; import android.os.PowerManager; import android.util.Log; import android.util.Log.TerribleFailureHandler; @@ -739,20 +737,12 @@ boolean featureEnabled) throws Exception { final TcpSocketTracker tst = new TcpSocketTracker(mDependencies, mNetwork); tst.setNetworkCapabilities(CELL_NOT_METERED_CAPABILITIES); - - // Verify that device idle mode receiver does not register as the event for NM creation - // is not yet received. - verify(mDependencies, never()).addDeviceIdleReceiver(any(), - anyBoolean(), anyBoolean(), any()); - - final Handler nmHandler = new Handler(Looper.getMainLooper()); - tst.init(nmHandler, new LinkProperties(), CELL_NOT_METERED_CAPABILITIES); final ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); // Enable doze mode with 1 netlink message. verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture(), - anyBoolean(), anyBoolean(), eq(nmHandler)); + anyBoolean(), anyBoolean()); final BroadcastReceiver receiver = receiverCaptor.getValue(); if (dozeModeType == DEEP_DOZE) { doReturn(true).when(mPowerManager).isDeviceIdleMode();
diff --git a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java index a949f80..d5d1c90 100644 --- a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java +++ b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -633,7 +633,6 @@ doReturn(0).when(mRandom).nextInt(); doReturn(mNetd).when(mTstDependencies).getNetd(); - doNothing().when(mTst).init(any(), any(), any()); // DNS probe timeout should not be defined more than half of HANDLER_TIMEOUT_MS. Otherwise, // it will fail the test because of timeout expired for querying AAAA and A sequentially. doReturn(200).when(mResources) @@ -2731,30 +2730,12 @@ } @Test - public void testTcpSocketTracker_init() throws Exception { - setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_TCP); - final WrappedNetworkMonitor wnm = makeCellMeteredNetworkMonitor(); - // makeCellMeteredNetworkMonitor() creates the NM first and then assign - // new NetworkCapabilities, so notifyNMCreated() will start with a empty NC - // then update CELL_METERED_CAPABILITIES in the follow up call. - final InOrder inOrder = inOrder(mTst); - inOrder.verify(mTst).init( - eq(wnm.getHandler()), - eq(new LinkProperties()), - eq(new NetworkCapabilities(null))); - inOrder.verify(mTst).setNetworkCapabilities(eq(CELL_METERED_CAPABILITIES)); - } - - @Test public void testDataStall_setOpportunisticMode() { setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_TCP); WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor(); InOrder inOrder = inOrder(mTst); - // Initialized. - inOrder.verify(mTst).init( - eq(wnm.getHandler()), - eq(new LinkProperties()), - eq(new NetworkCapabilities(null))); + // Initialized with default value. + inOrder.verify(mTst).setOpportunisticMode(false); // Strict mode. wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));