Improve stability of APFv{4,6} multi-device tests
This commit enhances the stability of the APFv{4,6} multi-device tests by addressing several sources of flakiness and improving the test setup and validation.
Specifically, this commit:
* Increased sleep time in the test setup. This ensures APF is activated before each test, preventing unexpected behavior.
* Added sleep time in `ApfV4Test` to ensure APF remains enabled and is not disabled due to high throughput scenarios.
* Changed the validation order to first check received packets and then APF counters. This helps to more easily identify the root cause of test failures.
* Changed the Ethernet destination address from multicast to unicast in `ApfV6Test` to prevent packets from being filtered due to DTIM skip.
* Removed the `test_broadcast_arp_request_offload()` test, which was flaky due to DTIM skip and is adequately covered by the `test_unicast_arp_request_offload()` test.
Bug: 406570694
Flag: TEST_ONLY
Test: atest CtsConnectivityMultiDevicesTestCases:ApfV4Test
Test: atest CtsConnectivityMultiDevicesTestCases:ApfV6Test
Test: run cts -m CtsConnectivityMultiDevicesTestCases --skip-preconditions -t ApfV4Test --shard-count 2
Test: run cts -m CtsConnectivityMultiDevicesTestCases --skip-preconditions -t ApfV6Test --shard-count 2
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:744a17443a425e3320219ff02f9dbfa78216464e)
Merged-In: I053509459078d0bd94e16a6bf7349b948f930e6c
Change-Id: I053509459078d0bd94e16a6bf7349b948f930e6c
diff --git a/staticlibs/testutils/host/python/apf_test_base.py b/staticlibs/testutils/host/python/apf_test_base.py
index 6a62e21..9d1ea02 100644
--- a/staticlibs/testutils/host/python/apf_test_base.py
+++ b/staticlibs/testutils/host/python/apf_test_base.py
@@ -70,8 +70,8 @@
# Enable doze mode to activate APF.
adb_utils.set_doze_mode(self.clientDevice, True)
- # wait for APF to become active.
- time.sleep(3)
+ # Longer wait time is required for APF to become active in CTS test suite.
+ time.sleep(5)
def teardown_class(self):
adb_utils.set_doze_mode(self.clientDevice, False)
@@ -106,7 +106,15 @@
try:
apf_utils.start_capture_packets(self.serverDevice, self.server_iface_name)
- self.send_packet_and_expect_counter_increased(send_packet, counter_name)
+ count_before_test = apf_utils.get_apf_counter(
+ self.clientDevice,
+ self.client_iface_name,
+ counter_name,
+ )
+
+ apf_utils.send_raw_packet_downstream(
+ self.serverDevice, self.server_iface_name, send_packet
+ )
assert_utils.expect_with_retry(
lambda: apf_utils.get_matched_packet_counts(
@@ -114,5 +122,15 @@
)
== 1
)
+
+ assert_utils.expect_with_retry(
+ lambda: apf_utils.get_apf_counter(
+ self.clientDevice,
+ self.client_iface_name,
+ counter_name,
+ )
+ > count_before_test
+ )
+
finally:
apf_utils.stop_capture_packets(self.serverDevice, self.server_iface_name)
diff --git a/tests/cts/multidevices/apfv4_test.py b/tests/cts/multidevices/apfv4_test.py
index 0fc1093..2f212fc 100644
--- a/tests/cts/multidevices/apfv4_test.py
+++ b/tests/cts/multidevices/apfv4_test.py
@@ -16,6 +16,7 @@
from mobly import asserts
from net_tests_utils.host.python import apf_test_base, apf_utils
from scapy.layers.l2 import Ether
+import time
# Constants.
COUNTER_DROPPED_ETHERTYPE_NOT_ALLOWED = "DROPPED_ETHERTYPE_NOT_ALLOWED"
@@ -59,6 +60,9 @@
# Add zero padding up to minimum ethernet frame length
packet = packet.ljust(MIN_PACKET_SIZE * 2, "0")
+
+ # Pause packet sending between tests to avoid APF disablement due to high throughput.
+ time.sleep(3)
self.send_packet_and_expect_counter_increased(
packet, COUNTER_DROPPED_ETHERTYPE_NOT_ALLOWED
)
diff --git a/tests/cts/multidevices/apfv6_test.py b/tests/cts/multidevices/apfv6_test.py
index 9b2e309..c6e5f8d 100644
--- a/tests/cts/multidevices/apfv6_test.py
+++ b/tests/cts/multidevices/apfv6_test.py
@@ -79,33 +79,6 @@
arp_request, "DROPPED_ARP_REQUEST_REPLIED", expected_arp_reply
)
- def test_broadcast_arp_request_offload(self):
- eth = Ether(src=self.server_mac_address, dst='ff:ff:ff:ff:ff:ff')
- arp = ARP(
- op=1,
- psrc=self.server_ipv4_addresses[0],
- pdst=self.client_ipv4_addresses[0],
- hwsrc=self.server_mac_address
- )
- arp_request = bytes(eth/arp).hex()
-
- eth = Ether(src=self.client_mac_address, dst=self.server_mac_address)
- arp = ARP(
- op=2,
- psrc=self.client_ipv4_addresses[0],
- pdst=self.server_ipv4_addresses[0],
- hwsrc=self.client_mac_address,
- hwdst=self.server_mac_address
- )
- expected_arp_reply = bytes(eth/arp).hex()
-
- # Add zero padding up to 60 bytes, since APFv6 ARP offload always sent out 60 bytes reply
- expected_arp_reply = expected_arp_reply.ljust(ARP_OFFLOAD_REPLY_LEN * 2, "0")
-
- self.send_packet_and_expect_reply_received(
- arp_request, "DROPPED_ARP_REQUEST_REPLIED", expected_arp_reply
- )
-
def test_non_dad_ipv6_neighbor_solicitation_offload(self):
eth = Ether(src=self.server_mac_address, dst=self.client_mac_address)
ip = IPv6(src=self.server_ipv6_addresses[0], dst=self.client_ipv6_addresses[0])
@@ -158,7 +131,8 @@
@apf_utils.at_least_B()
def test_igmpv3_general_query_offload(self):
- ether = Ether(src=self.server_mac_address, dst='01:00:5e:00:00:01')
+ # use unicast to replace multicast ether dst to prevent flaky due to DTIM skip
+ ether = Ether(src=self.server_mac_address, dst=self.client_mac_address)
ip = IP(
src=self.server_ipv4_addresses[0],
dst='224.0.0.1',
@@ -206,7 +180,8 @@
@apf_utils.at_least_B()
@apf_utils.apf_ram_at_least(3000)
def test_mldv2_general_query_offload(self):
- ether = Ether(src=self.server_mac_address, dst='33:33:00:00:00:01')
+ # use unicast to replace multicast ether dst to prevent flaky due to DTIM skip
+ ether = Ether(src=self.server_mac_address, dst=self.client_mac_address)
ip = IPv6(src=self.server_ipv6_addresses[0], dst='ff02::1', hlim=1)
hopOpts = IPv6ExtHdrHopByHop(options=[RouterAlert(otype=5)])
mld = ICMPv6MLQuery2()