brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | ''' |
| 3 | Script that tests Flow Manager performance |
| 4 | Author: Brian O'Connor <bocon@onlab.us> |
| 5 | |
| 6 | ''' |
| 7 | |
| 8 | import csv |
| 9 | import os |
| 10 | import sys |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 11 | import re |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 12 | from time import sleep, strftime |
| 13 | from subprocess import Popen, call, check_output, PIPE |
| 14 | from datetime import datetime |
| 15 | |
| 16 | try: |
| 17 | import pexpect |
| 18 | except: |
| 19 | # install pexpect if it cannot be found and re-import |
| 20 | print '* Installing Pexpect' |
| 21 | call( 'apt-get install -y python-pexpect', stdout=PIPE, shell=True ) |
| 22 | import pexpect |
| 23 | |
| 24 | ONOS_HOME = '..' |
| 25 | ONOS_LOG = '%s/onos-logs/onos.%s.log' % ( ONOS_HOME, check_output( 'hostname').strip() ) |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 26 | ONOS_URL = 'http://127.0.0.1:8080/wm/onos/flows/get/%d/json' |
| 27 | ONOS_LOG = '/tmp/onos-0.logs/onos.onos-vm.log' |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 28 | print "ONOS Log File:", ONOS_LOG |
| 29 | |
| 30 | PORT = 's1-eth2' |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 31 | N = 5 |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 32 | |
| 33 | # ----------------- Running the test and output ------------------------- |
| 34 | |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 35 | class Result(object): |
| 36 | def __init__(self, tsharkTime, flowmods, onosTime, overhead, details): |
| 37 | self.tsharkTime = tsharkTime |
| 38 | self.flowmods = flowmods |
| 39 | self.onosTime = onosTime |
| 40 | self.overhead = overhead |
| 41 | # sorted by start time |
| 42 | self.details = sorted(details, key=lambda x: float(x[2]) ) |
| 43 | |
| 44 | def __repr__(self): |
| 45 | return '%f %f %f %d %s' % (self.tsharkTime, self.onosTime, self.overhead, self.flowmods, self.details) |
| 46 | |
| 47 | |
| 48 | def clearResults(): |
| 49 | cmd = 'curl %s' % ONOS_URL % -200 |
| 50 | call( cmd, shell=True ) |
| 51 | pass |
| 52 | |
| 53 | def reportResults(): |
| 54 | cmd = 'curl %s' % ONOS_URL % -100 |
| 55 | call( cmd, shell=True ) |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 56 | |
| 57 | def test(): |
| 58 | # Start tailing the onos log |
| 59 | tail = pexpect.spawn( "tail -0f %s" % ONOS_LOG ) |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 60 | tshark = pexpect.spawn( 'tshark -i lo -R "of.type == 12 || of.type == 14"' ) |
| 61 | tshark.expect('Capturing on lo') |
| 62 | sleep(1) # wait for tshark to start |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 63 | |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 64 | clearResults() # REST call to ONOS |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 65 | # Take link down |
| 66 | call( 'ifconfig %s down' % PORT, shell=True ) |
| 67 | |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 68 | # collect openflow packets using tshark |
| 69 | count = 0 |
| 70 | timeout = 6000 |
| 71 | start = -1 |
| 72 | end = -1 |
| 73 | while True: |
| 74 | i = tshark.expect( ['(\d+\.\d+)', pexpect.TIMEOUT], timeout=timeout ) |
| 75 | if i == 1: |
| 76 | break |
| 77 | time = float(tshark.match.group(1)) |
| 78 | if start == -1: |
| 79 | start = time |
| 80 | if time > end: |
| 81 | end = time |
| 82 | i = tshark.expect( ['Port Status', 'Flow Mod'] ) |
| 83 | if i == 1: |
| 84 | count += 1 |
| 85 | timeout = 3 #sec |
| 86 | elapsed = (end - start) * 1000 |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 87 | |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 88 | # read the performance results from ONOS |
| 89 | reportResults() # REST call |
| 90 | |
| 91 | # Wait for performance results in the log |
| 92 | tail.expect('Performance Results: \(avg/start/stop/count\)', timeout=10) |
| 93 | i = tail.expect('TotalTime:([\d\.]+)/Overhead:([\d\.]+)') |
| 94 | totalTime = float(tail.match.group(1)) |
| 95 | overhead = float(tail.match.group(2)) |
| 96 | tags = re.findall( r'([\w\.]+)=([\d\.]+)/([\d\.]+)/([\d\.]+)/(\d+)', tail.before ) |
| 97 | result = Result(elapsed, count, totalTime, overhead, tags) |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 98 | # Output results |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 99 | print result |
| 100 | |
| 101 | |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 102 | # Bring port back up |
| 103 | call( 'ifconfig %s up' % PORT, shell=True ) |
| 104 | |
| 105 | tail.terminate() |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 106 | tshark.terminate() |
| 107 | return [] |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 108 | |
| 109 | def outputResults(filename, results): |
| 110 | with open(filename, 'a') as csvfile: |
| 111 | writer = csv.writer(csvfile) |
| 112 | writer.writerow(results) |
| 113 | |
| 114 | def runPerf(n): |
| 115 | filename = 'results-flowmanager-%s.csv' % strftime( '%Y%m%d-%H%M%S' ) |
| 116 | print 'Starting experiments:' |
| 117 | start = datetime.now() |
| 118 | for i in range(n): |
| 119 | results = test() |
Brian O'Connor | 0d9963f | 2014-01-14 14:44:21 -0800 | [diff] [blame^] | 120 | #outputResults(filename, results) |
| 121 | sys.stdout.write('$') |
| 122 | sys.stdout.flush() |
| 123 | sleep(5) # sleep for 5 seconds between tests |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 124 | sys.stdout.write('.') |
| 125 | sys.stdout.flush() |
brian | b87e3b1 | 2014-01-12 22:12:14 -0800 | [diff] [blame] | 126 | totalTime = datetime.now() - start |
| 127 | print '\nExperiments complete in %s (h:m:s.s)' % totalTime |
| 128 | |
| 129 | if __name__ == '__main__': |
| 130 | n = N |
| 131 | runPerf(n) |
| 132 | |