Skip to content
Snippets Groups Projects
Commit 197b083f authored by Bob Lantz's avatar Bob Lantz
Browse files

Add static cpu (and memory) assignment.

parent a7648e78
No related branches found
No related tags found
No related merge requests found
......@@ -221,6 +221,9 @@ class MininetRunner( object ):
opts.add_option( '--prefixlen', type='int', default=8,
help='prefix length (e.g. /8) for automatic '
'network configuration' )
opts.add_option( '--pin', action='store_true',
default=False, help="pin hosts to CPU cores "
"(requires --host cfs or --host rt)" )
self.options, self.args = opts.parse_args()
......@@ -259,6 +262,7 @@ class MininetRunner( object ):
xterms = self.options.xterms
mac = self.options.mac
arp = self.options.arp
pin = self.options.pin
listenPort = None
if not self.options.nolistenport:
listenPort = self.options.listenport
......@@ -268,7 +272,8 @@ class MininetRunner( object ):
ipBase=ipBase,
inNamespace=inNamespace,
xterms=xterms, autoSetMacs=mac,
autoStaticArp=arp, listenPort=listenPort )
autoStaticArp=arp, autoPinCpus=pin,
listenPort=listenPort )
if self.options.pre:
CLI( mn, script=self.options.pre )
......
......@@ -96,7 +96,7 @@
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 @@ def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
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 @@ def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
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 @@ def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
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 @@ def addHost( self, name, cls=None, **params ):
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 @@ def configHosts( self ):
"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...
......
......@@ -51,8 +51,8 @@
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 @@ def cgroupGet( self, param, resource='cpu' ):
"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 @@ def setCPUFrac( self, f=-1, sched=None):
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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment