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
53 length - length of buffer to read or write,
54 (default 128 KB for TCP, 8 KB for UDP)
58 window - set window size / socket buffer size
59 set TCP windows size. for UDP way to test, this will set to accept UDP
60 packet buffer size, limit the max size of acceptable data packet.
65 __scenario_type__ = "Iperf3"
67 def __init__(self, scenario_cfg, context_cfg):
68 self.scenario_cfg = scenario_cfg
69 self.context_cfg = context_cfg
70 self.setup_done = False
73 host = self.context_cfg['host']
74 target = self.context_cfg['target']
76 LOG.info("user:%s, target:%s", target['user'], target['ip'])
77 self.target = ssh.SSH.from_node(target, defaults={"user": "ubuntu"})
78 self.target.wait(timeout=600)
80 LOG.info("user:%s, host:%s", host['user'], host['ip'])
81 self.host = ssh.SSH.from_node(host, defaults={"user": "ubuntu"})
82 self.host.wait(timeout=600)
85 LOG.debug("Starting iperf3 server with command: %s", cmd)
86 status, _, stderr = self.target.execute(cmd)
88 raise RuntimeError(stderr)
90 self.setup_done = True
95 status, _, stderr = self.target.execute("pkill iperf3")
100 def run(self, result):
101 """execute the benchmark"""
102 if not self.setup_done:
105 # if run by a duration runner, get the duration time and setup as arg
106 time = self.scenario_cfg["runner"].get("duration", None) \
107 if "runner" in self.scenario_cfg else None
108 options = self.scenario_cfg['options']
110 cmd = "iperf3 -c %s --json" % (self.context_cfg['target']['ipaddr'])
112 # If there are no options specified
118 protocol = options.get("protocol")
119 bandwidth = options.get('bandwidth')
120 use_UDP = protocol == 'udp'
122 cmd += " --" + protocol
123 if use_UDP and bandwidth:
124 cmd += " --bandwidth " + bandwidth
125 # if nodelay in the option, protocal maybe null or 'tcp'
126 if "nodelay" in options:
128 except AttributeError:
129 LOG.warning("Can't parser the options in your config file!!!")
131 # these options are mutually exclusive in iperf3
134 elif "bytes" in options:
135 # number of bytes to transmit (instead of --time)
136 cmd += " --bytes %d" % options["bytes"]
137 elif "blockcount" in options:
138 cmd += " --blockcount %d" % options["blockcount"]
140 if "length" in options:
141 cmd += " --length %s" % options["length"]
143 if "window" in options:
144 cmd += " --window %s" % options["window"]
146 LOG.debug("Executing command: %s", cmd)
148 status, stdout, _ = self.host.execute(cmd)
150 # error cause in json dict on stdout
151 raise RuntimeError(stdout)
153 # Note: convert all ints to floats in order to avoid
154 # schema conflicts in influxdb. We probably should add
155 # a format func in the future.
156 iperf_result = jsonutils.loads(stdout, parse_int=float)
157 result.update(utils.flatten_dict_key(iperf_result))
159 if "sla" in self.scenario_cfg:
160 sla_iperf = self.scenario_cfg["sla"]
162 sla_bytes_per_second = int(sla_iperf["bytes_per_second"])
164 # convert bits per second to bytes per second
166 int(iperf_result["end"]["sum_received"]["bits_per_second"])
167 bytes_per_second = bit_per_second / 8
169 bytes_per_second >= sla_bytes_per_second,
170 "bytes_per_second %d < sla:bytes_per_second (%d); "
171 % (bytes_per_second, sla_bytes_per_second))
173 sla_jitter = float(sla_iperf["jitter"])
175 jitter_ms = float(iperf_result["end"]["sum"]["jitter_ms"])
176 self.verify_SLA(jitter_ms <= sla_jitter,
177 "jitter_ms %f > sla:jitter %f; "
178 % (jitter_ms, sla_jitter))
182 """internal test function"""
183 key_filename = pkg_resources.resource_filename('yardstick.resources',
184 'files/yardstick_key')
187 'ip': '10.229.47.137',
189 'key_filename': key_filename
192 'ip': '10.229.47.137',
194 'key_filename': key_filename,
195 'ipaddr': '10.229.47.137',
199 logger = logging.getLogger('yardstick')
200 logger.setLevel(logging.DEBUG)
202 options = {'packetsize': 120}
203 args = {'options': options}
211 if __name__ == '__main__':