autotest: Convert network_WiFiMatFunc/012CheckMaskedBSSID
Rewrite network_WiFiMatFunc/012CheckMaskedBSSID to use the new WiFi
framework. In the process, move the logic to trigger a scan over to
WiFiClient. Also expand hostapd_configure in site_linux_router to
handle SSID and BSSID configuration settings.
TEST=The following:
./run_remote_tests.sh --remote=chromeos1-shelf1-host4 wifi_masked_bssid
(Fails with TestNA because this is a RSPro cell)
./run_remote_tests.sh --remote=chromeos1-shelf1-host3 wifi_masked_bssid
(Passes)
./run_remote_tests.sh --remote=chromeos1-shelf1-host3 \
network_WiFiRoaming --args='test_pat=006*'
(Passes; Verifies that scanning is working for older site_wifitest tests)
BUG=chromium:230660
Change-Id: I95ffbeb2cc0361fb98289fc8623fe6dfe33eb25d
Reviewed-on: https://gerrit.chromium.org/gerrit/50557
Commit-Queue: Christopher Wiley <wiley@chromium.org>
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Tested-by: Christopher Wiley <wiley@chromium.org>
diff --git a/server/cros/wlan/hostap_config.py b/server/cros/wlan/hostap_config.py
index 631e112..a1c7ead 100644
--- a/server/cros/wlan/hostap_config.py
+++ b/server/cros/wlan/hostap_config.py
@@ -114,7 +114,7 @@
def __init__(self, mode=None, channel=None, frequency=None,
n_capabilities=None, hide_ssid=None, beacon_interval=None,
- dtim_period=None, frag_threshold=None):
+ dtim_period=None, frag_threshold=None, ssid=None, bssid=None):
"""Construct a HostapConfig.
You may specify channel or frequency, but not both. Both options
@@ -129,6 +129,9 @@
@param beacon_interval int beacon interval of AP.
@param dtim_period int include a DTIM every |dtim_period| beacons.
@param frag_threshold int maximum outgoing data frame size.
+ @param ssid string up to 32 byte SSID overriding the router default.
+ @param bssid string like 00:11:22:33:44:55.
+
"""
super(HostapConfig, self).__init__()
if channel is not None and frequency is not None:
@@ -208,3 +211,8 @@
self.beacon_interval = beacon_interval
self.dtim_period = dtim_period
self.frag_threshold = frag_threshold
+ if len(ssid) > 32:
+ raise error.TestFail('Tried to specify SSID that was too long.')
+
+ self.ssid = ssid
+ self.bssid = bssid
diff --git a/server/cros/wlan/wifi_client.py b/server/cros/wlan/wifi_client.py
index 23fb4c8..a637cb8 100644
--- a/server/cros/wlan/wifi_client.py
+++ b/server/cros/wlan/wifi_client.py
@@ -455,3 +455,25 @@
wording)
logging.debug('Power save is indeed %s.', wording)
+
+
+ def scan(self, frequencies, ssids):
+ """Request a scan and check that certain SSIDs appear in the results.
+
+ @param frequencies list of int WiFi frequencies to scan for.
+ @param ssids list of string ssids to probe request for.
+
+ """
+ scan_params = ''
+ if frequencies:
+ scan_params += ' freq %s' % ' '.join(map(str, frequencies))
+ if ssids:
+ scan_params += ' ssid "%s"' % '" "'.join(ssids)
+ result = self.host.run('%s dev %s scan%s' % (self.command_iw,
+ self.wifi_if,
+ scan_params))
+ scan_lines = result.stdout.splitlines()
+ for ssid in ssids:
+ if ssid and ('\tSSID: %s' % ssid) not in scan_lines:
+ raise error.TestFail('SSID %s is not in scan results: %s' %
+ (ssid, result.stdout))
diff --git a/server/cros/wlan/wifi_test_context_manager.py b/server/cros/wlan/wifi_test_context_manager.py
index c754730..3c5c1f8 100644
--- a/server/cros/wlan/wifi_test_context_manager.py
+++ b/server/cros/wlan/wifi_test_context_manager.py
@@ -122,16 +122,19 @@
return self.server.wifi_ip
- def configure(self, configuration_parameters):
+ def configure(self, configuration_parameters, multi_interface=None):
"""Configure a router with the given parameters.
Configures an AP according to the specified parameters and
- enables whatever packet captures are appropriate.
+ enables whatever packet captures are appropriate. Will deconfigure
+ existing APs unless |multi_interface| is specified.
@param configuration_parameters HostapConfig object.
+ @param multi_interface True iff having multiple configured interfaces
+ is expected for this configure call.
"""
- self.router.hostap_configure(configuration_parameters)
+ self.router.hostap_configure(configuration_parameters, multi_interface)
if self._enable_client_packet_captures:
self.client.start_capture()
if self._enable_router_packet_captures:
diff --git a/server/site_linux_router.py b/server/site_linux_router.py
index 84f3c86..0961e2a 100644
--- a/server/site_linux_router.py
+++ b/server/site_linux_router.py
@@ -252,6 +252,11 @@
# Start with the default hostapd config parameters.
conf = self.__get_default_hostap_config()
conf['ssid'] = (self.defssid + configuration.ssid_suffix)[-32:]
+ if configuration.ssid:
+ # Let test writers overwrite the default SSID.
+ conf['ssid'] = configuration.ssid
+ if configuration.bssid:
+ conf['bssid'] = configuration.bssid
conf['channel'] = configuration.channel
self.hostapd['frequency'] = configuration.frequency
conf['hw_mode'] = configuration.hw_mode
diff --git a/server/site_linux_system.py b/server/site_linux_system.py
index 08d172c..c84afbd 100644
--- a/server/site_linux_system.py
+++ b/server/site_linux_system.py
@@ -32,10 +32,9 @@
self._capabilities = []
phymap = self.phys_for_frequency
- frequencies = phymap.iterkeys()
- if [freq for freq in frequencies if freq > 5000]:
+ if [freq for freq in phymap.iterkeys() if freq > 5000]:
self._capabilities.append(self.CAPABILITY_5GHZ)
- if [freq for freq in frequencies if len(phymap[freq]) > 1]:
+ if [freq for freq in phymap.iterkeys() if len(phymap[freq]) > 1]:
self._capabilities.append(self.CAPABILITY_MULTI_AP_SAME_BAND)
self._capabilities.append(self.CAPABILITY_MULTI_AP)
elif len(self.phy_bus_type) > 1:
@@ -121,7 +120,7 @@
elif '/pci' in devpath:
phybus = 'pci'
phy_bus_type[phy] = phybus
-
+ logging.debug('Got phys for frequency: %r', phys_for_frequency)
return phys_for_frequency, phy_bus_type
@@ -301,3 +300,24 @@
for phy, wlanif_i, phytype in self.wlanifs_in_use:
if wlanif_i == wlanif:
self.wlanifs_in_use.remove((phy, wlanif, phytype))
+
+
+ def require_capabilities(self, requirements, fatal_failure=False):
+ """Require capabilities of this LinuxSystem.
+
+ Check that capabilities in |requirements| exist on this system.
+ Raise and exception to skip but not fail the test if said
+ capabilities are not found. Pass |fatal_failure| to cause this
+ error to become a test failure.
+
+ @param requirements list of CAPABILITY_* defined above.
+ @param fatal_failure bool True iff failures should be fatal.
+
+ """
+ to_be_raised = error.TestNAError
+ if fatal_failure:
+ to_be_raised = error.TestFail
+ missing = [cap for cap in requirements if not cap in self.capabilities]
+ if missing:
+ raise to_be_raised('AP on %s is missing required capabilites: %r' %
+ (self.role, missing))
diff --git a/server/site_tests/network_WiFiMatFunc/012CheckMaskedBSSID b/server/site_tests/network_WiFiMatFunc/012CheckMaskedBSSID
deleted file mode 100644
index 2f59ef6..0000000
--- a/server/site_tests/network_WiFiMatFunc/012CheckMaskedBSSID
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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.
-
-# This test is designed to check that we can successfully scan for two
-# different SSIDs which respond with the same BSSID. Some client
-# firmwares may hold only one scan entry per BSSID and will foil attempts
-# to connect to certain types of APs.
-
-{ "name":"MaskedBSSID",
- "steps":[
- [ "create", { "type":"hostap" } ],
-
- # Create an AP, manually specifying both the SSID and BSSID.
- [ "config", { "channel":"2412", "mode":"11b",
- "bssid":"00:01:02:03:04:05",
- "ssid": "CrOS_Masked1" } ],
-
- # Create a second AP that responds to probe requests with the same BSSID
- # but an different SSID. These APs together are meant to emulate
- # situations that occur with some types of APs which broadcast or
- # respond with more than one (non-empty) SSID.
- [ "config", { "channel":"2412", "mode":"11b",
- "bssid":"00:01:02:03:04:05", "multi_interface":None,
- "ssid": "CrOS_Masked2" } ],
-
- # We cannot connect to this AP, since there are two separate APs that
- # respond to the same BSSID, but we can test to make sure both SSIDs
- # appears in the scan.
- [ "scan", { "freq": [ "2412" ],
- "ssid": [ "CrOS_Masked1", "CrOS_Masked2" ] } ],
-
- [ "destroy" ],
- ],
-}
diff --git a/server/site_tests/network_WiFi_MaskedBSSID/control.wifi_masked_bssid b/server/site_tests/network_WiFi_MaskedBSSID/control.wifi_masked_bssid
new file mode 100644
index 0000000..31b326e
--- /dev/null
+++ b/server/site_tests/network_WiFi_MaskedBSSID/control.wifi_masked_bssid
@@ -0,0 +1,25 @@
+# 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.
+
+AUTHOR = 'wiley@chromium.com'
+NAME = 'network_WiFi_MaskedBSSID'
+TIME = 'SHORT'
+TEST_TYPE = 'Server'
+
+DOC = """
+This test is designed to check that we can successfully scan for two
+different SSIDs which respond with the same BSSID. Some client
+firmwares may hold only one scan entry per BSSID and will foil attempts
+to connect to certain types of APs.
+"""
+
+
+def run(machine):
+ host = hosts.create_host(machine)
+ job.run_test('network_WiFi_MaskedBSSID',
+ host=host,
+ raw_cmdline_args=args)
+
+
+parallel_simple(run, machines)
diff --git a/server/site_tests/network_WiFi_MaskedBSSID/network_WiFi_MaskedBSSID.py b/server/site_tests/network_WiFi_MaskedBSSID/network_WiFi_MaskedBSSID.py
new file mode 100644
index 0000000..1a5b653
--- /dev/null
+++ b/server/site_tests/network_WiFi_MaskedBSSID/network_WiFi_MaskedBSSID.py
@@ -0,0 +1,46 @@
+# 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.
+
+from autotest_lib.server import site_linux_system
+from autotest_lib.server.cros.wlan import hostap_config
+from autotest_lib.server.cros.wlan import wifi_cell_test_base
+
+
+class network_WiFi_MaskedBSSID(wifi_cell_test_base.WiFiCellTestBase):
+ """Test behavior around masked BSSIDs."""
+ version = 1
+
+
+ def run_once_impl(self):
+ """Test body.
+
+ Set up two APs on the same channel/bssid but with different SSIDs.
+ Check that we can see both APs in scan results.
+
+ """
+ self.context.router.require_capabilities(
+ [site_linux_system.LinuxSystem.CAPABILITY_MULTI_AP_SAME_BAND])
+ frequency = 2412
+ configurations = [hostap_config.HostapConfig(
+ frequency=frequency,
+ mode=hostap_config.HostapConfig.MODE_11B,
+ bssid='00:11:22:33:44:55',
+ ssid=('CrOS_Masked%d' % i)) for i in range(2)]
+ # Create an AP, manually specifying both the SSID and BSSID.
+ self.context.configure(configurations[0])
+ # Create a second AP that responds to probe requests with the same BSSID
+ # but an different SSID. These APs together are meant to emulate
+ # situations that occur with some types of APs which broadcast or
+ # respond with more than one (non-empty) SSID.
+ self.context.configure(configurations[1], multi_interface=True)
+ # We cannot connect to this AP, since there are two separate APs that
+ # respond to the same BSSID, but we can test to make sure both SSIDs
+ # appears in the scan.
+ self.context.client.scan([frequency],
+ [config.ssid for config in configurations])
+ self.context.router.deconfig()
+
+
+
+
diff --git a/server/site_wifitest.py b/server/site_wifitest.py
index dc3ce4a..320ac83 100644
--- a/server/site_wifitest.py
+++ b/server/site_wifitest.py
@@ -392,11 +392,8 @@
raise error.TestNAError(
"%s: client is missing required capability: %s" %
(self.name, requirement))
- for requirement in self.router_requirements:
- if not requirement in self.wifi.capabilities:
- raise error.TestNAError(
- "%s: AP is missing required capability: %s" %
- (self.name, requirement))
+
+ self.wifi.require_capabilities(self.router_requirements)
for step_number, s in enumerate(self.steps):
method = s[0]
@@ -1745,22 +1742,18 @@
def scan(self, params):
- scan_params = ''
- frequencies = params.get('freq', [])
- if frequencies:
- scan_params += ' freq %s' % ' '.join(frequencies)
+ """Ask the DUT to scan for SSIDs on frequencies.
+
+ |params| may contain 'freq' and 'ssid' keys, which should
+ map to lists of frequencies and ssids respectively. Asserts
+ that we find all 'ssid' members listed.
+
+ @param params dict of settings for scan.
+
+ """
+ frequencies = map(int, params.get('freq', []))
ssids = params.get('ssid', [])
- if ssids:
- scan_params += ' ssid "%s"' % '" "'.join(ssids)
- result = self.client.run("%s dev %s scan%s" %
- (self.client_proxy.command_iw,
- self.client_wlanif,
- scan_params))
- scan_lines = result.stdout.splitlines()
- for ssid in ssids:
- if ssid and ('\tSSID: %s' % ssid) not in scan_lines:
- raise error.TestFail('SSID %s is not in scan results: %s' %
- (ssid, result.stdout))
+ self.client_proxy.scan(frequencies, ssids)
def time_sync(self, params):