• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3# Copyright (c) 2015 Google, Inc.
4# Copyright (c) 2015 Linaro, Ltd.
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9# 1. Redistributions of source code must retain the above copyright notice,
10# this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright notice,
12# this list of conditions and the following disclaimer in the documentation
13# and/or other materials provided with the distribution.
14# 3. Neither the name of the copyright holder nor the names of its
15# contributors may be used to endorse or promote products derived from this
16# software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30from __future__ import print_function
31import csv
32import datetime
33import sys
34import time
35
36dict = {'ping': '2', 'transfer': '3', 'sink': '4'}
37verbose = 1
38
39def abort():
40	sys.exit(1)
41
42def usage():
43	print('Usage: looptest TEST SIZE ITERATIONS PATH\n\n'
44	'  Run TEST for a number of ITERATIONS with operation data SIZE bytes\n'
45	'  TEST may be \'ping\' \'transfer\' or \'sink\'\n'
46	'  SIZE indicates the size of transfer <= greybus max payload bytes\n'
47	'  ITERATIONS indicates the number of times to execute TEST at SIZE bytes\n'
48	'             Note if ITERATIONS is set to zero then this utility will\n'
49	'             initiate an infinite (non terminating) test and exit\n'
50	'             without logging any metrics data\n'
51	'  PATH indicates the sysfs path for the loopback greybus entries e.g.\n'
52	'             /sys/bus/greybus/devices/endo0:1:1:1:1/\n'
53	'Examples:\n'
54	'  looptest transfer 128 10000\n'
55	'  looptest ping 0 128\n'
56	'  looptest sink 2030 32768\n'
57	.format(sys.argv[0]), file=sys.stderr)
58
59	abort()
60
61def read_sysfs_int(path):
62	try:
63		f = open(path, "r");
64		val = f.read();
65		f.close()
66		return int(val)
67	except IOError as e:
68		print("I/O error({0}): {1}".format(e.errno, e.strerror))
69		print("Invalid path %s" % path)
70
71def write_sysfs_val(path, val):
72	try:
73		f = open(path, "r+")
74		f.write(val)
75		f.close()
76	except IOError as e:
77		print("I/O error({0}): {1}".format(e.errno, e.strerror))
78		print("Invalid path %s" % path)
79
80def log_csv(test_name, size, iteration_max, sys_pfx):
81	# file name will test_name_size_iteration_max.csv
82	# every time the same test with the same parameters is run we will then
83	# append to the same CSV with datestamp - representing each test dataset
84	fname = test_name + '_' + size + '_' + str(iteration_max) + '.csv'
85
86	try:
87		# gather data set
88		date = str(datetime.datetime.now())
89		error = read_sysfs_int(sys_pfx + 'error')
90		request_min = read_sysfs_int(sys_pfx + 'requests_per_second_min')
91		request_max = read_sysfs_int(sys_pfx + 'requests_per_second_max')
92		request_avg = read_sysfs_int(sys_pfx + 'requests_per_second_avg')
93		latency_min = read_sysfs_int(sys_pfx + 'latency_min')
94		latency_max = read_sysfs_int(sys_pfx + 'latency_max')
95		latency_avg = read_sysfs_int(sys_pfx + 'latency_avg')
96		throughput_min = read_sysfs_int(sys_pfx + 'throughput_min')
97		throughput_max = read_sysfs_int(sys_pfx + 'throughput_max')
98		throughput_avg = read_sysfs_int(sys_pfx + 'throughput_avg')
99
100		# derive jitter
101		request_jitter = request_max - request_min
102		latency_jitter = latency_max - latency_min
103		throughput_jitter = throughput_max - throughput_min
104
105		# append data set to file
106		with open(fname, 'a') as csvf:
107			row = csv.writer(csvf, delimiter=",", quotechar="'",
108					quoting=csv.QUOTE_MINIMAL)
109			row.writerow([date, test_name, size, iteration_max, error,
110					request_min, request_max, request_avg, request_jitter,
111					latency_min, latency_max, latency_avg, latency_jitter,
112					throughput_min, throughput_max, throughput_avg, throughput_jitter])
113	except IOError as e:
114		print("I/O error({0}): {1}".format(e.errno, e.strerror))
115
116def loopback_run(test_name, size, iteration_max, sys_pfx):
117	test_id = dict[test_name]
118	try:
119		# Terminate any currently running test
120		write_sysfs_val(sys_pfx + 'type', '0')
121		# Set parameter for no wait between messages
122		write_sysfs_val(sys_pfx + 'ms_wait', '0')
123		# Set operation size
124		write_sysfs_val(sys_pfx + 'size', size)
125		# Set iterations
126		write_sysfs_val(sys_pfx + 'iteration_max', str(iteration_max))
127		# Initiate by setting loopback operation type
128		write_sysfs_val(sys_pfx + 'type', test_id)
129		time.sleep(1)
130
131		if iteration_max == 0:
132			print ("Infinite test initiated CSV won't be logged\n")
133			return
134
135		previous = 0
136		err = 0
137		while True:
138			# get current count bail out if it hasn't changed
139			iteration_count = read_sysfs_int(sys_pfx + 'iteration_count')
140			if previous == iteration_count:
141				err = 1
142				break
143			elif iteration_count == iteration_max:
144				break
145			previous = iteration_count
146			if verbose:
147				print('%02d%% complete %d of %d ' %
148					(100 * iteration_count / iteration_max,
149					iteration_count, iteration_max))
150			time.sleep(1)
151		if err:
152			print ('\nError executing test\n')
153		else:
154			log_csv(test_name, size, iteration_max, sys_pfx)
155	except ValueError as ve:
156		print("Error: %s " % format(e.strerror), file=sys.stderr)
157		abort()
158
159def main():
160	if len(sys.argv) < 5:
161		usage()
162
163	if sys.argv[1] in dict.keys():
164		loopback_run(sys.argv[1], sys.argv[2], int(sys.argv[3]), sys.argv[4])
165	else:
166		usage()
167if __name__ == '__main__':
168	main()
169