autotest: Migrate network_WiFiMatFunc/011CheckIBSS to new framework

TEST=This is a test, it passes.  In addition, running 011CheckIBSS still
passes with the modifications to site_wifitest.  check11b also passes.
BUG=chromium:245907
CQ-DEPEND=CL:57385

Change-Id: Ibd370bfb5e0fd21e3bce084834e8f38a8512422d
Reviewed-on: https://gerrit.chromium.org/gerrit/57386
Tested-by: Christopher Wiley <wiley@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Commit-Queue: Christopher Wiley <wiley@chromium.org>
diff --git a/client/common_lib/cros/network/shill_xmlrpc_server.py b/client/common_lib/cros/network/shill_xmlrpc_server.py
index ab06468..5d34515 100755
--- a/client/common_lib/cros/network/shill_xmlrpc_server.py
+++ b/client/common_lib/cros/network/shill_xmlrpc_server.py
@@ -114,6 +114,7 @@
                 params.security,
                 params.psk,
                 params.save_credentials,
+                station_type=params.station_type,
                 hidden_network=params.is_hidden,
                 discovery_timeout_seconds=params.discovery_timeout,
                 association_timeout_seconds=params.association_timeout,
diff --git a/client/common_lib/cros/network/xmlrpc_datatypes.py b/client/common_lib/cros/network/xmlrpc_datatypes.py
index 358a399..2fbd581 100644
--- a/client/common_lib/cros/network/xmlrpc_datatypes.py
+++ b/client/common_lib/cros/network/xmlrpc_datatypes.py
@@ -12,6 +12,10 @@
     DEFAULT_DISCOVERY_TIMEOUT = 15
     DEFAULT_ASSOCIATION_TIMEOUT = 15
     DEFAULT_CONFIGURATION_TIMEOUT = 15
+    # Mode for most routers and access points.
+    STATION_TYPE_MANAGED = 'managed'
+    # Mode for certain kinds of p2p networks like old Android phone hotspots.
+    STATION_TYPE_IBSS = 'ibss'
 
     def __init__(self, serialized=None):
         """Construct an AssociationParameters.
@@ -48,6 +52,9 @@
         self.is_hidden = serialized.get('is_hidden', False)
         # Passing false tells shill not to remember the configured service.
         self.save_credentials = serialized.get('save_credentials', False)
+        # Station type to connect with.  Usually left unfilled unless we're
+        # connecting to a non-managed BSS.
+        self.station_type = serialized.get('station_type', None)
 
 
 class AssociationResult(xmlrpc_datatypes.XmlRpcStruct):
diff --git a/server/cros/wlan/hostap_config.py b/server/cros/wlan/hostap_config.py
index e6a3589..aee8226 100644
--- a/server/cros/wlan/hostap_config.py
+++ b/server/cros/wlan/hostap_config.py
@@ -153,7 +153,7 @@
                 break
         else:
             raise error.TestError('Invalid channel %r or frequency %r '
-                                  'specified.' % channel, frequency)
+                                  'specified.' % (channel, frequency))
 
         self.is_11n = False
         self.require_ht = False
@@ -240,3 +240,13 @@
                                      self.ssid,
                                      self.bssid,
                                      self.wmm_enabled))
+
+
+    def get_ssid(self, default_ssid):
+        """Build up the SSID for this network given a router's default SSID.
+
+        @param default_ssid string default ssid for a router.
+        @return string configured ssid or a slight mutation of the default ssid.
+
+        """
+        return self.ssid or (default_ssid + self.ssid_suffix)[-32:]
diff --git a/server/cros/wlan/wifi_test_context_manager.py b/server/cros/wlan/wifi_test_context_manager.py
index a8973e6..8032237 100644
--- a/server/cros/wlan/wifi_test_context_manager.py
+++ b/server/cros/wlan/wifi_test_context_manager.py
@@ -122,7 +122,8 @@
         return self.server.wifi_ip
 
 
-    def configure(self, configuration_parameters, multi_interface=None):
+    def configure(self, configuration_parameters, multi_interface=None,
+                  is_ibss=None):
         """Configure a router with the given parameters.
 
         Configures an AP according to the specified parameters and
@@ -132,9 +133,18 @@
         @param configuration_parameters HostapConfig object.
         @param multi_interface True iff having multiple configured interfaces
                 is expected for this configure call.
+        @param is_ibss True iff this is an IBSS endpoint.
 
         """
-        self.router.hostap_configure(configuration_parameters, multi_interface)
+        if is_ibss:
+            if multi_interface:
+                raise error.TestFail('IBSS mode does not support multiple '
+                                     'interfaces.')
+
+            self.router.ibss_configure(configuration_parameters)
+        else:
+            self.router.hostap_configure(configuration_parameters,
+                                         multi_interface=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 0961e2a..6b37fdf 100644
--- a/server/site_linux_router.py
+++ b/server/site_linux_router.py
@@ -8,6 +8,7 @@
 from autotest_lib.client.common_lib import error
 from autotest_lib.server import site_linux_system
 from autotest_lib.server.cros import wifi_test_utils
+from autotest_lib.server.cros.wlan import hostap_config
 
 def isLinuxRouter(host):
     """Check if host is a linux router.
@@ -19,6 +20,7 @@
     router_uname = host.run('uname').stdout
     return re.search('Linux', router_uname)
 
+
 class LinuxRouter(site_linux_system.LinuxSystem):
     """Linux/mac80211-style WiFi Router support for WiFiTest class.
 
@@ -188,6 +190,7 @@
             'interface': interface
         })
 
+
     def _kill_process_instance(self, process, instance=None, wait=0):
         """Kill a process on the router.
 
@@ -214,6 +217,7 @@
         else:
             self.router.run(cmd, ignore_status=True)
 
+
     def kill_hostapd_instance(self, instance):
         """Kills a hostapd instance.
 
@@ -222,6 +226,7 @@
         """
         self._kill_process_instance('hostapd', instance, 30)
 
+
     def kill_hostapd(self):
         """Kill all hostapd instances."""
         self.kill_hostapd_instance(None)
@@ -251,10 +256,7 @@
             self.deconfig()
         # 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
+        conf['ssid'] = configuration.get_ssid(self.defssid)
         if configuration.bssid:
             conf['bssid'] = configuration.bssid
         conf['channel'] = configuration.channel
@@ -432,6 +434,7 @@
         logging.info("AP configured.")
         self.hostapd['configured'] = True
 
+
     @staticmethod
     def ip_addr(netblock, idx):
         """Simple IPv4 calculator.
@@ -460,57 +463,28 @@
                                   for a, m, o in zip(addr, mask, offset)]))
 
 
-    def station_config(self, params):
-        """Configure a station based AP.
+    def ibss_configure(self, config):
+        """Configure a station based AP in IBSS mode.
 
-        @param params dict of site_wifitest parameters.
+        Extract relevant configuration objects from |config| despite not
+        actually being a hostap managed endpoint.
+
+        @param config HostapConfig object.
 
         """
-        # keep parameter modifications local-only
-        orig_params = params
-        params = params.copy()
-
-        if 'multi_interface' in params:
-            raise NotImplementedError("station with multi_interface")
-
-        if self.station['type'] != 'ibss':
-            raise NotImplementedError("non-ibss station")
-
         if self.station['configured'] or self.hostapd['configured']:
             self.deconfig()
-
-        local_server = params.pop('local_server', False)
-        mode = None
-        conf = self.station['conf']
-        for k, v in params.iteritems():
-            if k == 'ssid_suffix':
-                conf['ssid'] = self.defssid + v
-            elif k == 'channel':
-                freq = int(v)
-                if freq > 2484:
-                    mode = 'a'
-            elif k == 'mode':
-                if v == '11a':
-                    mode = 'a'
-            else:
-                conf[k] = v
-
-        interface = self._get_wlanif(freq, self.phytype, mode)
-
-        # Run interface configuration commands
-        for k, v in conf.iteritems():
-            if k != 'ssid':
-                self.router.run("%s dev %s set %s %s" %
-                                (self.cmd_iw, interface, k, v))
-
+        interface = self._get_wlanif(config.frequency, self.phytype,
+                                     config.hw_mode)
+        ssid = config.get_ssid(self.defssid)
+        self.station['conf']['ssid'] = ssid
         # Connect the station
-        self.router.run("%s link set %s up" % (self.cmd_ip, interface))
-        self.router.run("%s dev %s ibss join %s %d" %
-                        (self.cmd_iw, interface, conf['ssid'], freq))
-
-        if self.force_local_server or local_server is not False:
-            self.start_local_server(interface)
-
+        self.router.run('%s link set %s up' % (self.cmd_ip, interface))
+        self.router.run('%s dev %s ibss join %s %d' % (self.cmd_iw, interface,
+                                                       ssid, config.frequency))
+        # Always start a local server.
+        self.start_local_server(interface)
+        # Remember that this interface is up.
         self.station['configured'] = True
         self.station['interface'] = interface
 
@@ -526,6 +500,7 @@
         """
         return '%d.%d.%d.%d' % (192, 168, index, 254)
 
+
     def start_local_server(self, interface):
         """Start a local server on an interface.
 
@@ -562,6 +537,7 @@
                         (self.cmd_ip, interface))
         self.start_dhcp_server(interface)
 
+
     def start_dhcp_server(self, interface):
         """Start a dhcp server on an interface.
 
@@ -593,6 +569,7 @@
         """
         self._kill_process_instance('dhcpd', instance, 0)
 
+
     def stop_dhcp_servers(self):
         """Stop all dhcp servers on the router."""
         self.stop_dhcp_server(None)
@@ -607,7 +584,10 @@
         if self.apmode:
             self.hostap_config(params)
         else:
-            self.station_config(params)
+            config = hostap_config.HostapConfig(
+                    ssid=self.get_ssid(),
+                    frequency=int(params.get('channel', None)))
+            self.ibss_configure(config)
 
 
     def get_wifi_ip(self, ap_num):
@@ -720,7 +700,10 @@
 
     def get_ssid(self):
         """@return string ssid for the network stemming from this router."""
-        return self.hostapd['conf']['ssid']
+        if self.hostapd['configured']:
+            return self.hostapd['conf']['ssid']
+
+        return self.station['conf']['ssid']
 
 
     def set_txpower(self, params):
diff --git a/server/site_tests/network_WiFiMatFunc/011CheckIBSS b/server/site_tests/network_WiFiMatFunc/011CheckIBSS
deleted file mode 100644
index 681e667..0000000
--- a/server/site_tests/network_WiFiMatFunc/011CheckIBSS
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2010 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.
-
-# Purpose: This test verifies that DUT can connect to an IBSS (AdHoc) server.
-
-{ "name":"CheckIBSS",
-  "steps":[
-    [ "create",         { "type":"ibss" } ],
-    [ "config",         { "channel":"2412", "mode":"11b",
-                          "local_server": {} } ],
-    # There's a delay before the IBSS service becomes ready
-    [ "sleep",          { "time": "5" } ],
-    [ "connect",        { "security":"none", "mode":"adhoc" } ],
-    [ "client_ping",    { "count":"10", "dest":"router" } ],
-    [ "destroy" ],
-  ],
-}
diff --git a/server/site_tests/network_WiFi_IBSS/control.wifi_IBSS b/server/site_tests/network_WiFi_IBSS/control.wifi_IBSS
new file mode 100644
index 0000000..1d00771
--- /dev/null
+++ b/server/site_tests/network_WiFi_IBSS/control.wifi_IBSS
@@ -0,0 +1,24 @@
+# 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_IBSS'
+TIME = 'SHORT'
+TEST_TYPE = 'Server'
+SUITE = 'wifi_matfunc'
+DEPENDENCIES = 'wificell'
+
+DOC = """
+This test verifies that DUT can connect to an IBSS (AdHoc) server.
+"""
+
+
+def run(machine):
+    host = hosts.create_host(machine)
+    job.run_test('network_WiFi_IBSS',
+                 host=host,
+                 raw_cmdline_args=args)
+
+
+parallel_simple(run, machines)
diff --git a/server/site_tests/network_WiFi_IBSS/network_WiFi_IBSS.py b/server/site_tests/network_WiFi_IBSS/network_WiFi_IBSS.py
new file mode 100644
index 0000000..a0ce0e7
--- /dev/null
+++ b/server/site_tests/network_WiFi_IBSS/network_WiFi_IBSS.py
@@ -0,0 +1,28 @@
+# 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.client.common_lib.cros.network import xmlrpc_datatypes
+from autotest_lib.server.cros.wlan import hostap_config
+from autotest_lib.server.cros.wlan import wifi_cell_test_base
+
+
+class network_WiFi_IBSS(wifi_cell_test_base.WiFiCellTestBase):
+    """Test that we can connect to an IBSS (Adhoc) endpoint."""
+    version = 1
+
+
+    def run_once_impl(self):
+        """Body of the test."""
+        self.context.router.create_wifi_device(device_type='ibss')
+        configuration = hostap_config.HostapConfig(
+                frequency=2412, mode=hostap_config.HostapConfig.MODE_11B)
+        self.context.configure(configuration, is_ibss=True)
+        assoc_params = xmlrpc_datatypes.AssociationParameters()
+        assoc_params.ssid = self.context.router.get_ssid()
+        assoc_params.station_type = \
+                xmlrpc_datatypes.AssociationParameters.STATION_TYPE_IBSS
+        self.assert_connect_wifi(assoc_params)
+        self.assert_ping_from_dut()
+        self.context.client.shill.disconnect(assoc_params.ssid)
+        self.context.router.deconfig()