blob: 8a50b8f9c7b45a63313ae2961d556d7c343fdb75 [file] [log] [blame]
mbligh44394242009-06-15 21:31:32 +00001import os, time, re, logging
mbligh67a72f92009-01-13 19:31:08 +00002from autotest_lib.client.bin import test, utils
mbligh44394242009-06-15 21:31:32 +00003from autotest_lib.client.bin.net import net_utils
mbligh67a72f92009-01-13 19:31:08 +00004from autotest_lib.client.common_lib import error
mbligh9f857922008-06-05 16:19:07 +00005
mbligh44394242009-06-15 21:31:32 +00006MPSTAT_IX = 0
7NETPERF_IX = 1
mbligh56a91f02006-09-14 17:55:19 +00008
9class netperf2(test.test):
Kelly Lucas8acfcfa2010-03-01 10:19:31 -080010 version = 4
mbligh56a91f02006-09-14 17:55:19 +000011
mbligha5630a52008-09-03 22:09:50 +000012 # ftp://ftp.netperf.org/netperf/netperf-2.4.4.tar.gz
13 def setup(self, tarball = 'netperf-2.4.4.tar.gz'):
mbligh44394242009-06-15 21:31:32 +000014 self.job.require_gcc()
mbligh8b352852008-06-07 01:07:08 +000015 tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
mbligh53da18e2009-01-05 21:13:26 +000016 utils.extract_tarball_to_dir(tarball, self.srcdir)
jadmanski0afbb632008-06-06 21:10:57 +000017 os.chdir(self.srcdir)
mbligh56a91f02006-09-14 17:55:19 +000018
mbligh44394242009-06-15 21:31:32 +000019 utils.system('patch -p0 < ../wait_before_data.patch')
mblighc21cb462008-10-22 03:34:40 +000020 # Fixing up a compile issue under newer systems that have
21 # CPU_SET_S defined on /usr/include/sched.h, backported from
22 # upstream svn trunk
mbligh1eb6e9e2009-03-11 17:14:45 +000023 utils.system('patch -p0 < ../fix_netperf_build.patch')
jadmanski0afbb632008-06-06 21:10:57 +000024 utils.system('./configure')
25 utils.system('make')
mbligh44394242009-06-15 21:31:32 +000026 utils.system('sync')
mbligh54e56842006-09-23 06:02:54 +000027
Kelly Lucas8acfcfa2010-03-01 10:19:31 -080028 self.job.setup_dep(['sysstat'])
29
mbligh54e56842006-09-23 06:02:54 +000030
jadmanski0afbb632008-06-06 21:10:57 +000031 def initialize(self):
mbligh44394242009-06-15 21:31:32 +000032 self.server_prog = '%s&' % os.path.join(self.srcdir, 'src/netserver')
33 self.client_prog = '%s' % os.path.join(self.srcdir, 'src/netperf')
34 self.valid_tests = ['TCP_STREAM', 'TCP_MAERTS', 'TCP_RR', 'TCP_CRR',
35 'TCP_SENDFILE', 'UDP_STREAM', 'UDP_RR']
mbligha5630a52008-09-03 22:09:50 +000036 self.results = []
mbligh865ee822008-10-03 16:03:34 +000037 self.actual_times = []
mbligh44394242009-06-15 21:31:32 +000038 self.netif = ''
39 self.network = net_utils.network()
40 self.network_utils = net_utils.network_utils()
mbligh56a91f02006-09-14 17:55:19 +000041
Kelly Lucasae352272010-03-05 15:42:10 -080042 dep = 'sysstat'
43 dep_dir = os.path.join(self.autodir, 'deps', dep)
44 self.job.install_pkg(dep, 'dep', dep_dir)
45
mbligh6f5bbce2007-08-10 19:18:37 +000046
mbligh44394242009-06-15 21:31:32 +000047 def run_once(self, server_ip, client_ip, role, test = 'TCP_STREAM',
48 test_time = 15, stream_list = [1], test_specific_args = '',
49 cpu_affinity = '', dev = '', bidi = False, wait_time = 5):
50 """
51 server_ip: IP address of host running netserver
52 client_ip: IP address of host running netperf client(s)
53 role: 'client' or 'server'
54 test: one of TCP_STREAM, TCP_MEARTS, TCP_RR, TCP_CRR, TCP_SENDFILE,
55 UDP_STREAM or UDP_RR
56 test_time: time to run the test for in seconds
57 stream_list: list of number of netperf streams to launch
58 test_specific_args: Optional test specific args. For example to set
59 the request,response size for RR tests to 200,100, set it
60 to: '-- -r 200,100'. Or, to set the send buffer size of STREAM
61 tests to 200, set it to: '-- -m 200'
62 cpu_affinity: netperf/netserver processes will get taskset to the
63 cpu_affinity. cpu_affinity is specified as a bitmask in hex
64 without the leading 0x. For example, to run on CPUs 0 & 5,
65 cpu_affinity needs to be '21'
66 dev: device on which to run traffic on. For example, to run on
67 inteface eth1, set it to 'eth1'.
68 bidi: bi-directional traffic. This is supported for TCP_STREAM
69 test only. The RR & CRR tests are bi-directional by nature.
70 wait_time: Time to wait after establishing data/control connections
71 but before sending data traffic.
72 """
mbligha5630a52008-09-03 22:09:50 +000073 if test not in self.valid_tests:
74 raise error.TestError('invalid test specified')
75 self.role = role
mbligh52fa6922008-09-05 20:37:08 +000076 self.test = test
mbligh865ee822008-10-03 16:03:34 +000077 self.test_time = test_time
mbligh44394242009-06-15 21:31:32 +000078 self.wait_time = wait_time
mbligh52fa6922008-09-05 20:37:08 +000079 self.stream_list = stream_list
mbligh44394242009-06-15 21:31:32 +000080 self.bidi = bidi
mbligha5630a52008-09-03 22:09:50 +000081
jadmanski0afbb632008-06-06 21:10:57 +000082 server_tag = server_ip + '#netperf-server'
83 client_tag = client_ip + '#netperf-client'
84 all = [server_tag, client_tag]
mbligha5630a52008-09-03 22:09:50 +000085
mbligh44394242009-06-15 21:31:32 +000086 # If a specific device has been requested, configure it.
87 if dev:
88 timeout = 60
89 if role == 'server':
90 self.configure_interface(dev, server_ip)
91 self.ping(client_ip, timeout)
92 else:
93 self.configure_interface(dev, client_ip)
94 self.ping(server_ip, timeout)
95
mbligha5630a52008-09-03 22:09:50 +000096 for num_streams in stream_list:
97 if role == 'server':
mbligh44394242009-06-15 21:31:32 +000098 self.server_start(cpu_affinity)
mbligha5630a52008-09-03 22:09:50 +000099 try:
mbligh15b8a262008-09-16 16:50:49 +0000100 # Wait up to ten minutes for the client to reach this
mbligh52fa6922008-09-05 20:37:08 +0000101 # point.
mbligh15b8a262008-09-16 16:50:49 +0000102 self.job.barrier(server_tag, 'start_%d' % num_streams,
mbligh44394242009-06-15 21:31:32 +0000103 600).rendezvous(*all)
mbligh15b8a262008-09-16 16:50:49 +0000104 # Wait up to test_time + 5 minutes for the test to
mbligh52fa6922008-09-05 20:37:08 +0000105 # complete
mbligh15b8a262008-09-16 16:50:49 +0000106 self.job.barrier(server_tag, 'stop_%d' % num_streams,
mbligh44394242009-06-15 21:31:32 +0000107 test_time+300).rendezvous(*all)
mbligha5630a52008-09-03 22:09:50 +0000108 finally:
109 self.server_stop()
110
111 elif role == 'client':
mbligh15b8a262008-09-16 16:50:49 +0000112 # Wait up to ten minutes for the server to start
113 self.job.barrier(client_tag, 'start_%d' % num_streams,
mbligh44394242009-06-15 21:31:32 +0000114 600).rendezvous(*all)
115 self.client(server_ip, test, test_time, num_streams,
116 test_specific_args, cpu_affinity)
mbligh15b8a262008-09-16 16:50:49 +0000117 # Wait up to 5 minutes for the server to also reach this point
118 self.job.barrier(client_tag, 'stop_%d' % num_streams,
mbligh44394242009-06-15 21:31:32 +0000119 300).rendezvous(*all)
mbligha5630a52008-09-03 22:09:50 +0000120 else:
121 raise error.TestError('invalid role specified')
mbligh54e56842006-09-23 06:02:54 +0000122
mbligh44394242009-06-15 21:31:32 +0000123 self.restore_interface()
mbligh56a91f02006-09-14 17:55:19 +0000124
mbligh44394242009-06-15 21:31:32 +0000125
126 def configure_interface(self, dev, ip_addr):
127 self.netif = net_utils.netif(dev)
128 self.netif.up()
129 if self.netif.get_ipaddr() != ip_addr:
130 self.netif.set_ipaddr(ip_addr)
131
132
133 def restore_interface(self):
134 if self.netif:
135 self.netif.restore()
136
137
138 def server_start(self, cpu_affinity):
mbligh78be24a2008-06-13 21:40:08 +0000139 utils.system('killall netserver', ignore_status=True)
mbligh44394242009-06-15 21:31:32 +0000140 cmd = self.server_prog
141 if cpu_affinity:
142 cmd = 'taskset %s %s' % (cpu_affinity, cmd)
143
144 self.results.append(utils.system_output(cmd, retain_output=True))
mbligh56a91f02006-09-14 17:55:19 +0000145
mbligh54e56842006-09-23 06:02:54 +0000146
jadmanski0afbb632008-06-06 21:10:57 +0000147 def server_stop(self):
mbligha5630a52008-09-03 22:09:50 +0000148 utils.system('killall netserver', ignore_status=True)
mbligh56a91f02006-09-14 17:55:19 +0000149
mbligh54e56842006-09-23 06:02:54 +0000150
mbligh44394242009-06-15 21:31:32 +0000151 def client(self, server_ip, test, test_time, num_streams,
152 test_specific_args, cpu_affinity):
153 args = '-H %s -t %s -l %d' % (server_ip, test, test_time)
Kelly Lucas8acfcfa2010-03-01 10:19:31 -0800154
Kelly Lucasae352272010-03-05 15:42:10 -0800155 if os.path.exists('/usr/bin/mpstat'):
156 mpstat = '/usr/bin/mpstat'
157 else:
158 mpstat = os.path.join(self.autodir + '/deps/sysstat/src/mpstat')
Kelly Lucas8acfcfa2010-03-01 10:19:31 -0800159
mbligh44394242009-06-15 21:31:32 +0000160 if self.wait_time:
161 args += ' -s %d ' % self.wait_time
162
163 # Append the test specific arguments.
164 if test_specific_args:
165 args += ' ' + test_specific_args
166
167 cmd = '%s %s' % (self.client_prog, args)
168
169 if cpu_affinity:
170 cmd = 'taskset %s %s' % (cpu_affinity, cmd)
mbligh56a91f02006-09-14 17:55:19 +0000171
mbligha5630a52008-09-03 22:09:50 +0000172 try:
mbligh44394242009-06-15 21:31:32 +0000173 cmds = []
174
175 # Get 5 mpstat samples. Since tests with large number of streams
176 # take a long time to start up all the streams, we'll toss out the
177 # first and last sample when recording results
178 interval = max(1, test_time / 5)
Kelly Lucasae352272010-03-05 15:42:10 -0800179 cmds.append('sleep %d && %s -P ALL %s 5' % (self.wait_time, mpstat,
mbligh44394242009-06-15 21:31:32 +0000180 interval))
181
182 # Add the netperf commands
183 for i in xrange(num_streams):
184 cmds.append(cmd)
185 if self.bidi and test == 'TCP_STREAM':
186 cmds.append(cmd.replace('TCP_STREAM', 'TCP_MAERTS'))
187
mbligh865ee822008-10-03 16:03:34 +0000188 t0 = time.time()
mbligh44394242009-06-15 21:31:32 +0000189 # Launch all commands in parallel
190 out = utils.run_parallel(cmds, timeout=test_time + 500,
191 ignore_status=True)
mbligh865ee822008-10-03 16:03:34 +0000192 t1 = time.time()
193
mbligh44394242009-06-15 21:31:32 +0000194 self.results.append(out)
195 self.actual_times.append(t1 - t0 - self.wait_time)
196 # Log test output
197 logging.info(out)
mbligh865ee822008-10-03 16:03:34 +0000198
mbligha5630a52008-09-03 22:09:50 +0000199 except error.CmdError, e:
200 """ Catch errors due to timeout, but raise others
201 The actual error string is:
202 "Command did not complete within %d seconds"
203 called in function join_bg_job in the file common_lib/utils.py
mblighe8fa3af2006-09-28 23:14:56 +0000204
mbligha5630a52008-09-03 22:09:50 +0000205 Looking for 'within' is probably not the best way to do this but
206 works for now"""
207
mbligh52fa6922008-09-05 20:37:08 +0000208 if ('within' in e.additional_text
209 or 'non-zero' in e.additional_text):
lmr4c607f22009-06-02 11:50:38 +0000210 logging.debug(e.additional_text)
mbligh44394242009-06-15 21:31:32 +0000211 self.results.append(None)
mbligh865ee822008-10-03 16:03:34 +0000212 self.actual_times.append(1)
mbligha5630a52008-09-03 22:09:50 +0000213 else:
214 raise
215
216
217 def postprocess(self):
mbligh52fa6922008-09-05 20:37:08 +0000218 if self.role == 'client':
mbligh44394242009-06-15 21:31:32 +0000219 # if profilers are enabled, the test gets runs twice
220 if (len(self.stream_list) != len(self.results) and
221 2*len(self.stream_list) != len(self.results)):
mbligh52fa6922008-09-05 20:37:08 +0000222 raise error.TestError('Mismatched number of results')
223
224 function = None
225 keys = None
226
227 # Each of the functions return tuples in which the keys define
228 # what that item in the tuple represents
mbligh44394242009-06-15 21:31:32 +0000229 if self.test in ['TCP_STREAM', 'TCP_MAERTS', 'TCP_SENDFILE']:
mbligh52fa6922008-09-05 20:37:08 +0000230 function = self.process_tcp_stream
231 keys = ('Throughput',)
232 elif self.test == 'UDP_STREAM':
233 function = self.process_udp_stream
234 keys = ('Throughput', 'Errors')
235 elif self.test in ['TCP_RR', 'TCP_CRR', 'UDP_RR']:
236 function = self.process_request_response
237 keys = ('Transfer_Rate',)
238 else:
239 raise error.TestError('Unhandled test')
240
mbligh52fa6922008-09-05 20:37:08 +0000241 for i, streams in enumerate(self.stream_list):
242 attr = {'stream_count':streams}
243 keyval = {}
244 temp_vals = []
mbligh52fa6922008-09-05 20:37:08 +0000245
246 # Short circuit to handle errors due to client timeouts
mbligh44394242009-06-15 21:31:32 +0000247 if not self.results[i]:
mbligh52fa6922008-09-05 20:37:08 +0000248 self.write_iteration_keyval(attr, keyval)
249 continue
250
mbligh44394242009-06-15 21:31:32 +0000251 # Collect output of netperf sessions
252 failed_streams_count = 0
253 for result in self.results[i][NETPERF_IX:]:
254 if result.exit_status:
255 failed_streams_count += 1
256 else:
257 temp_vals.append(function(result.stdout))
258
259 keyval['Failed_streams_count'] = failed_streams_count
260
261 # Process mpstat output
262 mpstat_out = self.results[i][MPSTAT_IX].stdout
263 cpu_stats = self.network_utils.process_mpstat(mpstat_out, 5)
264 keyval['CPU_C'] = 100 - cpu_stats['idle']
265 keyval['CPU_C_SYS'] = cpu_stats['sys']
266 keyval['CPU_C_HI'] = cpu_stats['irq']
267 keyval['CPU_C_SI'] = cpu_stats['soft']
268 keyval['INTRS_C'] = cpu_stats['intr/s']
269
270 actual_time = self.actual_times[i]
271 keyval['actual_time'] = actual_time
272 logging.info('actual_time: %f', actual_time)
mbligh52fa6922008-09-05 20:37:08 +0000273
mbligh6d858fa2008-09-19 21:19:03 +0000274 # Compute the sum of elements returned from function which
mbligh52fa6922008-09-05 20:37:08 +0000275 # represent the string contained in keys
276 for j, key in enumerate(keys):
277 vals = [x[j] for x in temp_vals]
mbligh865ee822008-10-03 16:03:34 +0000278 # scale result by the actual time taken
mbligh44394242009-06-15 21:31:32 +0000279 keyval[key] = sum(vals)
mbligh865ee822008-10-03 16:03:34 +0000280
281 # record 'Efficiency' as perf/CPU
mbligh44394242009-06-15 21:31:32 +0000282 if keyval['CPU_C'] != 0:
283 keyval['Efficieny_C'] = keyval[keys[0]]/keyval['CPU_C']
284 else:
285 keyval['Efficieny_C'] = keyval[keys[0]]
mbligh52fa6922008-09-05 20:37:08 +0000286
287 self.write_iteration_keyval(attr, keyval)
288
289
290 def process_tcp_stream(self, output):
mbligh44394242009-06-15 21:31:32 +0000291 """Parses the following (works for both TCP_STREAM, TCP_MAERTS and
292 TCP_SENDFILE) and returns a singleton containing throughput.
mbligh52fa6922008-09-05 20:37:08 +0000293
mbligh44394242009-06-15 21:31:32 +0000294 TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to foo.bar.com \
295 (10.10.10.3) port 0 AF_INET
mbligh52fa6922008-09-05 20:37:08 +0000296 Recv Send Send
297 Socket Socket Message Elapsed
298 Size Size Size Time Throughput
299 bytes bytes bytes secs. 10^6bits/sec
300
301 87380 16384 16384 2.00 941.28
302 """
303
304 return float(output.splitlines()[6].split()[4]),
305
306
307 def process_udp_stream(self, output):
308 """Parses the following and returns a touple containing throughput
309 and the number of errors.
310
mbligh44394242009-06-15 21:31:32 +0000311 UDP UNIDIRECTIONAL SEND TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET \
312 to foo.bar.com (10.10.10.3) port 0 AF_INET
mbligh52fa6922008-09-05 20:37:08 +0000313 Socket Message Elapsed Messages
314 Size Size Time Okay Errors Throughput
315 bytes bytes secs # # 10^6bits/sec
316
317 129024 65507 2.00 3673 0 961.87
318 131072 2.00 3673 961.87
319 """
320
321 line_tokens = output.splitlines()[5].split()
322 return float(line_tokens[5]), int(line_tokens[4])
323
324
325 def process_request_response(self, output):
326 """Parses the following which works for both rr (TCP and UDP) and crr
327 tests and returns a singleton containing transfer rate.
328
mbligh44394242009-06-15 21:31:32 +0000329 TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET \
330 to foo.bar.com (10.10.10.3) port 0 AF_INET
mbligh52fa6922008-09-05 20:37:08 +0000331 Local /Remote
332 Socket Size Request Resp. Elapsed Trans.
333 Send Recv Size Size Time Rate
334 bytes Bytes bytes bytes secs. per sec
335
336 16384 87380 1 1 2.00 14118.53
337 16384 87380
338 """
339
340 return float(output.splitlines()[6].split()[5]),
mbligh44394242009-06-15 21:31:32 +0000341
342
343 def ping(self, ip, timeout):
344 curr_time = time.time()
345 end_time = curr_time + timeout
346 while curr_time < end_time:
347 if not os.system('ping -c 1 ' + ip):
348 # Ping succeeded
349 return
350 # Ping failed. Lets sleep a bit and try again.
351 time.sleep(5)
352 curr_time = time.time()
353
354 return