| # 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.cros.network import ping_runner |
| from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes |
| from autotest_lib.server.cros.network import hostap_config |
| from autotest_lib.server.cros.network import wifi_cell_test_base |
| |
| |
| class network_WiFi_OverlappingBSSScan(wifi_cell_test_base.WiFiCellTestBase): |
| """Test that background scan backs off when there is foreground traffic.""" |
| version = 1 |
| |
| OBSS_SCAN_SAMPLE_PERIOD_SECONDS = 100 |
| NO_OBSS_SCAN_SAMPLE_PERIOD_SECONDS = 10 |
| PING_INTERVAL_SECONDS = 0.1 |
| LATENCY_MARGIN_MS = 150 |
| THRESHOLD_BASELINE_LATENCY_MS = 100 |
| WIFI_FREQUENCY = 2437 |
| |
| |
| @classmethod |
| def get_ap_config(cls, scenario_name, use_obss): |
| """Returns a HostapConfig object based on the given parameters. |
| |
| @param scenario_name: string describing a portion of this test. |
| @param use_obss: bool indicating if the AP should ask clients to |
| perform OBSS scans. |
| @return HostapConfig which incorporates the given parameters. |
| |
| """ |
| return hostap_config.HostapConfig( |
| frequency=cls.WIFI_FREQUENCY, |
| mode=hostap_config.HostapConfig.MODE_11N_PURE, |
| n_capabilities=[ |
| hostap_config.HostapConfig.N_CAPABILITY_GREENFIELD, |
| hostap_config.HostapConfig.N_CAPABILITY_HT40 |
| ], |
| obss_interval=10 if use_obss else None, |
| scenario_name=scenario_name) |
| |
| |
| def run_once(self): |
| """Body of the test.""" |
| get_assoc_params = lambda: xmlrpc_datatypes.AssociationParameters( |
| ssid=self.context.router.get_ssid()) |
| 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)) |
| # Gather some statistics about ping latencies without scanning going on. |
| self.context.configure(self.get_ap_config('obss_disabled', False)) |
| self.context.assert_connect_wifi(get_assoc_params()) |
| logging.info('Pinging router without OBSS scans for %d seconds.', |
| self.NO_OBSS_SCAN_SAMPLE_PERIOD_SECONDS) |
| result_no_obss_scan = self.context.client.ping( |
| get_ping_config(self.NO_OBSS_SCAN_SAMPLE_PERIOD_SECONDS)) |
| logging.info('Ping statistics without OBSS scans: %r', |
| result_no_obss_scan) |
| if result_no_obss_scan.max_latency > self.THRESHOLD_BASELINE_LATENCY_MS: |
| raise error.TestFail('RTT latency is too high even without ' |
| 'OBSS scans: %f' % |
| result_no_obss_scan.max_latency) |
| |
| self.context.client.shill.disconnect(self.context.router.get_ssid()) |
| |
| # Re-configure the AP for OBSS and repeat the ping test. |
| self.context.configure(self.get_ap_config('obss_enabled', True)) |
| self.context.capture_host.start_capture( |
| self.WIFI_FREQUENCY, filename='obss_enabled.pcap') |
| self.context.assert_connect_wifi(get_assoc_params()) |
| logging.info('Pinging router with OBSS scans for %d seconds.', |
| self.OBSS_SCAN_SAMPLE_PERIOD_SECONDS) |
| result_obss_scan = self.context.client.ping( |
| get_ping_config(self.OBSS_SCAN_SAMPLE_PERIOD_SECONDS)) |
| logging.info('Ping statistics with OBSS scans: %r', result_obss_scan) |
| self.context.capture_host.stop_capture() |
| |
| if not self.context.router.detect_client_coexistence_report( |
| self.context.client.wifi_mac): |
| raise error.TestFail('No coexistence action frames detected ' |
| 'from the client.') |
| |
| self.context.client.shill.disconnect(self.context.router.get_ssid()) |
| self.context.router.deconfig() |
| # Dwell time for scanning is usually configured to be around 100 ms, |
| # since this is also the standard beacon interval. Tolerate spikes in |
| # latency up to 200 ms as a way of asking that our PHY be servicing |
| # foreground traffic regularly during background scans. |
| if (result_obss_scan.max_latency > |
| self.LATENCY_MARGIN_MS + result_no_obss_scan.avg_latency): |
| raise error.TestFail('Significant difference in rtt due to OBSS: ' |
| '%.1f > %.1f + %d' % |
| (result_obss_scan.max_latency, |
| result_no_obss_scan.avg_latency, |
| self.LATENCY_MARGIN_MS)) |