From fcd01592e11d7799a88abfbb9a2823cbd5fba768 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Wed, 14 Nov 2012 07:55:10 -0800 Subject: [PATCH] Move CPU limit into net, to be reused in future unit tests --- examples/limit.py | 24 ++++-------------------- mininet/net.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/examples/limit.py b/examples/limit.py index fbda428..0b23ca1 100755 --- a/examples/limit.py +++ b/examples/limit.py @@ -8,33 +8,17 @@ from mininet.net import Mininet from mininet.link import TCIntf from mininet.node import CPULimitedHost from mininet.topolib import TreeTopo -from mininet.util import custom, quietRun +from mininet.util import custom from mininet.log import setLogLevel -from time import sleep + def testLinkLimit( net, bw ): "Run bandwidth limit test" print '*** Testing network %.2f Mbps bandwidth limit' % bw net.iperf( ) -def testCpuLimit( net, cpu ): - "run CPU limit test" - pct = cpu * 100 - print '*** Testing CPU %.0f%% bandwidth limit' % pct - h1, h2 = net.hosts - h1.cmd( 'while true; do a=1; done &' ) - h2.cmd( 'while true; do a=1; done &' ) - pid1 = h1.cmd( 'echo $!' ).strip() - pid2 = h2.cmd( 'echo $!' ).strip() - cmd = 'ps -p %s,%s -o pid,%%cpu,args' % ( pid1, pid2 ) - # It's a shame that this is what pylint prefers - for _ in range( 5 ): - sleep( 1 ) - print quietRun( cmd ).strip() - h1.cmd( 'kill %1') - h2.cmd( 'kill %1') -def limit( bw=10, cpu=.4 ): +def limit( bw=10, cpu=.1 ): """Example/test of link and CPU bandwidth limits bw: interface bandwidth limit in Mbps cpu: cpu limit as fraction of overall CPU time""" @@ -46,7 +30,7 @@ def limit( bw=10, cpu=.4 ): net = Mininet( topo=myTopo, intf=intf, host=host ) net.start() testLinkLimit( net, bw=bw ) - testCpuLimit( net, cpu=cpu ) + net.runCpuLimitTest( cpu=cpu ) net.stop() def verySimpleLimit( bw=150 ): diff --git a/mininet/net.py b/mininet/net.py index 8b6cf94..f2b774a 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -530,6 +530,42 @@ class Mininet( object ): output( '*** Results: %s\n' % result ) return result + def runCpuLimitTest( self, cpu, duration=5 ): + """run CPU limit test with 'while true' processes. + cpu: desired CPU fraction of each host + duration: test duration in seconds + returns a single list of measured CPU fractions as floats. + """ + pct = cpu * 100 + info('*** Testing CPU %.0f%% bandwidth limit\n' % pct) + hosts = self.hosts + for h in hosts: + h.cmd( 'while true; do a=1; done &' ) + pids = [h.cmd( 'echo $!' ).strip() for h in hosts] + pids_str = ",".join(["%s" % pid for pid in pids]) + cmd = 'ps -p %s -o pid,%%cpu,args' % pids_str + # It's a shame that this is what pylint prefers + outputs = [] + for _ in range( duration ): + sleep( 1 ) + outputs.append( quietRun( cmd ).strip() ) + for h in hosts: + h.cmd( 'kill %1' ) + cpu_fractions = [] + for test_output in outputs: + # Split by line. Ignore first line, which looks like this: + # PID %CPU COMMAND\n + for line in test_output.split('\n')[1:]: + r = r'\d+ (\d+\.\d+)' + m = re.search( r, line ) + if m is None: + error( '*** Error: could not extract CPU fraction: %s\n' % + line ) + return None + cpu_fractions.append( float( m.group( 1 ) ) ) + output( '*** Results: %s\n' % cpu_fractions ) + return cpu_fractions + # BL: I think this can be rewritten now that we have # a real link class. def configLinkStatus( self, src, dst, status ):