autotest: Convert DTIM period test to new WiFi framework

This is another straightforward migration of a test to the new WiFi
framework.  As part of this change, we migrate powersave controls to
WiFiClient, and add DTIM period support to HostapConfig.

TEST=Ran:
./run_remote_tests.sh --remote=chromeos1-shelf1-host4 check_dtimperiod
./run_remote_tests.sh --remote=chromeos1-shelf1-host4 \
    network_WiFiMatFunc --args="test_pat=007*"
Which test both that the migrated test works and that the power save
migration is functionally identical to before.
BUG=chromium:230660

Change-Id: I4593bb6c61625ef69e0bf0256288a0cc9b031846
Reviewed-on: https://gerrit.chromium.org/gerrit/50065
Tested-by: Christopher Wiley <wiley@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Commit-Queue: Christopher Wiley <wiley@chromium.org>
diff --git a/server/cros/wlan/hostap_config.py b/server/cros/wlan/hostap_config.py
index 5a0cb4e..7f31167 100644
--- a/server/cros/wlan/hostap_config.py
+++ b/server/cros/wlan/hostap_config.py
@@ -113,7 +113,8 @@
 
 
     def __init__(self, mode=None, channel=None, frequency=None,
-                 n_capabilities=None, hide_ssid=None, beacon_interval=None):
+                 n_capabilities=None, hide_ssid=None, beacon_interval=None,
+                 dtim_period=None):
         """Construct a HostapConfig.
 
         You may specify channel or frequency, but not both.  Both options
@@ -126,6 +127,7 @@
         @param n_capabilities list of N_CAPABILITY_x defined above.
         @param hide_ssid True if we should set up a hidden SSID.
         @param beacon_interval int beacon interval of AP.
+        @param dtim_period int include a DTIM every |dtim_period| beacons.
 
         """
         super(HostapConfig, self).__init__()
@@ -204,3 +206,4 @@
 
         self.hide_ssid = hide_ssid
         self.beacon_interval = beacon_interval
+        self.dtim_period = dtim_period
diff --git a/server/cros/wlan/wifi_client.py b/server/cros/wlan/wifi_client.py
index f01e020..954c7c1 100644
--- a/server/cros/wlan/wifi_client.py
+++ b/server/cros/wlan/wifi_client.py
@@ -134,6 +134,7 @@
         Construct a WiFiClient.
 
         @param client_host host object representing a remote host.
+        @param result_dir string directory to store test logs/packet caps.
 
         """
         super(WiFiClient, self).__init__()
@@ -351,6 +352,7 @@
         for rule in self._firewall_rules:
             self._firewall_close(rule)
 
+
     def start_capture(self):
         """Start a packet capture.
 
@@ -400,3 +402,15 @@
 
         logging.info('Found iw link key %s with value %s.',
                      iw_link_key, actual_value)
+
+
+    def powersave_switch(self, turn_on):
+        """Toggle powersave mode for the DUT.
+
+        @param turn_on bool True iff powersave mode should be turned on.
+
+        """
+        mode = 'off'
+        if turn_on:
+            mode = 'on'
+        self.host.run('iw dev %s set power_save %s' % (self.wifi_if, mode))
diff --git a/server/site_linux_router.py b/server/site_linux_router.py
index a9d75bf..9d43e42 100644
--- a/server/site_linux_router.py
+++ b/server/site_linux_router.py
@@ -266,6 +266,8 @@
             conf['require_ht'] = 1
         if configuration.beacon_interval:
             conf['beacon_int'] = configuration.beacon_interval
+        if configuration.dtim_period:
+            conf['dtim_period'] = configuration.dtim_period
         self.start_hostapd(conf, {})
         # Configure transmit power
         tx_power_params = {'interface': conf['interface']}
diff --git a/server/site_tests/network_WiFiMatFunc/006CheckDTIM b/server/site_tests/network_WiFiMatFunc/006CheckDTIM
deleted file mode 100644
index 4b0a1e0..0000000
--- a/server/site_tests/network_WiFiMatFunc/006CheckDTIM
+++ /dev/null
@@ -1,23 +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 the DTIM period set on the AP was
-# successfully adopted by the DUT.
-
-# DTIM = delivery traffic information message.
-# DTIM period is the number of beacons between DTIMs
-# (1 = every beacon includes DTIM element. Default: 2).
-
-{ "name":"CheckDTIM",
-  "steps":[             # Channel 6
-    [ "create",         { "type":"hostap" } ],
-    [ "config",         { "channel":"2437", "mode":"11g", "dtimperiod":"5" } ],
-    [ "client_powersave_on" ],
-    [ "connect",        { "security":"none" } ],
-    [ "client_check_dtimperiod", [ "5" ] ],
-    [ "client_ping",    { "count":"10" } ],
-    [ "client_powersave_off" ],
-    [ "destroy" ],
-  ],
-}
diff --git a/server/site_tests/network_WiFi_DTIMPeriod/control.check_dtimperiod b/server/site_tests/network_WiFi_DTIMPeriod/control.check_dtimperiod
new file mode 100644
index 0000000..faaa481
--- /dev/null
+++ b/server/site_tests/network_WiFi_DTIMPeriod/control.check_dtimperiod
@@ -0,0 +1,23 @@
+# 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_DTIMPeriod'
+TIME = 'SHORT'
+TEST_TYPE = 'Server'
+
+DOC = """
+Purpose: This test verifies that the DTIM period set on the AP was
+successfully adopted by the DUT.
+"""
+
+
+def run(machine):
+    host = hosts.create_host(machine)
+    job.run_test('network_WiFi_DTIMPeriod',
+                 host=host,
+                 raw_cmdline_args=args)
+
+
+parallel_simple(run, machines)
diff --git a/server/site_tests/network_WiFi_DTIMPeriod/network_WiFi_DTIMPeriod.py b/server/site_tests/network_WiFi_DTIMPeriod/network_WiFi_DTIMPeriod.py
new file mode 100644
index 0000000..3ecae3d
--- /dev/null
+++ b/server/site_tests/network_WiFi_DTIMPeriod/network_WiFi_DTIMPeriod.py
@@ -0,0 +1,50 @@
+# 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_test_base
+from autotest_lib.server.cros.wlan import wifi_client
+
+
+class network_WiFi_DTIMPeriod(wifi_test_base.WiFiTestBase):
+    """Test that we understand the routers negotiated DTIM period."""
+    version = 1
+
+
+    def run_once_impl(self):
+        """DTIM period test.
+
+        DTIM stands for delivery traffic information message and refers to
+        the number of beacons between DTIMS.  For instance, a DTIM period
+        of 1 would indicate that every beacon should have a DTIM element.
+        The default DTIM period value is 2.
+
+        This flag is used in combination with powersave mode as follows:
+        1) A client goes into powersave mode and notifies the router.
+        2) While in powersave mode, the client turns off as much as possible;
+           the AP is supposed to buffer unicast traffic.
+        3) The client wakes up to receive beacons, which may include a DTIM
+           notification.
+        4) On receiving such a notification, the client should
+           stay up to recieve the pending frames.
+
+        """
+        dtim_val = 5
+        configuration = hostap_config.HostapConfig(
+                frequency=2437,
+                mode=hostap_config.HostapConfig.MODE_11G,
+                dtim_period=dtim_val)
+        self.context.configure(configuration)
+        assoc_params = xmlrpc_datatypes.AssociationParameters()
+        assoc_params.ssid = self.context.router.get_ssid()
+        self.context.client.powersave_switch(True)
+        self.assert_connect_wifi(assoc_params)
+        self.context.client.check_iw_link_value(
+                wifi_client.WiFiClient.IW_LITNK_KEY_DTIM_PERIOD,
+                dtim_val)
+        self.assert_ping_from_dut()
+        self.context.client.shill.disconnect(assoc_params.ssid)
+        self.context.client.powersave_switch(False)
+        self.context.router.deconfig()
diff --git a/server/site_wifitest.py b/server/site_wifitest.py
index e1be7ac..32a7886 100644
--- a/server/site_wifitest.py
+++ b/server/site_wifitest.py
@@ -952,13 +952,21 @@
 
 
     def client_powersave_on(self, params):
-        """ Enable power save operation """
-        self.client.run("iw dev %s set power_save on" % self.client_wlanif)
+        """Enable power save operation.
+
+        @param params ignored, but required by this framework.
+
+        """
+        self.client_proxy.powersave_switch(True)
 
 
     def client_powersave_off(self, params):
-        """ Disable power save operation """
-        self.client.run("iw dev %s set power_save off" % self.client_wlanif)
+        """Disable power save operation.
+
+        @param params ignored, but required by this framework.
+
+        """
+        self.client_proxy.powersave_switch(False)
 
 
     def client_check_powersave(self, params):