blob: 9eb022eb44519038e8ddb48d58757d3747552be9 [file] [log] [blame]
#!/usr/bin/python
'''
Script that tests Flow Manager performance
Author: Brian O'Connor <bocon@onlab.us>
'''
import csv
import os
import sys
import re
from time import sleep, strftime
from subprocess import Popen, call, check_output, PIPE
from datetime import datetime
try:
import pexpect
except:
# install pexpect if it cannot be found and re-import
print '* Installing Pexpect'
call( 'apt-get install -y python-pexpect', stdout=PIPE, shell=True )
import pexpect
ONOS_HOME = '..'
ONOS_LOG = '%s/onos-logs/onos.%s.log' % ( ONOS_HOME, check_output( 'hostname').strip() )
ONOS_URL = 'http://127.0.0.1:8080/wm/onos/flows/get/%d/json'
ONOS_LOG = '/tmp/onos-0.logs/onos.onos-vm.log'
print "ONOS Log File:", ONOS_LOG
PORT = 's1-eth2'
N = 1
# ----------------- Running the test and output -------------------------
class Result(object):
def __init__(self, tsharkTime, flowmods, onosTime, overhead, details):
self.tsharkTime = tsharkTime
self.flowmods = flowmods
self.onosTime = onosTime
self.overhead = overhead
# sorted by start time
self.tags = sorted(details, key=lambda x: float(x[2]))
self.details = sorted(details, key=lambda x: float(x[2]), reverse=True)
def __repr__(self):
return '%f %f %f %d %s' % (self.tsharkTime, self.onosTime, self.overhead, self.flowmods, self.tags)
def clearResults():
cmd = 'curl %s' % ONOS_URL % -200
call( cmd, shell=True )
pass
def reportResults():
cmd = 'curl %s' % ONOS_URL % -100
call( cmd, shell=True )
def test():
# Start tailing the onos log
tail = pexpect.spawn( "tail -0f %s" % ONOS_LOG )
tshark = pexpect.spawn( 'tshark -i lo -R "of.type == 12 || of.type == 14"' )
tshark.expect('Capturing on lo')
sleep(1) # wait for tshark to start
clearResults() # REST call to ONOS
# Take link down
call( 'ifconfig %s down' % PORT, shell=True )
# collect openflow packets using tshark
count = 0
timeout = 6000
start = -1
end = -1
while True:
i = tshark.expect( ['(\d+\.\d+)', pexpect.TIMEOUT], timeout=timeout )
if i == 1:
break
time = float(tshark.match.group(1))
if start == -1:
start = time
if time > end:
end = time
i = tshark.expect( ['Port Status', 'Flow Mod'] )
if i == 1:
count += 1
timeout = 3 #sec
elapsed = (end - start) * 1000
sleep(2)
# read the performance results from ONOS
reportResults() # REST call
# Wait for performance results in the log
tail.expect('Performance Results: \(avg/start/stop/count\)', timeout=10)
i = tail.expect('TotalTime:([\d\.]+)/Overhead:([\d\.]+)')
totalTime = float(tail.match.group(1))
overhead = float(tail.match.group(2))
tags = re.findall( r'([\w\.]+)=([\d\.]+)/([\d\.]+)/([\d\.]+)/(\d+)', tail.before )
result = Result(elapsed, count, totalTime, overhead, tags)
# Output results
print result
plot(result)
# Bring port back up
call( 'ifconfig %s up' % PORT, shell=True )
tail.terminate()
tshark.terminate()
return []
def outputResults(filename, results):
with open(filename, 'a') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(results)
def runPerf(n):
filename = 'results-flowmanager-%s.csv' % strftime( '%Y%m%d-%H%M%S' )
print 'Starting experiments:'
start = datetime.now()
for i in range(n):
results = test()
#outputResults(filename, results)
sys.stdout.write('$')
sys.stdout.flush()
sleep(5) # sleep for 5 seconds between tests
sys.stdout.write('.')
sys.stdout.flush()
totalTime = datetime.now() - start
print '\nExperiments complete in %s (h:m:s.s)' % totalTime
def plot(result):
import matplotlib.pyplot as plt
import pylab
import numpy as np
from matplotlib.ticker import MaxNLocator
tags = [ x[0] for x in result.details ]
numTags = len(tags)
scores = [ float(x[1]) for x in result.details ]
offset = [ float(x[2]) for x in result.details ]
rankings = [ float(x[3]) - float(x[2]) for x in result.details ]
counts = [ x[4] for x in result.details ]
fig, ax1 = plt.subplots(figsize=(15, 9))
plt.subplots_adjust(left=0.3, right=0.8)
pos = np.arange(numTags)+0.5 # Center bars on the Y-axis ticks
rects = ax1.barh(pos, rankings, left=offset, align='center', height=0.5, color='m')
ax1.axis([0, result.onosTime, 0, numTags])
pylab.yticks(pos, tags)
ax1.set_title('TITLE HERE')
#plt.text(result.onosTime/2, -0.5,
# 'Iteration: ' + str(1), horizontalalignment='center', size='small')
# Set the right-hand Y-axis ticks and labels and set X-axis tick marks at the
# deciles
ax2 = ax1.twinx()
print MaxNLocator(7)
ax2.xaxis.set_major_locator(MaxNLocator(7)) # max number of xaxis ticks
#ax2.plot([100, 100], [0, 5], 'white', alpha=0.1)
ax2.xaxis.grid(True, linestyle='--', which='major', color='grey', alpha=0.25)
#Plot a solid vertical gridline to highlight the median position
#plt.plot([50, 50], [0, 5], 'grey', alpha=0.25)
# Build up the score labels for the right Y-axis by first appending a carriage
# return to each string and then tacking on the appropriate meta information
# (i.e., 'laps' vs 'seconds'). We want the labels centered on the ticks, so if
# there is no meta info (like for pushups) then don't add the carriage return to
# the string
'''
scoreLabels = [withnew(i, scr) for i, scr in enumerate(scores)]
scoreLabels = [i+j for i, j in zip(scoreLabels, testMeta)]
'''
scoreLabels = ['%.3f ms\n%s'%(i,j) for i,j in zip(scores,counts)]
# set the tick locations
ax2.set_yticks(pos)
# set the tick labels
ax2.set_yticklabels(scoreLabels)
# make sure that the limits are set equally on both yaxis so the ticks line up
ax2.set_ylim(ax1.get_ylim())
ax1.set_xlabel('Time (ms)')
ax2.set_ylabel('Average iteration / Count')
# Lastly, write in the ranking inside each bar to aid in interpretation
for rect in rects:
# Rectangle widths are already integer-valued but are floating
# type, so it helps to remove the trailing decimal point and 0 by
# converting width to int type
width = int(rect.get_width())
offset = int(rect.get_x())
percent = width / result.onosTime
onePercent = 0.01 * result.onosTime
rankStr = str(width) + 'ms'
if (percent < 0.09): # The bars aren't wide enough to print the ranking inside
xloc = offset + width + onePercent # Shift the text to the right side of the right edge
clr = 'black' # Black against white background
align = 'left'
else:
xloc = offset + 0.98*width # Shift the text to the left side of the right edge
clr = 'white' # White on magenta
align = 'right'
# Center the text vertically in the bar
yloc = rect.get_y()+rect.get_height()/2.0
ax1.text(xloc, yloc, rankStr, horizontalalignment=align,
verticalalignment='center', color=clr)
plt.show()
plt.savefig('test.png')
if __name__ == '__main__':
n = N
runPerf(n)