blob: 897512993c41b7b8b68b0b53a6873cf3bda58390 [file] [log] [blame]
# Copyright (c) 2013 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 autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.cros.network import iw_runner
from autotest_lib.client.common_lib.cros.network import ping_runner
from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
from autotest_lib.server.cros.network import wifi_cell_test_base
class network_WiFi_BgscanBackoff(wifi_cell_test_base.WiFiCellTestBase):
"""Test that background scan backs off when there is foreground traffic."""
version = 1
BGSCAN_SAMPLE_PERIOD_SECONDS = 100
NO_BGSCAN_SAMPLE_PERIOD_SECONDS = 10
CONFIGURED_BGSCAN_INTERVAL_SECONDS = 7
PING_INTERVAL_SECONDS = 0.1
# Dwell time for scanning is usually configured to be around 100 ms (some
# are higher, around 150 ms), since this is also the standard beacon
# interval. Tolerate spikes in latency up to 250 ms as a way of asking
# that our PHY be servicing foreground traffic regularly during background
# scans.
# See also network_WiFi_OverlappingBSSScan for similar parameters.
LATENCY_MARGIN_MS = 250
THRESHOLD_BASELINE_LATENCY_MS = 100
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 list of HostapConfig objects and LinuxSystem
capabilities.
"""
self._config_first_ap = additional_params[0]
self._config_second_ap = additional_params[1]
def _find_bss_matching_mac_addr(self, iw, mac_addr):
""" Scan and look for a BSS in the scan results with given mac address.
@param iw iw_runner instantiated on the client
@param mac_addr the address to look for
"""
bss_list = iw.scan_dump(self.context.client.wifi_if)
logging.debug('Found BSSes: %r', bss_list)
return filter(lambda bss: bss.bss == mac_addr, bss_list)
def run_once(self):
"""Body of the test."""
get_assoc_params = lambda conf: xmlrpc_datatypes.AssociationParameters(
ssid=self.context.router.get_ssid(instance=0),
bgscan_config=conf)
get_ping_config = lambda period: ping_runner.PingConfig(
self.context.get_wifi_addr(),
interval=self.PING_INTERVAL_SECONDS,
count=int(period / self.PING_INTERVAL_SECONDS))
self.context.configure(self._config_first_ap)
bgscan_config = xmlrpc_datatypes.BgscanConfiguration(
short_interval=self.CONFIGURED_BGSCAN_INTERVAL_SECONDS,
long_interval=self.CONFIGURED_BGSCAN_INTERVAL_SECONDS,
method=xmlrpc_datatypes.BgscanConfiguration.SCAN_METHOD_SIMPLE)
self.context.assert_connect_wifi(get_assoc_params(bgscan_config))
logging.info('Pinging router with background scans for %d seconds.',
self.BGSCAN_SAMPLE_PERIOD_SECONDS)
result_bgscan = self.context.client.ping(
get_ping_config(self.BGSCAN_SAMPLE_PERIOD_SECONDS))
logging.info('Ping statistics with bgscan: %r', result_bgscan)
# Bring up a second AP, make sure that it shows up in bgscans.
self._config_second_ap.ssid = self.context.router.get_ssid()
self.context.configure(self._config_second_ap,multi_interface=True)
logging.info('Without a ping running, ensure that bgscans succeed.')
ap_mac = self.context.router.get_hostapd_mac(ap_num=1)
logging.debug('Looking for BSS %s', ap_mac)
iw = iw_runner.IwRunner(remote_host=self.context.client.host)
utils.poll_for_condition(
condition=lambda: self._find_bss_matching_mac_addr(iw, ap_mac),
exception=error.TestFail('Background scans should detect new BSSes '
'within an associated ESS.'),
timeout=self.BGSCAN_SAMPLE_PERIOD_SECONDS,
sleep_interval=1)
self.context.router.deconfig_aps(instance=1)
self.context.client.shill.disconnect(
self.context.router.get_ssid(instance=0))
# Reconfigure AP, so the new bgscan setting can be correctly applied.
self.context.configure(self._config_first_ap)
# Gather some statistics about ping latencies without scanning going on.
self.context.assert_connect_wifi(get_assoc_params(None))
logging.info('Pinging router without background scans for %d seconds.',
self.NO_BGSCAN_SAMPLE_PERIOD_SECONDS)
result_no_bgscan = self.context.client.ping(
get_ping_config(self.NO_BGSCAN_SAMPLE_PERIOD_SECONDS))
logging.info('Ping statistics without bgscan: %r', result_no_bgscan)
if result_no_bgscan.max_latency > self.THRESHOLD_BASELINE_LATENCY_MS:
raise error.TestFail('RTT latency is too high even without '
'background scans: %f' %
result_no_bgscan.max_latency)
if (result_bgscan.max_latency >
self.LATENCY_MARGIN_MS + result_no_bgscan.avg_latency):
raise error.TestFail('Significant difference in rtt due to bgscan: '
'%.1f > %.1f + %d' %
(result_bgscan.max_latency,
result_no_bgscan.avg_latency,
self.LATENCY_MARGIN_MS))