1 ##############################################################################
2 # Copyright (c) 2015 Ericsson AB and others.
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
11 # iperf3 homepage at: http://software.es.net/iperf/
13 from __future__ import absolute_import
14 from __future__ import print_function
19 from oslo_serialization import jsonutils
21 import yardstick.ssh as ssh
22 from yardstick.common import utils
23 from yardstick.benchmark.scenarios import base
25 LOG = logging.getLogger(__name__)
28 class Iperf(base.Scenario):
29 """Execute iperf3 between two hosts
31 By default TCP is used but UDP can also be configured.
32 For more info see http://software.es.net/iperf
35 bytes - number of bytes to transmit
36 only valid with a non duration runner, mutually exclusive with blockcount
40 udp - use UDP rather than TCP
44 nodelay - set TCP no delay, disabling Nagle's Algorithm
48 blockcount - number of blocks (packets) to transmit,
49 only valid with a non duration runner, mutually exclusive with bytes
54 __scenario_type__ = "Iperf3"
56 def __init__(self, scenario_cfg, context_cfg):
57 self.scenario_cfg = scenario_cfg
58 self.context_cfg = context_cfg
59 self.setup_done = False
62 host = self.context_cfg['host']
63 target = self.context_cfg['target']
65 LOG.info("user:%s, target:%s", target['user'], target['ip'])
66 self.target = ssh.SSH.from_node(target, defaults={"user": "ubuntu"})
67 self.target.wait(timeout=600)
69 LOG.info("user:%s, host:%s", host['user'], host['ip'])
70 self.host = ssh.SSH.from_node(host, defaults={"user": "ubuntu"})
71 self.host.wait(timeout=600)
74 LOG.debug("Starting iperf3 server with command: %s", cmd)
75 status, _, stderr = self.target.execute(cmd)
77 raise RuntimeError(stderr)
79 self.setup_done = True
84 status, stdout, stderr = self.target.execute("pkill iperf3")
89 def run(self, result):
90 """execute the benchmark"""
91 if not self.setup_done:
94 # if run by a duration runner, get the duration time and setup as arg
95 time = self.scenario_cfg["runner"].get("duration", None) \
96 if "runner" in self.scenario_cfg else None
97 options = self.scenario_cfg['options']
99 cmd = "iperf3 -c %s --json" % (self.context_cfg['target']['ipaddr'])
101 # If there are no options specified
109 if "bandwidth" in options:
110 cmd += " --bandwidth %s" % options["bandwidth"]
113 if "nodelay" in options:
116 # these options are mutually exclusive in iperf3
119 elif "bytes" in options:
120 # number of bytes to transmit (instead of --time)
121 cmd += " --bytes %d" % options["bytes"]
122 elif "blockcount" in options:
123 cmd += " --blockcount %d" % options["blockcount"]
125 LOG.debug("Executing command: %s", cmd)
127 status, stdout, stderr = self.host.execute(cmd)
129 # error cause in json dict on stdout
130 raise RuntimeError(stdout)
132 # Note: convert all ints to floats in order to avoid
133 # schema conflicts in influxdb. We probably should add
134 # a format func in the future.
135 iperf_result = jsonutils.loads(stdout, parse_int=float)
136 result.update(utils.flatten_dict_key(iperf_result))
138 if "sla" in self.scenario_cfg:
139 sla_iperf = self.scenario_cfg["sla"]
141 sla_bytes_per_second = int(sla_iperf["bytes_per_second"])
143 # convert bits per second to bytes per second
145 int(iperf_result["end"]["sum_received"]["bits_per_second"])
146 bytes_per_second = bit_per_second / 8
147 assert bytes_per_second >= sla_bytes_per_second, \
148 "bytes_per_second %d < sla:bytes_per_second (%d); " % \
149 (bytes_per_second, sla_bytes_per_second)
151 sla_jitter = float(sla_iperf["jitter"])
153 jitter_ms = float(iperf_result["end"]["sum"]["jitter_ms"])
154 assert jitter_ms <= sla_jitter, \
155 "jitter_ms %f > sla:jitter %f; " % \
156 (jitter_ms, sla_jitter)
160 """internal test function"""
161 key_filename = pkg_resources.resource_filename('yardstick.resources',
162 'files/yardstick_key')
165 'ip': '10.229.47.137',
167 'key_filename': key_filename
170 'ip': '10.229.47.137',
172 'key_filename': key_filename,
173 'ipaddr': '10.229.47.137',
177 logger = logging.getLogger('yardstick')
178 logger.setLevel(logging.DEBUG)
180 options = {'packetsize': 120}
181 args = {'options': options}
189 if __name__ == '__main__':