Add static cpu (and memory) assignment.
This commit is contained in:
+12
-4
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user