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