Home | History | Annotate | Download | only in network_WiFi_AttenuatedPerf
      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 
      5 import collections
      6 import logging
      7 import os.path
      8 import time
      9 
     10 from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
     11 from autotest_lib.server.cros.network import netperf_runner
     12 from autotest_lib.server.cros.network import netperf_session
     13 from autotest_lib.server.cros.network import wifi_cell_test_base
     14 
     15 
     16 class network_WiFi_AttenuatedPerf(wifi_cell_test_base.WiFiCellTestBase):
     17     """Test maximal achievable bandwidth while varying attenuation.
     18 
     19     Performs a performance test for a specified router configuration as
     20     signal attentuation increases.
     21 
     22     """
     23 
     24     version = 1
     25 
     26     CMDLINE_SERIES_NOTE = 'series_note'
     27 
     28     NETPERF_CONFIGS = [
     29             netperf_runner.NetperfConfig(
     30                        netperf_runner.NetperfConfig.TEST_TYPE_TCP_STREAM),
     31             netperf_runner.NetperfConfig(
     32                        netperf_runner.NetperfConfig.TEST_TYPE_TCP_MAERTS),
     33             netperf_runner.NetperfConfig(
     34                        netperf_runner.NetperfConfig.TEST_TYPE_UDP_STREAM),
     35             netperf_runner.NetperfConfig(
     36                        netperf_runner.NetperfConfig.TEST_TYPE_UDP_MAERTS),
     37     ]
     38 
     39     ATTENUATION_STEP = 4
     40     FINAL_ATTENUATION = 100
     41 
     42     TSV_OUTPUT_DIR = 'tsvs'
     43 
     44     DataPoint = collections.namedtuple('DataPoint',
     45                                        ['attenuation', 'throughput',
     46                                         'variance', 'signal', 'test_type'])
     47 
     48 
     49     def parse_additional_arguments(self, commandline_args, additional_params):
     50         """Hook into super class to take control files parameters.
     51 
     52         @param commandline_args dict of parsed parameters from the autotest.
     53         @param additional_params list of dicts describing router configs.
     54 
     55         """
     56         self._ap_config = additional_params
     57         self.series_note = None
     58         if self.CMDLINE_SERIES_NOTE in commandline_args:
     59             self.series_note = commandline_args[self.CMDLINE_SERIES_NOTE]
     60 
     61 
     62     def run_once(self):
     63         start_time = time.time()
     64         throughput_data = []
     65         self.context.client.host.get_file('/etc/lsb-release', self.resultsdir)
     66         # Set up the router and associate the client with it.
     67         self.context.configure(self._ap_config)
     68         assoc_params = xmlrpc_datatypes.AssociationParameters(
     69                 ssid=self.context.router.get_ssid(),
     70                 security_config=self._ap_config.security_config)
     71         self.context.assert_connect_wifi(assoc_params)
     72 
     73         # Conduct the performance tests.  Ignore failures, since
     74         # at high attenuations, sometimes the control connection
     75         # is unable to terminate the test properly.
     76         session = netperf_session.NetperfSession(self.context.client,
     77                                                  self.context.router,
     78                                                  ignore_failures=True)
     79         session.warmup_stations() 
     80         start_atten = self.context.attenuator.get_minimal_total_attenuation()
     81         for atten in range(start_atten,
     82                            min(start_atten + 20, self.FINAL_ATTENUATION),
     83                            self.ATTENUATION_STEP):
     84             atten_tag = 'atten%03d' % atten
     85             self.context.attenuator.set_total_attenuation(
     86                     atten, self._ap_config.frequency)
     87             logging.info('RvR test: current attenuation = %d dB', atten)
     88             for config in self.NETPERF_CONFIGS:
     89                 results = session.run(config)
     90                 if not results:
     91                     logging.warning('Unable to take measurement for %s',
     92                                     config.human_readable_tag)
     93                     continue
     94                 graph_name = '.'.join(
     95                         [self._ap_config.perf_loggable_description, config.tag])
     96                 values = [result.throughput for result in results]
     97                 self.output_perf_value(atten_tag, values, units='Mbps',
     98                                        higher_is_better=True, graph=graph_name)
     99                 self.output_perf_value('_'.join([atten_tag, 'signal']),
    100                                        self.context.client.wifi_signal_level,
    101                                        units='dBm', higher_is_better=True,
    102                                        graph=graph_name)
    103                 result = netperf_runner.NetperfResult.from_samples(results)
    104                 throughput_data.append(self.DataPoint(
    105                         atten,
    106                         result.throughput,
    107                         result.throughput_dev,
    108                         self.context.client.wifi_signal_level,
    109                         config.tag))
    110                 keyval_prefix = '_'.join(
    111                         [self._ap_config.perf_loggable_description, config.tag,
    112                          atten_tag])
    113                 self.write_perf_keyval(result.get_keyval(prefix=keyval_prefix))
    114             signal_level = self.context.client.wifi_signal_level
    115             self.write_perf_keyval(
    116                     {'_'.join([atten_tag, 'signal']): signal_level})
    117         # Clean up router and client state.
    118         self.context.client.shill.disconnect(assoc_params.ssid)
    119         self.context.router.deconfig()
    120         end_time = time.time()
    121         logging.info('Running time %0.1f seconds.', end_time - start_time)
    122         self.write_throughput_tsv_files(throughput_data)
    123 
    124 
    125     def write_throughput_tsv_files(self, throughput_data):
    126         """Write out .tsv files with plotable data from |throughput_data|.
    127 
    128         Each .tsv file starts with a label for the series that can be
    129         customized with a short note passed in from the command line.
    130         It then has column headers and fields separated by tabs.  This format
    131         is easy to parse and also works well with spreadsheet programs for
    132         custom report generation.
    133 
    134         @param throughput_data a list of Datapoint namedtuples gathered from
    135                 tests.
    136 
    137         """
    138         logging.info('Writing .tsv files.')
    139         os.mkdir(os.path.join(self.resultsdir, self.TSV_OUTPUT_DIR))
    140         series_label_parts = [self.context.client.board,
    141                               'ch%03d' % self._ap_config.channel]
    142         if self.series_note:
    143             series_label_parts.insert(1, '(%s)' % self.series_note)
    144         header_parts = ['Attenuation', 'Throughput(Mbps)', 'StdDev(Mbps)',
    145                         'Client Reported Signal']
    146         mode = self._ap_config.printable_mode
    147         mode = mode.replace('+', 'p').replace('-', 'm').lower()
    148         result_file_prefix = '%s_ch%03d' % (mode, self._ap_config.channel)
    149         for test_type in set([data.test_type for data in throughput_data]):
    150             result_file = os.path.join(
    151                     self.resultsdir, self.TSV_OUTPUT_DIR,
    152                     '%s_%s.tsv' % (result_file_prefix, test_type))
    153             lines = [' '.join(series_label_parts),
    154                      '\t'.join(header_parts)]
    155             for result in sorted([datum for datum in throughput_data
    156                                   if datum.test_type == test_type]):
    157                 lines.append('\t'.join(map(str, result[0:4])))
    158             with open(result_file, 'w') as f:
    159                 f.writelines(['%s\n' % line for line in lines])
    160