4 ## Copyright (c) 2010-2017 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
36 env = "rapid" #Default string for environment
37 test = "basicrapid" #Default string for test
38 loglevel="DEBUG" # sets log level for writing to file
39 runtime=10 # time in seconds for 1 test run
42 print("usage: runrapid [--version] [-v]")
43 print(" [--env ENVIRONMENT_NAME]")
44 print(" [--test TEST_NAME]")
45 print(" [--runtime TIME_FOR_TEST]")
46 print(" [--log DEBUG|INFO|WARNING|ERROR|CRITICAL]")
47 print(" [-h] [--help]")
49 print("Command-line interface to runrapid")
51 print("optional arguments:")
52 print(" -v, --version Show program's version number and exit")
53 print(" --env ENVIRONMENT_NAME Parameters will be read from ENVIRONMENT_NAME.env Default is %s."%env)
54 print(" --test TEST_NAME Test cases will be read from TEST_NAME.test Default is %s."%test)
55 print(" --runtime Specify time in seconds for 1 test run")
56 print(" --log Specify logging level for log file output, screen output level is hard coded")
57 print(" -h, --help Show help message and exit.")
61 opts, args = getopt.getopt(sys.argv[1:], "vh", ["version","help", "env=", "test=","runtime=","log="])
62 except getopt.GetoptError as err:
63 print("===========================================")
65 print("===========================================")
72 if opt in ("-h", "--help"):
75 if opt in ("-v", "--version"):
76 print("Rapid Automated Performance Indication for Dataplane "+version)
80 print ("Using '"+env+"' as name for the environment")
83 print ("Using '"+test+".test' for test case definition")
84 if opt in ("--runtime"):
86 print ("Runtime: "+ runtime)
89 print ("Log level: "+ loglevel)
93 screen_formatter = logging.Formatter("%(message)s")
94 file_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
96 # get a top-level logger,
98 # BUT PREVENT IT from propagating messages to the root logger
100 log = logging.getLogger()
101 numeric_level = getattr(logging, loglevel.upper(), None)
102 if not isinstance(numeric_level, int):
103 raise ValueError('Invalid log level: %s' % loglevel)
104 log.setLevel(numeric_level)
107 # create a console handler
108 # and set its log level to the command-line option
110 console_handler = logging.StreamHandler(sys.stdout)
111 console_handler.setLevel(logging.INFO)
112 console_handler.setFormatter(screen_formatter)
114 # create a file handler
115 # and set its log level to DEBUG
117 log_file = 'RUN' +env+'.'+test+'.log'
118 file_handler = logging.handlers.RotatingFileHandler(log_file, backupCount=10)
119 #file_handler = log.handlers.TimedRotatingFileHandler(log_file, 'D', 1, 5)
120 file_handler.setLevel(numeric_level)
121 file_handler.setFormatter(file_formatter)
123 # add handlers to the logger
125 log.addHandler(file_handler)
126 log.addHandler(console_handler)
128 # Check if log exists and should therefore be rolled
129 needRoll = os.path.isfile(log_file)
132 # This is a stale log, so roll it
135 log.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime())
137 # Roll over on application start
138 log.handlers[0].doRollover()
141 log.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime())
143 log.debug("runrapid.py version: "+version)
144 #========================================================================
145 def connect_socket(client):
147 log.debug("Trying to connect to PROX (just launched) on %s, attempt: %d" % (client.ip(), attempts))
150 sock = client.prox_sock()
155 log.exception("Failed to connect to PROX on %s after %d attempts" % (client.ip(), attempts))
156 raise Exception("Failed to connect to PROX on %s after %d attempts" % (client.ip(), attempts))
158 log.debug("Trying to connect to PROX (just launched) on %s, attempt: %d" % (client.ip(), attempts))
159 log.info("Connected to PROX on %s" % client.ip())
162 def connect_client(client):
164 log.debug("Trying to connect to VM which was just launched on %s, attempt: %d" % (client.ip(), attempts))
169 except RuntimeWarning, ex:
172 log.exception("Failed to connect to VM after %d attempts:\n%s" % (attempts, ex))
173 raise Exception("Failed to connect to VM after %d attempts:\n%s" % (attempts, ex))
175 log.debug("Trying to connect to VM which was just launched on %s, attempt: %d" % (client.ip(), attempts))
176 log.debug("Connected to VM on %s" % client.ip())
178 def run_iteration(gensock,sutsock):
180 # 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
181 abs_old_rx, abs_old_tx, abs_old_drop, abs_old_tsc, abs_tsc_hz = gensock.core_stats(genstatcores)
182 gensock.start(gencores)
183 time.sleep(sleep_time)
185 old_sut_rx, old_sut_tx, old_sut_drop, old_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores)
186 old_rx, old_tx, old_drop, old_tsc, tsc_hz = gensock.core_stats(genstatcores)
187 time.sleep(float(runtime))
188 lat_min, lat_max, lat_avg = gensock.lat_stats(latcores)
189 # Get statistics after some execution time
190 new_rx, new_tx, new_drop, new_tsc, tsc_hz = gensock.core_stats(genstatcores)
192 new_sut_rx, new_sut_tx, new_sut_drop, new_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores)
194 gensock.stop(gencores)
195 time.sleep(sleep_time)
196 abs_new_rx, abs_new_tx, abs_new_drop, abs_new_tsc, abs_tsc_hz = gensock.core_stats(genstatcores)
197 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
198 rx = new_rx - old_rx # rx is all packets received by the nop task = all packets received in the gen VM
199 tx = new_tx - old_tx # tx is all generated packets actually accepted by the interface
200 abs_dropped = (abs_new_tx - abs_old_tx) - (abs_new_rx - abs_old_rx)
201 tsc = new_tsc - old_tsc # time difference between the 2 measurements, expressed in cycles.
202 pps_req_tx = (tx+drop-rx)*tsc_hz*1.0/(tsc*1000000)
203 pps_tx = tx*tsc_hz*1.0/(tsc*1000000)
204 pps_rx = rx*tsc_hz*1.0/(tsc*1000000)
206 sut_rx = new_sut_rx - old_sut_rx
207 sut_tx = new_sut_tx - old_sut_tx
208 sut_tsc = new_sut_tsc - old_sut_tsc
209 pps_sut_tx = sut_tx*sut_tsc_hz*1.0/(sut_tsc*1000000)
210 pps_sut_tx_str = '{:>9.3f}'.format(pps_sut_tx)
213 pps_sut_tx_str = 'NO MEAS.'
215 log.critical("TX = 0. Test interrupted since no packet has been sent.")
216 raise Exception("TX = 0")
217 return(pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,abs_dropped)
219 def new_speed(speed,minspeed,maxspeed,success):
220 # Following calculates the ratio for the new speed to be applied
221 # On the Y axis, we will find the ratio, a number between 0 and 1
222 # On the x axis, we find the % of dropped packets, a number between 0 and 100
223 # 2 lines are drawn and we take the minumun of these lines to calculate the ratio
224 # One line goes through (0,y0) and (p,q)
225 # The second line goes through (p,q) and (100,y100)
230 # ratio = min((q-y0)/p*drop_rate+y0,(q-y100)/(p-100)*drop_rate+q-p*(q-y100)/(p-100))
231 # return (int(speed*ratio*100)+0.5)/100.0
236 newspeed = (maxspeed+minspeed)/2.0
237 return (newspeed,minspeed,maxspeed)
239 def get_pps(speed,size):
240 return (speed * 100.0 / (8*(size+24)))
242 def get_drop_rate(speed,pps_rx,size):
243 # pps_rx are all the packets that are received by the generator. That is substracted
244 # from the pps that we wanted to send. This is calculated by taking the variable speed
245 # which is the requested percentage of a 10Gb/s link. So we take 10000bps (10Gbps, note
246 # that the speed variable is already expressed in % so we only take 100 and not 10000)
247 # divided by the number of bits in 1 packet. That is 8 bits in a byte times the size of
248 # a frame (=our size + 24 bytes overhead).
249 tried_to_send = get_pps(speed,size)
250 return abs(100.0*(tried_to_send - pps_rx)/tried_to_send)
252 def run_speedtest(gensock,sutsock):
253 log.info("+-------------------------------------------------------------------------------------------------------------------------------------------------------------+")
254 log.info("| Generator is sending UDP (1 flow) packets (64 bytes) to SUT. SUT sends packets back |")
255 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+-------------------------+")
256 log.info("| Test | Speed requested | Sent to NIC | Sent by Gen | Forward by SUT | Rec. by Gen | Avg. Latency | Packets Lost | Loss Ratio | Result |")
257 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+------------+")
263 endpps_sut_tx_str = 'NO_RESULTS'
264 gensock.set_size(gencores,0,size) # This is setting the frame size
265 gensock.set_value(gencores,0,16,(size-18),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS)
266 gensock.set_value(gencores,0,38,(size-38),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20)
267 # This will only work when using sending UDP packets. For different protocls and ehternet types, we would need a differnt calculation
268 while (maxspeed-minspeed > ACCURACY):
270 print('Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r')
272 # Start generating packets at requested speed (in % of a 10Gb/s link)
273 gensock.speed(speed, gencores)
275 # Get statistics now that the generation is stable and NO ARP messages any more
276 pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,abs_dropped = run_iteration(gensock,sutsock)
277 drop_rate = get_drop_rate(speed,pps_rx,size)
278 if (drop_rate < DROP_RATE_TRESHOLD) or (abs_dropped==DROP_RATE_TRESHOLD ==0):
279 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 | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% | SUCCESS |')
281 endpps_req_tx = pps_req_tx
283 endpps_sut_tx_str = pps_sut_tx_str
286 endabs_dropped = abs_dropped
287 enddrop_rate = drop_rate
290 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 | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% | FAILED |')
292 speed,minspeed,maxspeed = new_speed(speed,minspeed,maxspeed,success)
293 if endpps_sut_tx_str <> 'NO_RESULTS':
294 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+------------+")
295 log.info('|{:>7}'.format('END')+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+ '{:>14d}'.format(endabs_dropped)+ ' |''{:>9.2f}'.format(enddrop_rate)+ '% | SUCCESS |')
296 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+------------+")
298 log.info('| Speed 0 or close to 0')
300 def run_flowtest(gensock,sutsock):
301 log.info("+------------------------------------------------------------------------------------------------------------------------------------------------+")
302 log.info("| UDP, 64 bytes, different number of flows by randomizing SRC & DST UDP port |")
303 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+")
304 log.info("| Flows | Speed requested | Sent to NIC | Sent by Gen | Forward by SUT | Rec. by Gen | Avg. Latency | Packets Lost | Loss Ratio |")
305 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+")
308 # 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.
309 flows={128:['1000000000000XXX','100000000000XXXX'],1024:['10000000000XXXXX','10000000000XXXXX'],8192:['1000000000XXXXXX','100000000XXXXXXX'],65535:['10000000XXXXXXXX','10000000XXXXXXXX'],524280:['1000000XXXXXXXXX','100000XXXXXXXXXX']}
310 # flows={524280:['1000000XXXXXXXXX','100000XXXXXXXXXX']}
311 gensock.set_size(gencores,0,size) # This is setting the frame size
312 gensock.set_value(gencores,0,16,(size-18),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS)
313 gensock.set_value(gencores,0,38,(size-38),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20)
314 # This will only work when using sending UDP packets. For different protocls and ehternet types, we would need a differnt calculation
315 for flow_number in sorted(flows.iterkeys()):
316 #speed = 100 Commented out: Not starting from 100% since we are trying more flows, so speed will not be higher than the speed achieved in previous loop
317 gensock.reset_stats()
319 sutsock.reset_stats()
320 source_port,destination_port = flows[flow_number]
321 gensock.set_random(gencores,0,34,source_port,2)
322 gensock.set_random(gencores,0,36,destination_port,2)
323 endpps_sut_tx_str = 'NO_RESULTS'
326 while (maxspeed-minspeed > ACCURACY):
327 print(str(flow_number)+' flows: Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r')
329 # Start generating packets at requested speed (in % of a 10Gb/s link)
330 gensock.speed(speed, gencores)
332 # Get statistics now that the generation is stable and NO ARP messages any more
333 pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,abs_dropped = run_iteration(gensock,sutsock)
334 drop_rate = get_drop_rate(speed,pps_rx,size)
335 if (drop_rate < DROP_RATE_TRESHOLD) or (abs_dropped==DROP_RATE_TRESHOLD ==0):
337 endpps_req_tx = pps_req_tx
339 endpps_sut_tx_str = pps_sut_tx_str
342 endabs_dropped = abs_dropped
343 enddrop_rate = drop_rate
347 speed,minspeed,maxspeed = new_speed(speed,minspeed,maxspeed,success)
348 if endpps_sut_tx_str <> 'NO_RESULTS':
349 log.info('|{:>7}'.format(str(flow_number))+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+ '{:>14d}'.format(endabs_dropped)+ ' |'+'{:>9.2f}'.format(enddrop_rate)+ '% |')
350 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+")
352 log.info('|{:>7}'.format(str(flow_number))+" | Speed 0 or close to 0")
354 def run_sizetest(gensock,sutsock):
355 log.info("+------------------------------------------------------------------------------------------------------------------------------------------------+")
356 log.info("| UDP, 1 flow, different packet sizes |")
357 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+")
358 log.info("| Pktsize| Speed requested | Sent to NIC | Sent by Gen | Forward by SUT | Rec. by Gen | Avg. Latency | Packets Lost | Loss Ratio |")
359 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+")
361 # PROX will use different packet sizes as defined in sizes[]
362 # sizes=[1496,1020,508,252,124,60]
363 sizes=[1020,508,252,124,60]
365 #speed = 100 Commented out: Not starting from 100% since we are trying smaller packets, so speed will not be higher than the speed achieved in previous loop
366 gensock.reset_stats()
368 sutsock.reset_stats()
369 gensock.set_size(gencores,0,size) # This is setting the frame size
370 gensock.set_value(gencores,0,16,(size-18),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS)
371 gensock.set_value(gencores,0,38,(size-38),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20)
372 # This will only work when using sending UDP packets. For different protocls and ehternet types, we would need a differnt calculation
373 endpps_sut_tx_str = 'NO_RESULTS'
376 while (maxspeed-minspeed > ACCURACY):
377 print(str(size+4)+' bytes: Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r')
379 # Start generating packets at requested speed (in % of a 10Gb/s link)
380 gensock.speed(speed, gencores)
381 # Get statistics now that the generation is stable and NO ARP messages any more
382 pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg, abs_dropped = run_iteration(gensock,sutsock)
383 drop_rate = get_drop_rate(speed,pps_rx,size)
384 if (drop_rate < DROP_RATE_TRESHOLD) or (abs_dropped==DROP_RATE_TRESHOLD ==0):
386 endpps_req_tx = pps_req_tx
388 endpps_sut_tx_str = pps_sut_tx_str
391 endabs_dropped = abs_dropped
392 enddrop_rate = drop_rate
396 speed,minspeed,maxspeed = new_speed(speed,minspeed,maxspeed,success)
397 if endpps_sut_tx_str <> 'NO_RESULTS':
398 log.info('|{:>7}'.format(size+4)+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+ '{:>14d}'.format(endabs_dropped)+ ' |'+'{:>9.2f}'.format(enddrop_rate)+ '% |')
399 log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+")
401 log.debug('|{:>7}'.format(str(size))+" | Speed 0 or close to 0")
404 def run_irqtest(sock):
405 log.info("+----------------------------------------------------------------------------------------------------------------------------")
406 log.info("| Measuring time probably spent dealing with an interrupt. Interrupting DPDK cores for more than 50us might be problematic ")
407 log.info("| and result in packet loss. The first row shows the interrupted time buckets: first number is the bucket between 0us and ")
408 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 ")
409 log.info("| interrupted for a time as specified by its bucket. '0' is printed when there are no interrupts in this bucket throughout ")
410 log.info("| the duration of the test. This is to avoid rounding errors in the case of 0.0 ")
411 log.info("+----------------------------------------------------------------------------------------------------------------------------")
413 buckets=sock.show_irq_buckets(1)
414 print('Measurement ongoing ... ',end='\r')
416 old_irq = [[0 for x in range(len(buckets)+1)] for y in range(len(irqcores)+1)]
417 irq = [[0 for x in range(len(buckets)+1)] for y in range(len(irqcores)+1)]
418 irq[0][0] = 'bucket us'
419 for j,bucket in enumerate(buckets,start=1):
420 irq[0][j] = '<'+ bucket
421 irq[0][-1] = '>'+ buckets [-2]
422 for j,bucket in enumerate(buckets,start=1):
423 for i,irqcore in enumerate(irqcores,start=1):
424 old_irq[i][j] = sock.irq_stats(irqcore,j-1)
426 time.sleep(float(runtime))
428 for i,irqcore in enumerate(irqcores,start=1):
429 irq[i][0]='core %s '%irqcore
430 for j,bucket in enumerate(buckets,start=1):
431 diff = sock.irq_stats(irqcore,j-1) - old_irq[i][j]
435 irq[i][j] = diff/float(runtime)
436 log.info('\n'.join([''.join(['{:>12}'.format(item) for item in row]) for row in irq]))
440 # Running at low speed to make sure the ARP messages can get through.
441 # If not doing this, the ARP message could be dropped by a switch in overload and then the test will not give proper results
442 # Note hoever that if we would run the test steps during a very long time, the ARP would expire in the switch.
443 # PROX will send a new ARP request every seconds so chances are very low that they will all fail to get through
444 sock[0].speed(0.01, gencores)
445 sock[0].start(genstatcores)
447 sock[0].stop(gencores)
454 global DROP_RATE_TRESHOLD
463 testconfig = ConfigParser.RawConfigParser()
464 testconfig.read(test+'.test')
465 required_number_of_VMs = testconfig.get('DEFAULT', 'total_number_of_vms')
466 DROP_RATE_TRESHOLD = float(testconfig.get('DEFAULT', 'drop_rate_treshold'))
467 ACCURACY = float(testconfig.get('DEFAULT', 'accuracy'))
468 config = ConfigParser.RawConfigParser()
469 config.read(env+'.env')
470 key = config.get('OpenStack', 'key')
471 total_number_of_VMs = config.get('rapid', 'total_number_of_VMs')
472 if int(required_number_of_VMs) > int(total_number_of_VMs):
473 log.exception("Not enough VMs for this test: %s needed and only %s available" % (required_number_of_VMs,total_number_of_VMs))
474 raise Exception("Not enough VMs for this test: %s needed and only %s available" % (required_number_of_VMs,total_number_of_VMs))
475 for vm in range(1, int(total_number_of_VMs)+1):
476 vmAdminIP.append(config.get('VM%d'%vm, 'admin_ip'))
477 vmDPmac.append(config.get('VM%d'%vm, 'dp_mac'))
478 vmDPIP.append(config.get('VM%d'%vm, 'dp_ip'))
479 ip = vmDPIP[-1].split('.')
480 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))
481 for vm in range(1, int(required_number_of_VMs)+1):
482 config_file.append(testconfig.get('VM%d'%vm, 'config_file'))
483 script_control.append(testconfig.get('VM%d'%vm, 'script_control'))
484 group1cores=testconfig.get('VM%d'%vm, 'group1cores')
485 if group1cores <> 'not_used':
486 group1cores=ast.literal_eval(group1cores)
487 group2cores=testconfig.get('VM%d'%vm, 'group2cores')
488 if group2cores <> 'not_used':
489 group2cores=ast.literal_eval(group2cores)
490 group3cores=testconfig.get('VM%d'%vm, 'group3cores')
491 if group3cores <> 'not_used':
492 group3cores=ast.literal_eval(group3cores)
493 with open("parameters%d.lua"%vm, "w") as f:
494 f.write('name="%s"\n'% testconfig.get('VM%d'%vm, 'name'))
495 f.write('local_ip="%s"\n'% vmDPIP[vm-1])
496 f.write('local_hex_ip="%s"\n'% hexDPIP[vm-1])
497 gwVM = testconfig.get('VM%d'%vm, 'gw_vm')
498 if gwVM <> 'not_used':
499 gwVMindex = int(gwVM)-1
500 f.write('gw_ip="%s"\n'% vmDPIP[gwVMindex])
501 f.write('gw_hex_ip="%s"\n'% hexDPIP[gwVMindex])
502 destVM = testconfig.get('VM%d'%vm, 'dest_vm')
503 if destVM <> 'not_used':
504 destVMindex = int(destVM)-1
505 f.write('dest_ip="%s"\n'% vmDPIP[destVMindex])
506 f.write('dest_hex_ip="%s"\n'% hexDPIP[destVMindex])
507 f.write('dest_hex_mac="%s"\n'% vmDPmac[destVMindex].replace(':',' '))
508 if group1cores <> 'not_used':
509 f.write('group1="%s"\n'% ','.join(map(str, group1cores)))
510 if group2cores <> 'not_used':
511 f.write('group2="%s"\n'% ','.join(map(str, group2cores)))
512 if group3cores <> 'not_used':
513 f.write('group3="%s"\n'% ','.join(map(str, group3cores)))
514 if re.match('(l2){0,1}gen.*\.cfg',config_file[-1]):
515 gencores = group1cores
516 latcores = group2cores
517 genstatcores = group3cores
518 elif config_file[-1] == 'gen_gw.cfg':
519 gencores = group1cores
520 latcores = group2cores
521 genstatcores = group3cores
522 elif re.match('(l2){0,1}swap.*\.cfg',config_file[-1]):
523 sutstatcores = group1cores
524 elif config_file[-1] == 'secgw2.cfg':
525 sutstatcores = group1cores
526 elif config_file[-1] == 'irq.cfg':
527 irqcores = group1cores
529 #####################################################################################
533 for vm in range(0, int(required_number_of_VMs)):
534 client.append(prox_ctrl(vmAdminIP[vm], key+'.pem','root'))
535 connect_client(client[-1])
536 # Creating script to bind the right network interface to the poll mode driver
537 devbindfile = "devbindvm%d.sh"%(vm+1)
538 with open("devbind.sh") as f:
539 newText=f.read().replace('MACADDRESS', vmDPmac[vm])
540 with open(devbindfile, "w") as f:
542 st = os.stat(devbindfile)
543 os.chmod(devbindfile, st.st_mode | stat.S_IEXEC)
544 client[-1].scp_put('./%s'%devbindfile, '/root/devbind.sh')
545 cmd = '/root/devbind.sh'
546 client[-1].run_cmd(cmd)
547 log.debug("devbind.sh running on VM%d"%(vm+1))
548 client[-1].scp_put('./%s'%config_file[vm], '/root/%s'%config_file[vm])
549 client[-1].scp_put('./parameters%d.lua'%(vm+1), '/root/parameters.lua')
550 log.debug("Starting PROX on VM%d"%(vm+1))
551 if script_control[vm] == 'true':
552 cmd = '/root/prox/build/prox -e -t -o cli -f /root/%s'%config_file[vm]
554 cmd = '/root/prox/build/prox -t -o cli -f /root/%s'%config_file[vm]
555 client[-1].fork_cmd(cmd, 'PROX Testing on VM%d'%(vm+1))
556 sock.append(connect_socket(client[-1]))
558 init_code = testconfig.get('DEFAULT', 'init_code')
559 if init_code <> 'not_used':
561 ####################################################
563 # Best to run the flow test at the end since otherwise the tests coming after thatmight be influenced by the big number of entries in the switch flow tables
564 ####################################################
565 number_of_tests = testconfig.get('DEFAULT', 'number_of_tests')
566 for vm in range(1, int(number_of_tests)+1):
567 cmd=testconfig.get('test%d'%vm,'cmd')
569 ####################################################
570 for vm in range(0, int(required_number_of_VMs)):