Add static cpu (and memory) assignment.

This commit is contained in:
Bob Lantz
2012-04-08 20:49:12 -07:00
parent a7648e78fb
commit 197b083fbc
3 changed files with 55 additions and 11 deletions
+12 -4
View File
@@ -96,7 +96,7 @@ from mininet.cli import CLI
from mininet.log import info, error, debug, output
from mininet.node import Host, OVSKernelSwitch, Controller
from mininet.link import Link, Intf
from mininet.util import quietRun, fixLimits
from mininet.util import quietRun, fixLimits, numCores
from mininet.util import macColonHex, ipStr, ipParse, netParse, ipAdd
from mininet.term import cleanUpScreens, makeTerms
@@ -107,7 +107,8 @@ class Mininet( object ):
controller=Controller, link=Link, intf=Intf,
build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8',
inNamespace=False,
autoSetMacs=False, autoStaticArp=False, listenPort=None ):
autoSetMacs=False, autoStaticArp=False, autoPinCpus=False,
listenPort=None ):
"""Create Mininet object.
topo: Topo (topology) object or None
switch: default Switch class
@@ -120,8 +121,9 @@ class Mininet( object ):
xterms: if build now, spawn xterms?
cleanup: if build now, cleanup before creating?
inNamespace: spawn switches and controller in net namespaces?
autoSetMacs: set MAC addrs from topo dpid?
autoSetMacs: set MAC addrs automatically like IP addresses?
autoStaticArp: set all-pairs static MAC addrs?
autoPinCpus: pin hosts to (real) cores (requires CPULimitedHost)?
listenPort: base listening port to open; will be incremented for
each additional switch in the net if inNamespace=False"""
self.topo = topo
@@ -138,6 +140,9 @@ class Mininet( object ):
self.cleanup = cleanup
self.autoSetMacs = autoSetMacs
self.autoStaticArp = autoStaticArp
self.autoPinCpus = autoPinCpus
self.numCores = numCores()
self.nextCore = 0 # next core for pinning hosts to CPUs
self.listenPort = listenPort
self.hosts = []
@@ -166,6 +171,9 @@ class Mininet( object ):
prefixLen=self.prefixLen ) }
if self.autoSetMacs:
defaults[ 'mac'] = macColonHex( self.nextIP )
if self.autoPinCpus:
defaults[ 'cores' ] = self.nextCore
self.nextCore = ( self.nextCore + 1 ) % self.numCores
self.nextIP += 1
defaults.update( params )
if not cls:
@@ -230,7 +238,7 @@ class Mininet( object ):
"Configure a set of hosts."
for host in self.hosts:
info( host.name + ' ' )
host.configDefault( defaultRoute=host.defaultIntf )
host.configDefault( defaultRoute=host.defaultIntf() )
# You're low priority, dude!
# BL: do we want to do this here or not?
# May not make sense if we have CPU lmiting...
+37 -6
View File
@@ -51,8 +51,8 @@ import select
from subprocess import Popen, PIPE, STDOUT
from mininet.log import info, error, warn, debug
from mininet.util import quietRun, errRun, errFail, moveIntf, isShellBuiltin
from mininet.util import numCores, retry
from mininet.util import ( quietRun, errRun, errFail, moveIntf, isShellBuiltin,
numCores, retry, mountCgroups )
from mininet.moduledeps import moduleDeps, pathCheck, OVS_KMOD, OF_KMOD, TUN
from mininet.link import Link, Intf, TCIntf
@@ -514,10 +514,15 @@ class CPULimitedHost( Host ):
def __init__( self, name, sched='cfs', **kwargs ):
Host.__init__( self, name, **kwargs )
# Initialize class if necessary
if not CPULimitedHost.inited:
CPULimitedHost.init()
# Create a cgroup and move shell into it
self.cgroup = 'cpu,cpuacct:/' + self.name
self.cgroup = 'cpu,cpuacct,cpuset:/' + self.name
errFail( 'cgcreate -g ' + self.cgroup )
errFail( 'cgclassify -g %s %s' % ( self.cgroup, self.pid ) )
# We don't add ourselves to a cpuset because you must
# specify the cpu and memory placement first
errFail( 'cgclassify -g cpu,cpuacct:/%s %s' % ( self.name, self.pid ) )
# BL: Setting the correct period/quota is tricky, particularly
# for RT. RT allows very small quotas, but the overhead
# seems to be high. CFS has a mininimum quota of 1 ms, but
@@ -540,7 +545,7 @@ class CPULimitedHost( Host ):
"Return value of cgroup parameter"
cmd = 'cgget -r %s.%s /%s' % (
resource, param, self.name )
return quietRun( cmd ).split()[ -1 ]
return int( quietRun( cmd ).split()[ -1 ] )
def cgroupDel( self ):
"Clean up our cgroup"
@@ -616,15 +621,41 @@ class CPULimitedHost( Host ):
self.chrt( prio=20 )
info( '(%s %d/%dus) ' % ( sched, quota, period ) )
def config( self, cpu=None, **params ):
def setCPUs( self, cores ):
"Specify (real) cores that our cgroup can run on"
if type( cores ) is list:
cores = ','.join( [ str( c ) for c in cores ] )
self.cgroupSet( resource='cpuset', param='cpus',
value= cores )
# Memory placement is probably not relevant, but we
# must specify it anyway
self.cgroupSet( resource='cpuset', param='mems',
value= cores )
# We have to do this here after we've specified
# cpus and mems
errFail( 'cgclassify -g cpuset:/%s %s' % (
self.name, self.pid ) )
def config( self, cpu=None, cores=None, **params ):
"""cpu: desired overall system CPU fraction
cores: (real) core(s) this host can run on
params: parameters for Node.config()"""
r = Node.config( self, **params )
# Was considering cpu={'cpu': cpu , 'sched': sched}, but
# that seems redundant
self.setParam( r, 'setCPUFrac', cpu=cpu )
self.setParam( r, 'setCPUs', cores=cores )
return r
inited = False
@classmethod
def init( cls ):
"Initialization for CPULimitedHost class"
mountCgroups()
cls.inited = True
# Some important things to note:
#
# The "IP" address which setIP() assigns to the switch is not