blob: 0be14916fe69192661e6df7ee060198ee88b8b07 [file] [log] [blame]
# Lint as: python2, python3
# Copyright 2021 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import time
from autotest_lib.server.cros.network import iperf_runner
class IperfSession(object):
"""Runs iperf tests and reports average results."""
MEASUREMENT_MAX_SAMPLES = 10
MEASUREMENT_MAX_FAILURES = 2
MEASUREMENT_MIN_SAMPLES = 3
MAX_THROUGHPUT_CV = 0.03
def __init__(self,
client_proxy,
server_proxy,
client_interface=None,
server_interface=None,
ignore_failures=False):
"""Construct an IperfSession.
@param client_proxy: LinuxSystem object.
@param server_proxy: LinuxSystem object.
@param client_interface Interface object.
@param server_interface Interface object.
"""
self._client_proxy = client_proxy
self._server_proxy = server_proxy
self._client_interface = client_interface
self._server_interface = server_interface
self._ignore_failures = ignore_failures
def run(self, config, broadcast_rf_data=False, broadcast_rf_time=None):
"""Run multiple iperf tests and take the average performance values.
@param config IperfConfig.
@param broadcast_rf_data bool True iff RF data will be broadcast during
the iperf session.
@param broadcast_rf_time number of seconds RF data will be broadcast
if at all otherwise None.
"""
start_time = time.time()
logging.info('Performing %s measurements in iperf session.',
config.test_type)
history = []
failure_count = 0
final_result = None
with iperf_runner.IperfRunner(self._client_proxy, self._server_proxy,
config, self._client_interface,
self._server_interface) as runner:
while len(history) + failure_count < self.MEASUREMENT_MAX_SAMPLES:
result = runner.run(ignore_failures=self._ignore_failures)
if broadcast_rf_data:
elapsed_time = time.time() - start_time
if elapsed_time > broadcast_rf_time:
logging.info('Discarded most recent result because RF'
' data stopped broadcasting.')
break
if result is None:
failure_count += 1
# Might occur when, e.g., signal strength is too low.
if failure_count > self.MEASUREMENT_MAX_FAILURES:
logging.error('Too many failures (%d), aborting',
failure_count)
break
continue
logging.info('Took iperf %s Measurement: %r', config.test_type,
result)
history.append(result)
if len(history) < self.MEASUREMENT_MIN_SAMPLES:
continue
final_result = iperf_runner.IperfResult.from_samples(history, config)
if final_result.throughput_cv_less_than_maximum(
self.MAX_THROUGHPUT_CV):
break
if final_result is None:
final_result = iperf_runner.IperfResult.from_samples(history, config)
logging.info('Took averaged measurement from %s iperf %s runs: %r.',
len(history), config.test_type, final_result)
return history or None