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
+6 -1
View File
@@ -221,6 +221,9 @@ class MininetRunner( object ):
opts.add_option( '--prefixlen', type='int', default=8, opts.add_option( '--prefixlen', type='int', default=8,
help='prefix length (e.g. /8) for automatic ' help='prefix length (e.g. /8) for automatic '
'network configuration' ) '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() self.options, self.args = opts.parse_args()
@@ -259,6 +262,7 @@ class MininetRunner( object ):
xterms = self.options.xterms xterms = self.options.xterms
mac = self.options.mac mac = self.options.mac
arp = self.options.arp arp = self.options.arp
pin = self.options.pin
listenPort = None listenPort = None
if not self.options.nolistenport: if not self.options.nolistenport:
listenPort = self.options.listenport listenPort = self.options.listenport
@@ -268,7 +272,8 @@ class MininetRunner( object ):
ipBase=ipBase, ipBase=ipBase,
inNamespace=inNamespace, inNamespace=inNamespace,
xterms=xterms, autoSetMacs=mac, xterms=xterms, autoSetMacs=mac,
autoStaticArp=arp, listenPort=listenPort ) autoStaticArp=arp, autoPinCpus=pin,
listenPort=listenPort )
if self.options.pre: if self.options.pre:
CLI( mn, script=self.options.pre ) CLI( mn, script=self.options.pre )
+12 -4
View File
@@ -96,7 +96,7 @@ from mininet.cli import CLI
from mininet.log import info, error, debug, output from mininet.log import info, error, debug, output
from mininet.node import Host, OVSKernelSwitch, Controller from mininet.node import Host, OVSKernelSwitch, Controller
from mininet.link import Link, Intf 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.util import macColonHex, ipStr, ipParse, netParse, ipAdd
from mininet.term import cleanUpScreens, makeTerms from mininet.term import cleanUpScreens, makeTerms
@@ -107,7 +107,8 @@ class Mininet( object ):
controller=Controller, link=Link, intf=Intf, controller=Controller, link=Link, intf=Intf,
build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8', build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8',
inNamespace=False, inNamespace=False,
autoSetMacs=False, autoStaticArp=False, listenPort=None ): autoSetMacs=False, autoStaticArp=False, autoPinCpus=False,
listenPort=None ):
"""Create Mininet object. """Create Mininet object.
topo: Topo (topology) object or None topo: Topo (topology) object or None
switch: default Switch class switch: default Switch class
@@ -120,8 +121,9 @@ class Mininet( object ):
xterms: if build now, spawn xterms? xterms: if build now, spawn xterms?
cleanup: if build now, cleanup before creating? cleanup: if build now, cleanup before creating?
inNamespace: spawn switches and controller in net namespaces? 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? 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 listenPort: base listening port to open; will be incremented for
each additional switch in the net if inNamespace=False""" each additional switch in the net if inNamespace=False"""
self.topo = topo self.topo = topo
@@ -138,6 +140,9 @@ class Mininet( object ):
self.cleanup = cleanup self.cleanup = cleanup
self.autoSetMacs = autoSetMacs self.autoSetMacs = autoSetMacs
self.autoStaticArp = autoStaticArp self.autoStaticArp = autoStaticArp
self.autoPinCpus = autoPinCpus
self.numCores = numCores()
self.nextCore = 0 # next core for pinning hosts to CPUs
self.listenPort = listenPort self.listenPort = listenPort
self.hosts = [] self.hosts = []
@@ -166,6 +171,9 @@ class Mininet( object ):
prefixLen=self.prefixLen ) } prefixLen=self.prefixLen ) }
if self.autoSetMacs: if self.autoSetMacs:
defaults[ 'mac'] = macColonHex( self.nextIP ) defaults[ 'mac'] = macColonHex( self.nextIP )
if self.autoPinCpus:
defaults[ 'cores' ] = self.nextCore
self.nextCore = ( self.nextCore + 1 ) % self.numCores
self.nextIP += 1 self.nextIP += 1
defaults.update( params ) defaults.update( params )
if not cls: if not cls:
@@ -230,7 +238,7 @@ class Mininet( object ):
"Configure a set of hosts." "Configure a set of hosts."
for host in self.hosts: for host in self.hosts:
info( host.name + ' ' ) info( host.name + ' ' )
host.configDefault( defaultRoute=host.defaultIntf ) host.configDefault( defaultRoute=host.defaultIntf() )
# You're low priority, dude! # You're low priority, dude!
# BL: do we want to do this here or not? # BL: do we want to do this here or not?
# May not make sense if we have CPU lmiting... # 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 subprocess import Popen, PIPE, STDOUT
from mininet.log import info, error, warn, debug from mininet.log import info, error, warn, debug
from mininet.util import quietRun, errRun, errFail, moveIntf, isShellBuiltin from mininet.util import ( quietRun, errRun, errFail, moveIntf, isShellBuiltin,
from mininet.util import numCores, retry numCores, retry, mountCgroups )
from mininet.moduledeps import moduleDeps, pathCheck, OVS_KMOD, OF_KMOD, TUN from mininet.moduledeps import moduleDeps, pathCheck, OVS_KMOD, OF_KMOD, TUN
from mininet.link import Link, Intf, TCIntf from mininet.link import Link, Intf, TCIntf
@@ -514,10 +514,15 @@ class CPULimitedHost( Host ):
def __init__( self, name, sched='cfs', **kwargs ): def __init__( self, name, sched='cfs', **kwargs ):
Host.__init__( self, name, **kwargs ) Host.__init__( self, name, **kwargs )
# Initialize class if necessary
if not CPULimitedHost.inited:
CPULimitedHost.init()
# Create a cgroup and move shell into it # 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( '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 # BL: Setting the correct period/quota is tricky, particularly
# for RT. RT allows very small quotas, but the overhead # for RT. RT allows very small quotas, but the overhead
# seems to be high. CFS has a mininimum quota of 1 ms, but # 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" "Return value of cgroup parameter"
cmd = 'cgget -r %s.%s /%s' % ( cmd = 'cgget -r %s.%s /%s' % (
resource, param, self.name ) resource, param, self.name )
return quietRun( cmd ).split()[ -1 ] return int( quietRun( cmd ).split()[ -1 ] )
def cgroupDel( self ): def cgroupDel( self ):
"Clean up our cgroup" "Clean up our cgroup"
@@ -616,15 +621,41 @@ class CPULimitedHost( Host ):
self.chrt( prio=20 ) self.chrt( prio=20 )
info( '(%s %d/%dus) ' % ( sched, quota, period ) ) 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 """cpu: desired overall system CPU fraction
cores: (real) core(s) this host can run on
params: parameters for Node.config()""" params: parameters for Node.config()"""
r = Node.config( self, **params ) r = Node.config( self, **params )
# Was considering cpu={'cpu': cpu , 'sched': sched}, but # Was considering cpu={'cpu': cpu , 'sched': sched}, but
# that seems redundant # that seems redundant
self.setParam( r, 'setCPUFrac', cpu=cpu ) self.setParam( r, 'setCPUFrac', cpu=cpu )
self.setParam( r, 'setCPUs', cores=cores )
return r return r
inited = False
@classmethod
def init( cls ):
"Initialization for CPULimitedHost class"
mountCgroups()
cls.inited = True
# Some important things to note: # Some important things to note:
# #
# The "IP" address which setIP() assigns to the switch is not # The "IP" address which setIP() assigns to the switch is not