4 ## Copyright (c) 2010-2019 Intel Corporation
6 ## Licensed under the Apache License, Version 2.0 (the "License");
7 ## you may not use this file except in compliance with the License.
8 ## You may obtain a copy of the License at
10 ## http://www.apache.org/licenses/LICENSE-2.0
12 ## Unless required by applicable law or agreed to in writing, software
13 ## distributed under the License is distributed on an "AS IS" BASIS,
14 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ## See the License for the specific language governing permissions and
16 ## limitations under the License.
19 from __future__ import print_function
29 from logging.handlers import RotatingFileHandler
30 from logging import handlers
31 from prox_ctrl import prox_ctrl
38 env = "rapid.env" #Default string for environment
39 test_file = "basicrapid.test" #Default string for test
40 machine_map_file = "machine.map" #Default string for machine map file
41 loglevel="DEBUG" # sets log level for writing to file
42 screenloglevel="INFO" # sets log level for writing to screen
43 runtime=10 # time in seconds for 1 test run
44 configonly = False # IF True, the system will upload all the necessary config fiels to the VMs, but not start PROX and the actual testing
47 print("usage: runrapid [--version] [-v]")
48 print(" [--env ENVIRONMENT_NAME]")
49 print(" [--test TEST_NAME]")
50 print(" [--map MACHINE_MAP_FILE]")
51 print(" [--runtime TIME_FOR_TEST]")
52 print(" [--configonly False|True]")
53 print(" [--log DEBUG|INFO|WARNING|ERROR|CRITICAL]")
54 print(" [-h] [--help]")
56 print("Command-line interface to runrapid")
58 print("optional arguments:")
59 print(" -v, --version Show program's version number and exit")
60 print(" --env ENVIRONMENT_NAME Parameters will be read from ENVIRONMENT_NAME. Default is %s."%env)
61 print(" --test TEST_NAME Test cases will be read from TEST_NAME. Default is %s."%test_file)
62 print(" --map MACHINE_MAP_FILE Machine mapping will be read from MACHINE_MAP_FILE. Default is %s."%machine_map_file)
63 print(" --runtime Specify time in seconds for 1 test run")
64 print(" --configonly If this option is specified, only upload all config files to the VMs, do not run the tests")
65 print(" --log Specify logging level for log file output, default is DEBUG")
66 print(" --screenlog Specify logging level for screen output, default is INFO")
67 print(" -h, --help Show help message and exit.")
71 opts, args = getopt.getopt(sys.argv[1:], "vh", ["version","help", "env=", "test=", "map=", "runtime=","configonly","log=","screenlog="])
72 except getopt.GetoptError as err:
73 print("===========================================")
75 print("===========================================")
82 if opt in ["-h", "--help"]:
85 if opt in ["-v", "--version"]:
86 print("Rapid Automated Performance Indication for Dataplane "+version)
93 machine_map_file = arg
94 if opt in ["--runtime"]:
96 if opt in ["--configonly"]:
98 print('No actual runs, only uploading configuration files')
101 print ("Log level: "+ loglevel)
102 if opt in ["--screenlog"]:
104 print ("Screen Log level: "+ screenloglevel)
106 print ("Using '"+env+"' as name for the environment")
107 print ("Using '"+test_file+"' for test case definition")
108 print ("Using '"+machine_map_file+"' for machine mapping")
109 print ("Runtime: "+ runtime)
119 UNDERLINE = '\033[4m'
122 screen_formatter = logging.Formatter("%(message)s")
123 file_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
125 # get a top-level logger,
127 # BUT PREVENT IT from propagating messages to the root logger
129 log = logging.getLogger()
130 numeric_level = getattr(logging, loglevel.upper(), None)
131 if not isinstance(numeric_level, int):
132 raise ValueError('Invalid log level: %s' % loglevel)
133 log.setLevel(numeric_level)
136 # create a console handler
137 # and set its log level to the command-line option
139 console_handler = logging.StreamHandler(sys.stdout)
140 #console_handler.setLevel(logging.INFO)
141 numeric_screenlevel = getattr(logging, screenloglevel.upper(), None)
142 if not isinstance(numeric_screenlevel, int):
143 raise ValueError('Invalid screenlog level: %s' % screenloglevel)
144 console_handler.setLevel(numeric_screenlevel)
145 console_handler.setFormatter(screen_formatter)
147 # create a file handler
148 # and set its log level
150 log_file = 'RUN{}.{}.log'.format(env,test_file)
151 file_handler = logging.handlers.RotatingFileHandler(log_file, backupCount=10)
152 #file_handler = log.handlers.TimedRotatingFileHandler(log_file, 'D', 1, 5)
153 file_handler.setLevel(numeric_level)
154 file_handler.setFormatter(file_formatter)
156 # add handlers to the logger
158 log.addHandler(file_handler)
159 log.addHandler(console_handler)
161 # Check if log exists and should therefore be rolled
162 needRoll = os.path.isfile(log_file)
165 # This is a stale log, so roll it
168 log.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime())
170 # Roll over on application start
171 log.handlers[0].doRollover()
174 log.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime())
176 log.debug("runrapid.py version: "+version)
177 #========================================================================
178 def connect_socket(client):
180 log.debug("Trying to connect to PROX (just launched) on %s, attempt: %d" % (client.ip(), attempts))
183 sock = client.prox_sock()
188 log.exception("Failed to connect to PROX on %s after %d attempts" % (client.ip(), attempts))
189 raise Exception("Failed to connect to PROX on %s after %d attempts" % (client.ip(), attempts))
191 log.debug("Trying to connect to PROX (just launched) on %s, attempt: %d" % (client.ip(), attempts))
192 log.info("Connected to PROX on %s" % client.ip())
195 def connect_client(client):
197 log.debug("Trying to connect to VM which was just launched on %s, attempt: %d" % (client.ip(), attempts))
202 except RuntimeWarning, ex:
205 log.exception("Failed to connect to VM after %d attempts:\n%s" % (attempts, ex))
206 raise Exception("Failed to connect to VM after %d attempts:\n%s" % (attempts, ex))
208 log.debug("Trying to connect to VM which was just launched on %s, attempt: %d" % (client.ip(), attempts))
209 log.debug("Connected to VM on %s" % client.ip())
211 def run_iteration(gensock,sutsock):
213 # Sleep_time is needed to be able to do accurate measurements to check for packet loss. We need to make this time large enough so that we do not take the first measurement while some packets from the previous tests migth still be in flight
214 time.sleep(sleep_time)
215 abs_old_rx, abs_old_non_dp_rx, abs_old_tx, abs_old_non_dp_tx, abs_old_drop, abs_old_tx_fail, abs_old_tsc, abs_tsc_hz = gensock.core_stats(genstatcores,tasks)
216 abs_old_rx = abs_old_rx - abs_old_non_dp_rx
217 abs_old_tx = abs_old_tx - abs_old_non_dp_tx
218 gensock.start(gencores)
219 time.sleep(sleep_time)
221 old_sut_rx, old_sut_non_dp_rx, old_sut_tx, old_sut_non_dp_tx, old_sut_drop, old_sut_tx_fail, old_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores,tasks)
222 old_sut_rx = old_sut_rx - old_sut_non_dp_rx
223 old_sut_tx = old_sut_tx - old_sut_non_dp_tx
224 old_rx, old_non_dp_rx, old_tx, old_non_dp_tx, old_drop, old_tx_fail, old_tsc, tsc_hz = gensock.core_stats(genstatcores,tasks)
225 old_rx = old_rx - old_non_dp_rx
226 old_tx = old_tx - old_non_dp_tx
227 # Measure latency statistics per second
233 while n_loops < float(runtime):
236 lat_min_sample, lat_max_sample, lat_avg_sample, used_sample = gensock.lat_stats(latcores)
237 if lat_min > lat_min_sample:
238 lat_min = lat_min_sample
239 if lat_max < lat_max_sample:
240 lat_max = lat_max_sample
241 lat_avg = lat_avg + lat_avg_sample
242 used_avg = used_avg + used_sample
243 lat_avg = lat_avg / n_loops
244 used_avg = used_avg / n_loops
245 # Get statistics after some execution time
246 new_rx, new_non_dp_rx, new_tx, new_non_dp_tx, new_drop, new_tx_fail, new_tsc, tsc_hz = gensock.core_stats(genstatcores,tasks)
247 new_rx = new_rx - new_non_dp_rx
248 new_tx = new_tx - new_non_dp_tx
250 new_sut_rx, new_sut_non_dp_rx, new_sut_tx, new_sut_non_dp_tx, new_sut_drop, new_sut_tx_fail, new_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores,tasks)
251 new_sut_rx = new_sut_rx - new_sut_non_dp_rx
252 new_sut_tx = new_sut_tx - new_sut_non_dp_tx
254 gensock.stop(gencores)
255 time.sleep(sleep_time)
256 abs_new_rx, abs_new_non_dp_rx, abs_new_tx, abs_new_non_dp_tx, abs_new_drop, abs_new_tx_fail, abs_new_tsc, abs_tsc_hz = gensock.core_stats(genstatcores,tasks)
257 abs_new_rx = abs_new_rx - abs_new_non_dp_rx
258 abs_new_tx = abs_new_tx - abs_new_non_dp_tx
259 drop = new_drop-old_drop # drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM
260 rx = new_rx - old_rx # rx is all packets received by the nop task = all packets received in the gen VM
261 tx = new_tx - old_tx # tx is all generated packets actually accepted by the interface
262 abs_dropped = (abs_new_tx - abs_old_tx) - (abs_new_rx - abs_old_rx)
263 tsc = new_tsc - old_tsc # time difference between the 2 measurements, expressed in cycles.
264 pps_req_tx = (tx+drop-rx)*tsc_hz*1.0/(tsc*1000000)
265 pps_tx = tx*tsc_hz*1.0/(tsc*1000000)
266 pps_rx = rx*tsc_hz*1.0/(tsc*1000000)
268 sut_rx = new_sut_rx - old_sut_rx
269 sut_tx = new_sut_tx - old_sut_tx
270 sut_tsc = new_sut_tsc - old_sut_tsc
271 pps_sut_tx = sut_tx*sut_tsc_hz*1.0/(sut_tsc*1000000)
272 pps_sut_tx_str = '{:>9.3f}'.format(pps_sut_tx)
275 pps_sut_tx_str = 'NO MEAS.'
277 log.critical("TX = 0. Test interrupted since no packet has been sent.")
278 raise Exception("TX = 0")
279 return(pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max,abs_dropped,(abs_new_tx_fail - abs_old_tx_fail),(abs_new_tx - abs_old_tx),lat_min,used_avg)
281 def new_speed(speed,minspeed,maxspeed,success):
286 newspeed = (maxspeed+minspeed)/2.0
287 return (newspeed,minspeed,maxspeed)
289 def get_pps(speed,size):
290 # speed is given in % of 10Gb/s, returning Mpps
291 return (speed * 100.0 / (8*(size+24)))
293 def get_speed(packet_speed,size):
294 # return speed in Gb/s
295 return (packet_speed / 1000.0 * (8*(size+24)))
298 def run_flow_size_test(gensock,sutsock):
299 gensock.start(latcores)
300 for size in packet_size_list:
302 gensock.set_size(gencores,0,size) # This is setting the frame size
303 gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS)
304 gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20)
305 # This will only work when using sending UDP packets. For different protocls and ehternet types, we would need a different calculation
306 log.info("+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+")
307 log.info("| UDP, "+ '{:>5}'.format(size+4) +" bytes, different number of flows by randomizing SRC & DST UDP port |")
308 log.info("+--------+--------------------+----------------+----------------+----------------+------------------------+----------------+----------------+----------------+------------+")
309 log.info("| Flows | Speed requested | core generated | Sent by Gen NIC| Forward by SUT | core received | Avg. Latency | Max. Latency | Packets Lost | Loss Ratio |")
310 log.info("+--------+--------------------+----------------+----------------+----------------+------------------------+----------------+----------------+----------------+------------+")
311 for flow_number in flow_size_list:
313 gensock.reset_stats()
315 sutsock.reset_stats()
316 source_port,destination_port = flows[flow_number]
317 gensock.set_random(gencores,0,34,source_port,2)
318 gensock.set_random(gencores,0,36,destination_port,2)
319 endpps_sut_tx_str = 'NO_RESULTS'
320 maxspeed = speed = STARTSPEED
322 while (maxspeed-minspeed > ACCURACY):
325 print(str(flow_number)+' flows: Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r')
327 # Start generating packets at requested speed (in % of a 10Gb/s link)
328 gensock.speed(speed / len(gencores), gencores)
330 # Get statistics now that the generation is stable and initial ARP messages are dealt with
331 pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx_fail, abs_tx, lat_min, lat_used = run_iteration(gensock,sutsock)
332 drop_rate = 100.0*abs_dropped/abs_tx
334 lat_warning = bcolors.WARNING + ' Latency accuracy issue?: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC
337 # The following if statement is testing if we pass the success criteria of a certain drop rate, average latenecy and maximum latency below the threshold
338 # The drop rate success can be achieved in 2 ways: either the drop rate is below a treshold, either we want that no packet has been lost during the test
339 # This can be specified by putting 0 in the .test file
340 if ((drop_rate < DROP_RATE_TRESHOLD) or (abs_dropped==DROP_RATE_TRESHOLD ==0)) and (lat_avg< LAT_AVG_TRESHOLD) and (lat_max < LAT_MAX_TRESHOLD):
341 lat_avg_prefix = bcolors.ENDC
342 lat_max_prefix = bcolors.ENDC
343 abs_drop_rate_prefix = bcolors.ENDC
344 drop_rate_prefix = bcolors.ENDC
345 if ((get_pps(speed,size) - pps_tx)/get_pps(speed,size))>0.01:
346 speed_prefix = bcolors.WARNING
348 gen_warning = bcolors.WARNING + ' Network limit?: requesting {:<.3f} Mpps and getting {:<.3f} Mpps - {} failed to be transmitted'.format(get_pps(speed,size), pps_tx, abs_tx_fail) + bcolors.ENDC
350 gen_warning = bcolors.WARNING + ' Generator limit?: requesting {:<.3f} Mpps and getting {:<.3f} Mpps'.format(get_pps(speed,size), pps_tx) + bcolors.ENDC
352 speed_prefix = bcolors.ENDC
355 endpps_req_tx = pps_req_tx
357 endpps_sut_tx_str = pps_sut_tx_str
361 endabs_dropped = abs_dropped
362 enddrop_rate = drop_rate
363 if lat_warning or gen_warning:
364 endwarning = '| | {:167.167} |'.format(lat_warning + gen_warning)
366 success_message='% | SUCCESS'
368 success_message='% | FAILED'
370 abs_drop_rate_prefix = bcolors.ENDC
371 if ((abs_dropped>0) and (DROP_RATE_TRESHOLD ==0)):
372 abs_drop_rate_prefix = bcolors.FAIL
373 if (drop_rate < DROP_RATE_TRESHOLD):
374 drop_rate_prefix = bcolors.ENDC
376 drop_rate_prefix = bcolors.FAIL
377 if (lat_avg< LAT_AVG_TRESHOLD):
378 lat_avg_prefix = bcolors.ENDC
380 lat_avg_prefix = bcolors.FAIL
381 if (lat_max< LAT_MAX_TRESHOLD):
382 lat_max_prefix = bcolors.ENDC
384 lat_max_prefix = bcolors.FAIL
385 if (((get_pps(speed,size) - pps_tx)/get_pps(speed,size))<0.001):
386 speed_prefix = bcolors.ENDC
388 speed_prefix = bcolors.FAIL
390 log.debug('|step{:>3}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% '+speed_prefix +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | ' + '{:>9.3f}'.format(pps_tx) +' Mpps | '+ bcolors.ENDC + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+bcolors.OKBLUE + '{:>4.1f}'.format(get_speed(pps_rx,size)) + 'Gb/s{:>9.3f}'.format(pps_rx)+' Mpps'+bcolors.ENDC+' | '+lat_avg_prefix+ '{:>9.0f}'.format(lat_avg)+' us | '+lat_max_prefix+ '{:>9.0f}'.format(lat_max)+' us | '+ abs_drop_rate_prefix + '{:>14d}'.format(abs_dropped)+drop_rate_prefix+ ' |''{:>9.2f}'.format(drop_rate)+bcolors.ENDC+ success_message +lat_warning + gen_warning)
391 speed,minspeed,maxspeed = new_speed(speed,minspeed,maxspeed,success)
392 if endpps_sut_tx_str != 'NO_RESULTS':
393 log.info('|{:>7}'.format(str(flow_number))+" | " + '{:>5.1f}'.format(endspeed) + '% ' + speed_prefix + '{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+ ' Mpps | '+ bcolors.ENDC + '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+bcolors.OKBLUE + '{:>4.1f}'.format(get_speed(pps_rx,size)) + 'Gb/s{:>9.3f}'.format(endpps_rx)+' Mpps'+bcolors.ENDC+' | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+ '{:>9.0f}'.format(endlat_max)+' us | '+ '{:>14d}'.format(endabs_dropped)+ ' |'+'{:>9.2f}'.format(enddrop_rate)+ '% |')
395 log.info (endwarning)
396 log.info("+--------+--------------------+----------------+----------------+----------------+------------------------+----------------+----------------+----------------+------------+")
397 writer.writerow({'flow':flow_number,'size':(size+4),'endspeed':endspeed,'endspeedpps':get_pps(endspeed,size),'endpps_req_tx':endpps_req_tx,'endpps_tx':endpps_tx,'endpps_sut_tx_str':endpps_sut_tx_str,'endpps_rx':endpps_rx,'endlat_avg':endlat_avg,'endlat_max':endlat_max,'endabs_dropped':endabs_dropped,'enddrop_rate':enddrop_rate})
399 log.info('|{:>7}'.format(str(flow_number))+" | Speed 0 or close to 0")
400 gensock.stop(latcores)
403 def run_fixed_rate(gensock,sutsock):
404 log.info("+-----------------------------------------------------------------------------------------------------------------------------------------------------------+")
405 log.info("| UDP, 1 flow, different packet sizes |")
406 log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+")
407 log.info("|Pktsz| Speed requested | Gen by core | Sent by NIC | Fwrd by SUT | Rec. by core| Avg. Latency| Max. Latency| Sent | Received | Lost | Total Lost |")
408 log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+")
410 gensock.start(latcores)
411 for size in packet_size_list:
412 # Sleep_time is needed to be able to do accurate measurements to check for packet loss. We need to make this time large enough so that we do not take the first measurement while some packets from the previous tests migth still be in flight
413 time.sleep(sleep_time)
415 gensock.reset_stats()
417 sutsock.reset_stats()
418 gensock.set_size(gencores,0,size) # This is setting the frame size
419 gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS)
420 gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20)
421 # This will only work when using sending UDP packets. For different protocls and ehternet types, we would need a differnt calculation
422 pps_sut_tx_str = 'NO_RESULTS'
424 # Start generating packets at requested speed (in % of a 10Gb/s link)
425 gensock.speed(speed / len(gencores), gencores)
426 duration = float(runtime)
430 old_sut_rx, old_sut_non_dp_rx, old_sut_tx, old_sut_non_dp_tx, old_sut_drop, old_sut_tx_fail, old_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores,tasks)
431 old_sut_rx = old_sut_rx - old_sut_non_dp_rx
432 old_sut_tx = old_sut_tx - old_sut_non_dp_tx
433 old_rx, old_non_dp_rx, old_tx, old_non_dp_tx, old_drop, old_tx_fail, old_tsc, tsc_hz = gensock.core_stats(genstatcores,tasks)
434 old_rx = old_rx - old_non_dp_rx
435 old_tx = old_tx - old_non_dp_tx
436 gensock.start(gencores)
437 while (duration > 0):
439 lat_min, lat_max, lat_avg, lat_used = gensock.lat_stats(latcores)
441 lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC
444 # Get statistics after some execution time
445 new_rx, new_non_dp_rx, new_tx, new_non_dp_tx, new_drop, new_tx_fail, new_tsc, tsc_hz = gensock.core_stats(genstatcores,tasks)
446 new_rx = new_rx - new_non_dp_rx
447 new_tx = new_tx - new_non_dp_tx
449 new_sut_rx, new_sut_non_dp_rx, new_sut_tx, new_sut_non_dp_tx, new_sut_drop, new_sut_tx_fail, new_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores,tasks)
450 new_sut_rx = new_sut_rx - new_sut_non_dp_rx
451 new_sut_tx = new_sut_tx - new_sut_non_dp_tx
452 drop = new_drop-old_drop # drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM
453 rx = new_rx - old_rx # rx is all packets received by the nop task = all packets received in the gen VM
454 tx = new_tx - old_tx # tx is all generated packets actually accepted by the interface
455 tsc = new_tsc - old_tsc # time difference between the 2 measurements, expressed in cycles.
459 sut_rx = new_sut_rx - old_sut_rx
460 sut_tx = new_sut_tx - old_sut_tx
461 sut_tsc = new_sut_tsc - old_sut_tsc
464 duration = duration - 1
469 pps_req_tx = (tx+drop-rx)*tsc_hz*1.0/(tsc*1000000)
470 pps_tx = tx*tsc_hz*1.0/(tsc*1000000)
471 pps_rx = rx*tsc_hz*1.0/(tsc*1000000)
473 old_sut_tx = new_sut_tx
474 old_sut_rx = new_sut_rx
475 old_sut_tsc= new_sut_tsc
476 pps_sut_tx = sut_tx*sut_tsc_hz*1.0/(sut_tsc*1000000)
477 pps_sut_tx_str = '{:>7.3f}'.format(pps_sut_tx)
480 pps_sut_tx_str = 'NO MEAS.'
482 log.critical("TX = 0. Test interrupted since no packet has been sent.")
483 raise Exception("TX = 0")
484 tot_drop = tot_drop + tx - rx
486 if pps_sut_tx_str != 'NO_RESULTS':
487 # First second mpps are not valid as there is no alignement between time the generator is started and per seconds stats
489 log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+' |' +' |' +' |'+ ' |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+'{:>7.0f}'.format(tot_drop) +' |'+lat_warning)
491 log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+ '{:>7.3f}'.format(pps_req_tx)+' Mpps |'+ '{:>7.3f}'.format(pps_tx) +' Mpps |' + '{:>7}'.format(pps_sut_tx_str) +' Mpps |'+ '{:>7.3f}'.format(pps_rx)+' Mpps |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+ '{:>7.0f}'.format(tot_drop) +' |'+lat_warning)
493 log.debug('|{:>7}'.format(str(size))+" | Speed 0 or close to 0")
497 gensock.stop(gencores)
498 time.sleep(sleep_time)
499 lat_min, lat_max, lat_avg, lat_used = gensock.lat_stats(latcores)
501 lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC
504 # Get statistics after some execution time
505 new_rx, new_non_dp_rx, new_tx, new_non_dp_tx, new_drop, new_tx_fail, new_tsc, tsc_hz = gensock.core_stats(genstatcores,tasks)
506 new_rx = new_rx - new_non_dp_rx
507 new_tx = new_tx - new_non_dp_tx
509 new_sut_rx, new_sut_non_dp_rx, new_sut_tx, new_sut_non_dp_tx, new_sut_drop, new_sut_tx_fail, new_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores,tasks)
510 new_sut_rx = new_sut_rx - new_sut_non_dp_rx
511 new_sut_tx = new_sut_tx - new_sut_non_dp_tx
512 drop = new_drop-old_drop # drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM
513 rx = new_rx - old_rx # rx is all packets received by the nop task = all packets received in the gen VM
514 tx = new_tx - old_tx # tx is all generated packets actually accepted by the interface
515 tsc = new_tsc - old_tsc # time difference between the 2 measurements, expressed in cycles.
516 tot_drop = tot_drop + tx - rx
518 sut_rx = new_sut_rx - old_sut_rx
519 sut_tx = new_sut_tx - old_sut_tx
520 sut_tsc = new_sut_tsc - old_sut_tsc
521 if pps_sut_tx_str != 'NO_RESULTS':
522 log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+' |' +' |' +' |'+ ' |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+ '{:>7.0f}'.format(tot_drop) +' |'+lat_warning)
523 log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+")
524 gensock.stop(latcores)
526 def run_measure_swap(sutsock):
527 log.info("+------------------------------------------------------------------------------------------------------+")
528 log.info("| Measuring packets on SWAP system |")
529 log.info("+-----------+------------+------------+------------+------------+------------+------------+------------+")
530 log.info("| Time | RX | TX | non DP RX | non DP TX | TX - RX | nonDP TX-RX| DROP TOT |")
531 log.info("+-----------+------------+------------+------------+------------+------------+------------+------------+")
532 sutsock.reset_stats()
533 duration = float(runtime)
536 old_rx, old_non_dp_rx, old_tx, old_non_dp_tx, old_drop, old_tx_fail, old_tsc, tsc_hz = sutsock.core_stats(sutstatcores,tasks)
537 while (duration > 0):
539 # Get statistics after some execution time
540 new_rx, new_non_dp_rx, new_tx, new_non_dp_tx, new_drop, new_tx_fail, new_tsc, tsc_hz = sutsock.core_stats(sutstatcores,tasks)
541 drop = new_drop-old_drop
544 non_dp_rx = new_non_dp_rx - old_non_dp_rx
545 non_dp_tx = new_non_dp_tx - old_non_dp_tx
546 tsc = new_tsc - old_tsc
549 duration = duration - 1
553 old_non_dp_rx = new_non_dp_rx
554 old_non_dp_tx = new_non_dp_tx
556 tot_drop = tot_drop + tx - rx
558 log.info('|{:>10.0f}'.format(duration)+' | ' + '{:>10.0f}'.format(rx) + ' | ' +'{:>10.0f}'.format(tx) + ' | '+'{:>10.0f}'.format(non_dp_rx)+' | '+'{:>10.0f}'.format(non_dp_tx)+' | ' + '{:>10.0f}'.format(tx-rx) + ' | '+ '{:>10.0f}'.format(non_dp_tx-non_dp_rx) + ' | '+'{:>10.0f}'.format(tot_drop) +' |')
559 log.info("+------------------------------------------------------------------------------------------------------+")
562 def run_irqtest(sock):
563 log.info("+----------------------------------------------------------------------------------------------------------------------------")
564 log.info("| Measuring time probably spent dealing with an interrupt. Interrupting DPDK cores for more than 50us might be problematic ")
565 log.info("| and result in packet loss. The first row shows the interrupted time buckets: first number is the bucket between 0us and ")
566 log.info("| that number expressed in us and so on. The numbers in the other rows show how many times per second, the program was ")
567 log.info("| interrupted for a time as specified by its bucket. '0' is printed when there are no interrupts in this bucket throughout ")
568 log.info("| the duration of the test. This is to avoid rounding errors in the case of 0.0 ")
569 log.info("+----------------------------------------------------------------------------------------------------------------------------")
571 buckets=sock.show_irq_buckets(1)
572 print('Measurement ongoing ... ',end='\r')
574 old_irq = [[0 for x in range(len(buckets)+1)] for y in range(len(irqcores)+1)]
575 irq = [[0 for x in range(len(buckets)+1)] for y in range(len(irqcores)+1)]
576 irq[0][0] = 'bucket us'
577 for j,bucket in enumerate(buckets,start=1):
578 irq[0][j] = '<'+ bucket
579 irq[0][-1] = '>'+ buckets [-2]
582 for j,bucket in enumerate(buckets,start=1):
583 for i,irqcore in enumerate(irqcores,start=1):
584 old_irq[i][j] = sock.irq_stats(irqcore,j-1)
585 time.sleep(float(runtime))
587 for i,irqcore in enumerate(irqcores,start=1):
588 irq[i][0]='core %s '%irqcore
589 for j,bucket in enumerate(buckets,start=1):
590 diff = sock.irq_stats(irqcore,j-1) - old_irq[i][j]
594 irq[i][j] = str(round(diff/float(runtime), 2))
596 log.info(''.join(['{:>12}'.format(item) for item in row]))
598 def run_impairtest(gensock,sutsock):
600 log.info("+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+")
601 log.info("| Generator is sending UDP (1 flow) packets ("+ '{:>5}'.format(size+4) +" bytes) to SUT via GW dropping and delaying packets. SUT sends packets back. Use ctrl-c to stop the test |")
602 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+")
603 log.info("| Test | Speed requested | Sent to NIC | Sent by Gen | Forward by SUT | Rec. by Gen | Avg. Latency | Max. Latency | Packets Lost | Loss Ratio |")
604 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+")
606 gensock.set_size(gencores,0,size) # This is setting the frame size
607 gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS)
608 gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20)
609 # This will only work when using sending UDP packets. For different protocols and ethernet types, we would need a different calculation
610 gensock.start(latcores)
612 gensock.speed(speed / len(gencores), gencores)
615 print('Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r')
618 # Get statistics now that the generation is stable and NO ARP messages any more
619 pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx_fail, abs_tx, lat_min, lat_used = run_iteration(gensock,sutsock)
620 drop_rate = 100.0*abs_dropped/abs_tx
622 lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC
625 log.info('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% |'+lat_warning)
626 writer.writerow({'flow':'1','size':(size+4),'endspeed':speed,'endspeedpps':get_pps(speed,size),'endpps_req_tx':pps_req_tx,'endpps_tx':pps_tx,'endpps_sut_tx_str':pps_sut_tx_str,'endpps_rx':pps_rx,'endlat_avg':lat_avg,'endlat_max':lat_max,'endabs_dropped':abs_dropped,'enddrop_rate':drop_rate})
628 def run_warmuptest(gensock):
629 # Running at low speed to make sure the ARP messages can get through.
630 # If not doing this, the ARP message could be dropped by a switch in overload and then the test will not give proper results
631 # Note hoever that if we would run the test steps during a very long time, the ARP would expire in the switch.
632 # PROX will send a new ARP request every seconds so chances are very low that they will all fail to get through
633 gensock.speed(WARMUPSPEED / len(gencores), gencores)
635 gensock.set_size(gencores,0,size) # This is setting the frame size
636 gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS)
637 gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20)
638 gensock.set_value(gencores,0,56,1,1)
639 # This will only work when using sending UDP packets. For different protocols and ethernet types, we would need a different calculation
640 source_port,destination_port = flows[FLOWSIZE]
641 gensock.set_random(gencores,0,34,source_port,2)
642 gensock.set_random(gencores,0,36,destination_port,2)
643 gensock.start(genstatcores)
644 time.sleep(WARMUPTIME)
645 gensock.stop(genstatcores)
646 gensock.set_value(gencores,0,56,50,1)
654 global packet_size_list
656 global flow_size_list
659 global required_number_of_test_machines
660 # To generate a desired number of flows, PROX will randomize the bits in source and destination ports, as specified by the bit masks in the flows variable.
662 1: ['1000000000000000','1000000000000000'],\
663 2: ['1000000000000000','100000000000000X'],\
664 4: ['100000000000000X','100000000000000X'],\
665 8: ['100000000000000X','10000000000000XX'],\
666 16: ['10000000000000XX','10000000000000XX'],\
667 32: ['10000000000000XX','1000000000000XXX'],\
668 64: ['1000000000000XXX','1000000000000XXX'],\
669 128: ['1000000000000XXX','100000000000XXXX'],\
670 256: ['100000000000XXXX','100000000000XXXX'],\
671 512: ['100000000000XXXX','10000000000XXXXX'],\
672 1024: ['10000000000XXXXX','10000000000XXXXX'],\
673 2048: ['10000000000XXXXX','1000000000XXXXXX'],\
674 4096: ['1000000000XXXXXX','1000000000XXXXXX'],\
675 8192: ['1000000000XXXXXX','100000000XXXXXXX'],\
676 16384: ['100000000XXXXXXX','100000000XXXXXXX'],\
677 32768: ['100000000XXXXXXX','10000000XXXXXXXX'],\
678 65535: ['10000000XXXXXXXX','10000000XXXXXXXX'],\
679 131072: ['10000000XXXXXXXX','1000000XXXXXXXXX'],\
680 262144: ['1000000XXXXXXXXX','1000000XXXXXXXXX'],\
681 524280: ['1000000XXXXXXXXX','100000XXXXXXXXXX'],\
682 1048576:['100000XXXXXXXXXX','100000XXXXXXXXXX'],}
697 data_file = 'RUN{}.{}.csv'.format(env,test_file)
698 data_csv_file = open(data_file,'w')
699 testconfig = ConfigParser.RawConfigParser()
700 testconfig.read(test_file)
701 required_number_of_test_machines = testconfig.get('DEFAULT', 'total_number_of_test_machines')
702 config = ConfigParser.RawConfigParser()
704 machine_map = ConfigParser.RawConfigParser()
705 machine_map.read(machine_map_file)
706 key = config.get('ssh', 'key')
707 total_number_of_machines = config.get('rapid', 'total_number_of_machines')
708 if int(required_number_of_test_machines) > int(total_number_of_machines):
709 log.exception("Not enough VMs for this test: %s needed and only %s available" % (required_number_of_test_machines,total_number_of_machines))
710 raise Exception("Not enough VMs for this test: %s needed and only %s available" % (required_number_of_test_machines,total_number_of_machines))
711 for vm in range(1, int(total_number_of_machines)+1):
712 vmAdminIP.append(config.get('M%d'%vm, 'admin_ip'))
713 vmDPmac.append(config.get('M%d'%vm, 'dp_mac'))
714 vmDPIP.append(config.get('M%d'%vm, 'dp_ip'))
715 ip = vmDPIP[-1].split('.')
716 hexDPIP.append(hex(int(ip[0]))[2:].zfill(2) + ' ' + hex(int(ip[1]))[2:].zfill(2) + ' ' + hex(int(ip[2]))[2:].zfill(2) + ' ' + hex(int(ip[3]))[2:].zfill(2))
718 for vm in range(1, int(required_number_of_test_machines)+1):
719 machine_index.append(int(machine_map.get('TestM%d'%vm, 'machine_index'))-1)
720 prox_socket.append(testconfig.getboolean('TestM%d'%vm, 'prox_socket'))
721 for vm in range(1, int(required_number_of_test_machines)+1):
722 if prox_socket[vm-1]:
723 prox_launch_exit.append(testconfig.getboolean('TestM%d'%vm, 'prox_launch_exit'))
724 config_file.append(testconfig.get('TestM%d'%vm, 'config_file'))
725 with open('{}_{}_parameters{}.lua'.format(env,test_file,vm), "w") as f:
726 f.write('name="%s"\n'% testconfig.get('TestM%d'%vm, 'name'))
727 f.write('local_ip="%s"\n'% vmDPIP[machine_index[vm-1]])
728 f.write('local_hex_ip="%s"\n'% hexDPIP[machine_index[vm-1]])
729 if re.match('(l2){0,1}gen(_bare){0,1}\.cfg',config_file[-1]):
730 gencores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'gencores'))
731 latcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'latcores'))
732 genstatcores = gencores + latcores
733 auto_start.append(False)
734 mach_type.append('gen')
735 f.write('gencores="%s"\n'% ','.join(map(str, gencores)))
736 f.write('latcores="%s"\n'% ','.join(map(str, latcores)))
737 destVMindex = int(testconfig.get('TestM%d'%vm, 'dest_vm'))-1
738 f.write('dest_ip="%s"\n'% vmDPIP[machine_index[destVMindex]])
739 f.write('dest_hex_ip="%s"\n'% hexDPIP[machine_index[destVMindex]])
740 f.write('dest_hex_mac="%s"\n'% vmDPmac[machine_index[destVMindex]].replace(':',' '))
741 elif re.match('(l2){0,1}gen_gw\.cfg',config_file[-1]):
742 gencores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'gencores'))
743 latcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'latcores'))
744 genstatcores = gencores + latcores
745 auto_start.append(False)
746 mach_type.append('gen')
747 f.write('gencores="%s"\n'% ','.join(map(str, gencores)))
748 f.write('latcores="%s"\n'% ','.join(map(str, latcores)))
749 gwVMindex = int(testconfig.get('TestM%d'%vm, 'gw_vm')) -1
750 f.write('gw_ip="%s"\n'% vmDPIP[machine_index[gwVMindex]])
751 f.write('gw_hex_ip="%s"\n'% hexDPIP[machine_index[gwVMindex]])
752 destVMindex = int(testconfig.get('TestM%d'%vm, 'dest_vm'))-1
753 f.write('dest_ip="%s"\n'% vmDPIP[machine_index[destVMindex]])
754 f.write('dest_hex_ip="%s"\n'% hexDPIP[machine_index[destVMindex]])
755 f.write('dest_hex_mac="%s"\n'% vmDPmac[machine_index[destVMindex]].replace(':',' '))
756 elif re.match('(l2){0,1}swap.*\.cfg',config_file[-1]):
757 sutstatcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'swapcores'))
758 auto_start.append(True)
759 mach_type.append('sut')
760 f.write('swapcores="%s"\n'% ','.join(map(str, sutstatcores)))
761 elif config_file[-1] == 'secgw1.cfg':
762 auto_start.append(True)
763 mach_type.append('none')
764 f.write('secgwcores="%s"\n'% ','.join(map(str, ast.literal_eval(testconfig.get('TestM%d'%vm, 'secgwcores')))))
765 destVMindex = int(testconfig.get('TestM%d'%vm, 'dest_vm'))-1
766 f.write('dest_ip="%s"\n'% vmDPIP[machine_index[destVMindex]])
767 f.write('dest_hex_ip="%s"\n'% hexDPIP[machine_index[destVMindex]])
768 f.write('dest_hex_mac="%s"\n'% vmDPmac[machine_index[destVMindex]].replace(':',' '))
769 elif config_file[-1] == 'secgw2.cfg':
770 sutstatcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'secgwcores'))
771 auto_start.append(True)
772 mach_type.append('sut')
773 f.write('secgwcores="%s"\n'% ','.join(map(str, sutstatcores)))
774 elif config_file[-1] == 'impair.cfg':
775 auto_start.append(True)
776 mach_type.append('none')
777 f.write('impaircores="%s"\n'% ','.join(map(str, ast.literal_eval(testconfig.get('TestM%d'%vm, 'impaircores')))))
778 elif config_file[-1] == 'irq.cfg':
779 irqcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'irqcores'))
780 auto_start.append(False)
781 mach_type.append('irq')
782 f.write('irqcores="%s"\n'% ','.join(map(str, irqcores)))
784 #####################################################################################
786 log.debug ('exit cleanup')
787 for index, sock in enumerate(socks):
788 if socks_control[index]:
790 for client in clients:
795 atexit.register(exit_handler)
797 for vm in range(0, int(required_number_of_test_machines)):
799 clients.append(prox_ctrl(vmAdminIP[machine_index[vm]], key+'.pem','root'))
800 connect_client(clients[-1])
801 # Creating script to bind the right network interface to the poll mode driver
802 devbindfile = '{}_{}_devbindvm{}.sh'.format(env,test_file, vm+1)
803 with open("devbind.sh") as f:
804 newText=f.read().replace('MACADDRESS', vmDPmac[machine_index[vm]])
805 with open(devbindfile, "w") as f:
807 st = os.stat(devbindfile)
808 os.chmod(devbindfile, st.st_mode | stat.S_IEXEC)
809 clients[-1].scp_put('./%s'%devbindfile, '/root/devbind.sh')
810 cmd = '/root/devbind.sh'
811 clients[-1].run_cmd(cmd)
812 log.debug("devbind.sh running on VM%d"%(vm+1))
813 clients[-1].scp_put('./%s'%config_file[vm], '/root/%s'%config_file[vm])
814 clients[-1].scp_put('./{}_{}_parameters{}.lua'.format(env,test_file, vm+1), '/root/parameters.lua')
816 if prox_launch_exit[vm]:
817 log.debug("Starting PROX on VM%d"%(vm+1))
819 cmd = '/root/prox/build/prox -t -o cli -f /root/%s'%config_file[vm]
821 cmd = '/root/prox/build/prox -e -t -o cli -f /root/%s'%config_file[vm]
822 clients[-1].fork_cmd(cmd, 'PROX Testing on TestM%d'%(vm+1))
823 socks_control.append(prox_launch_exit[vm])
824 socks.append(connect_socket(clients[-1]))
825 sock_type.append(mach_type[vm])
827 socks_control.append(False)
829 def get_BinarySearchParams() :
830 global DROP_RATE_TRESHOLD
831 global LAT_AVG_TRESHOLD
832 global LAT_MAX_TRESHOLD
835 DROP_RATE_TRESHOLD = float(testconfig.get('BinarySearchParams', 'drop_rate_threshold'))
836 LAT_AVG_TRESHOLD = float(testconfig.get('BinarySearchParams', 'lat_avg_threshold'))
837 LAT_MAX_TRESHOLD = float(testconfig.get('BinarySearchParams', 'lat_max_threshold'))
838 ACCURACY = float(testconfig.get('BinarySearchParams', 'accuracy'))
839 STARTSPEED = float(testconfig.get('BinarySearchParams', 'startspeed'))
843 ####################################################
845 # Best to run the flow test at the end since otherwise the tests coming after might be influenced by the big number of entries in the switch flow tables
846 ####################################################
847 gensock_index = sock_type.index('gen') if 'gen' in sock_type else -1
848 sutsock_index = sock_type.index('sut') if 'sut' in sock_type else -1
849 irqsock_index = sock_type.index('irq') if 'irq' in sock_type else -1
850 number_of_tests = testconfig.get('DEFAULT', 'number_of_tests')
852 fieldnames = ['flow','size','endspeed','endspeedpps','endpps_req_tx','endpps_tx','endpps_sut_tx_str','endpps_rx','endlat_avg','endlat_max','endabs_dropped','enddrop_rate']
853 writer = csv.DictWriter(data_csv_file, fieldnames=fieldnames)
855 for test_nr in range(1, int(number_of_tests)+1):
856 test=testconfig.get('test%d'%test_nr,'test')
857 tasks= ast.literal_eval(testconfig.get('test%d'%test_nr, 'tasks'))
859 if test == 'flowsizetest':
860 get_BinarySearchParams()
861 packet_size_list = ast.literal_eval(testconfig.get('test%d'%test_nr, 'packetsizes'))
862 flow_size_list = ast.literal_eval(testconfig.get('test%d'%test_nr, 'flows'))
863 run_flow_size_test(socks[gensock_index],socks[sutsock_index])
864 elif test == 'fixed_rate':
865 packet_size_list = ast.literal_eval(testconfig.get('test%d'%test_nr, 'packetsizes'))
866 STARTSPEED = float(testconfig.get('test%d'%test_nr, 'speed'))
867 run_fixed_rate(socks[gensock_index],socks[sutsock_index])
868 elif test == 'measureswap':
869 #packet_size_list = ast.literal_eval(testconfig.get('test%d'%test_nr, 'packetsizes'))
870 run_measure_swap(socks[sutsock_index])
871 elif test == 'impairtest':
872 get_BinarySearchParams()
873 PACKETSIZE = int(testconfig.get('test%d'%test_nr, 'packetsize'))
874 run_impairtest(socks[gensock_index],socks[sutsock_index])
875 elif test == 'irqtest':
876 run_irqtest(socks[irqsock_index])
877 elif test == 'warmuptest':
878 PACKETSIZE = int(testconfig.get('test%d'%test_nr, 'packetsize'))
879 FLOWSIZE = int(testconfig.get('test%d'%test_nr, 'flowsize'))
880 WARMUPSPEED = int(testconfig.get('test%d'%test_nr, 'warmupspeed'))
881 WARMUPTIME = int(testconfig.get('test%d'%test_nr, 'warmuptime'))
882 run_warmuptest(socks[gensock_index])
883 ####################################################