blob: 8b77a99598ce41b583bb8d68d212d69c3ff5478d [file] [log] [blame]
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
from autotest_lib.client.common_lib import error
from import tcpdump_analyzer
from import xmlrpc_datatypes
from import wifi_cell_test_base
class network_WiFi_APSupportedRates(wifi_cell_test_base.WiFiCellTestBase):
"""Test that the WiFi chip honors the SupportedRates IEs sent by the AP."""
version = 1
def check_bitrates_in_capture(self, pcap_result, supported_rates):
Check that bitrates look like we expect in a packet capture.
The DUT should not send packets at bitrates that were disabled by the
@param pcap_result: RemoteCaptureResult tuple.
@param supported_rates: List of upported legacy bitrates (Mbps).
# Filter notes:
# (a) Some chips use self-addressed frames to tune channel performance.
# They don't carry host-generated traffic, so filter them out.
# (b) Use TA (not SA), because multicast may retransmit our
# "Source-Addressed" frames at rates we don't control.
# (c) BSSID filter: non-BSSID frames include Ack and BlockAck frames;
# these rates tend to match the frames to which they're responding
# (i.e., not under DUT's control).
# (d) QoS null filter: these frames are short (no data payload), and
# it's more important that they be reliable (e.g., for PS
# transitions) than fast. See b/132825853#comment40,
# for example.
# Items (b) and (c) wouldn't be much problem if our APs actually
# respected the Supported Rates IEs that we're configuring, but current
# (2019-06-28) test AP builds do not appear to.
frame_filter = ('wlan.ta==%s and (not wlan.da==%s) and wlan.bssid==%s'
' and wlan.fc.type_subtype!=%s' %
frames = tcpdump_analyzer.get_frames(pcap_result.local_pcap_path,
frame_filter, reject_bad_fcs=False)
if not frames:
raise error.TestError('Failed to capture any relevant frames')
# Some frames don't have bitrate fields -- for example, if they are
# using MCS rates (not legacy rates). For MCS rates, that's OK, since
# that satisfies this test requirement (not using "unsupported legacy
# rates"). So ignore them.
bad_frames = [f for f in frames
if f.bit_rate is not None and
f.bit_rate not in supported_rates]
if bad_frames:
# Remove duplicates.
bad_rates = list(set(f.bit_rate for f in bad_frames))
logging.error('Unexpected rate for frames:')
for f in bad_frames:
logging.error('%s', f)
raise error.TestFail('Saw frames at rates %r (expected %r).' %
(bad_rates, supported_rates))
def parse_additional_arguments(self, commandline_args, additional_params):
"""Hook into super class to take control files parameters.
@param commandline_args dict of parsed parameters from the autotest.
@param additional_params HostapConfig object.
self._ap_config = additional_params
def run_once(self):
"""Verify that we respond accurately to APs that disable legacy bitrates.
# See b/138406224. ath10k only supports this on CrOS kernels >=4.14.
if':')[1] == 'scarlet':
raise error.TestNAError('Scarlet does not support this feature on '
'kernel 4.4')
ap_config = self._ap_config
# TODO(b/160281713): remove this if we cherry-pick the bitrate fixes
# and deploy an OS update.
if (ap_config.frequency < 5000 and
self.context.capture_host.board == 'whirlwind'):
raise error.TestNAError('Whirlwind does not capture 802.11g/OFDM '
'rates correctly (b/160281713)')
assoc_params = xmlrpc_datatypes.AssociationParameters(
results = self.context.capture_host.stop_capture()
if len(results) != 1:
raise error.TestError('Expected to generate one packet '
'capture but got %d captures instead.' %