• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import time
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.common_lib import utils
10from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
11from autotest_lib.server.cros.network import netperf_runner
12from autotest_lib.server.cros.network import netperf_session
13from autotest_lib.server.cros.network import wifi_cell_test_base
14
15
16class network_WiFi_Perf(wifi_cell_test_base.WiFiCellTestBase):
17    """Test maximal achievable bandwidth on several channels per band.
18
19    Conducts a performance test for a set of specified router configurations
20    and reports results as keyval pairs.
21
22    """
23
24    version = 1
25
26    NETPERF_CONFIGS = [
27            netperf_runner.NetperfConfig(
28                       netperf_runner.NetperfConfig.TEST_TYPE_TCP_STREAM),
29            netperf_runner.NetperfConfig(
30                       netperf_runner.NetperfConfig.TEST_TYPE_TCP_MAERTS),
31            netperf_runner.NetperfConfig(
32                       netperf_runner.NetperfConfig.TEST_TYPE_UDP_STREAM),
33            netperf_runner.NetperfConfig(
34                       netperf_runner.NetperfConfig.TEST_TYPE_UDP_MAERTS),
35    ]
36
37
38    def parse_additional_arguments(self, commandline_args, additional_params):
39        """Hook into super class to take control files parameters.
40
41        @param commandline_args dict of parsed parameters from the autotest.
42        @param additional_params list of HostapConfig objects.
43
44        """
45        if 'governor' in commandline_args:
46            self._governor = commandline_args['governor']
47            # validate governor string. Not all machines will support all of
48            # these governors, but this at least ensures that a potentially
49            # valid governor was passed in
50            if self._governor not in ('performance', 'powersave', 'userspace',
51                                      'ondemand', 'conservative', 'schedutil'):
52                logging.warning('Unrecognized CPU governor "%s". Running test '
53                        'without setting CPU governor...' % self._governor)
54                self._governor = None
55        else:
56            self._governor = None
57        self._ap_configs = additional_params
58
59
60    def do_run(self, ap_config, session, power_save, governor):
61        """Run a single set of perf tests, for a given AP and DUT config.
62
63        @param ap_config: the AP configuration that is being used
64        @param session: a netperf session instance
65        @param power_save: whether or not to use power-save mode on the DUT
66                           (boolean)
67
68        """
69        def get_current_governor(host):
70            """
71            @ return the CPU governor name used on a machine. If cannot find
72                     the governor info of the host, or if there are multiple
73                     different governors being used on different cores, return
74                     'default'.
75            """
76            try:
77                governors = set(utils.get_scaling_governor_states(host))
78                if len(governors) != 1:
79                    return 'default'
80                return next(iter(governors))
81            except:
82                return 'default'
83        if governor:
84            client_governor = utils.get_scaling_governor_states(
85                    self.context.client.host)
86            router_governor = utils.get_scaling_governor_states(
87                    self.context.router.host)
88            utils.set_scaling_governors(governor, self.context.client.host)
89            utils.set_scaling_governors(governor, self.context.router.host)
90            governor_name = governor
91        else:
92            # try to get machine's current governor
93            governor_name = get_current_governor(self.context.client.host)
94            if governor_name != get_current_governor(self.context.router.host):
95                governor_name = 'default'
96            if governor_name == self._governor:
97                # If CPU governor is already set to self._governor, don't
98                # perform the run twice
99                return
100
101        self.context.client.powersave_switch(power_save)
102        session.warmup_stations()
103        ps_tag = 'PS%s' % ('on' if power_save else 'off')
104        governor_tag = 'governor-%s' % governor_name
105        ap_config_tag = '_'.join([ap_config.perf_loggable_description,
106                                  ps_tag, governor_tag])
107        signal_level = self.context.client.wifi_signal_level
108        signal_description = '_'.join([ap_config_tag, 'signal'])
109        self.write_perf_keyval({signal_description: signal_level})
110        for config in self.NETPERF_CONFIGS:
111            results = session.run(config)
112            if not results:
113                logging.error('Failed to take measurement for %s',
114                              config.tag)
115                continue
116            values = [result.throughput for result in results]
117            self.output_perf_value(config.tag, values, units='Mbps',
118                                   higher_is_better=True,
119                                   graph=ap_config_tag)
120            result = netperf_runner.NetperfResult.from_samples(results)
121            self.write_perf_keyval(result.get_keyval(
122                prefix='_'.join([ap_config_tag, config.tag])))
123        if governor:
124            utils.restore_scaling_governor_states(client_governor,
125                    self.context.client.host)
126            utils.restore_scaling_governor_states(router_governor,
127                    self.context.router.host)
128
129
130    def run_once(self):
131        """Test body."""
132        start_time = time.time()
133        for ap_config in self._ap_configs:
134            # Set up the router and associate the client with it.
135            self.context.configure(ap_config)
136            # self.context.configure has a similar check - but that one only
137            # errors out if the AP *requires* VHT i.e. AP is requesting
138            # MODE_11AC_PURE and the client does not support it.
139            # For wifi_perf, we don't want to run MODE_11AC_MIXED on the AP if
140            # the client does not support VHT, as we are guaranteed to get the
141            # same results at 802.11n/HT40 in that case.
142            if ap_config.is_11ac and not self.context.client.is_vht_supported():
143                raise error.TestNAError('Client does not have AC support')
144            assoc_params = xmlrpc_datatypes.AssociationParameters(
145                    ssid=self.context.router.get_ssid(),
146                    security_config=ap_config.security_config)
147            self.context.assert_connect_wifi(assoc_params)
148            session = netperf_session.NetperfSession(self.context.client,
149                                                     self.context.router)
150
151            # Flag a test error if we disconnect for any reason.
152            with self.context.client.assert_no_disconnects():
153                # Conduct the performance tests while toggling powersave mode.
154                for power_save in (True, False):
155                    for governor in sorted(set([None, self._governor])):
156                        self.do_run(ap_config, session, power_save, governor)
157
158            # Clean up router and client state for the next run.
159            self.context.client.shill.disconnect(self.context.router.get_ssid())
160            self.context.router.deconfig()
161        end_time = time.time()
162        logging.info('Running time %0.1f seconds.', end_time - start_time)
163