From 93cd5583eb9618ca38ba450bfa999975b1a3c77a Mon Sep 17 00:00:00 2001 From: Rich Lane Date: Thu, 22 May 2014 12:18:08 -0700 Subject: [PATCH 1/8] IVSSwitch: support batch shutdown Not a single command like the OVS one, but it still greatly decreases the shutdown time. This does assume that stop() is called after batchShutdown(), which is true in the current mininet code. --- mininet/node.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mininet/node.py b/mininet/node.py index 27d1e16..fdc855e 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -1106,6 +1106,13 @@ class IVSSwitch(Switch): 'not be loaded. Try modprobe openvswitch.\n' ) exit( 1 ) + @classmethod + def batchShutdown( cls, switches ): + "Kill each IVS switch, to be waited on later in stop()" + for switch in switches: + if type(switch) == cls: + switch.cmd( 'kill %ivs' ) + def start( self, controllers ): "Start up a new IVS switch" args = ['ivs'] From 876e66e5553fe1c93ef4ad4d3c9cbff5bb3735ee Mon Sep 17 00:00:00 2001 From: Rich Lane Date: Thu, 22 May 2014 12:36:07 -0700 Subject: [PATCH 2/8] net: allow batch shutdown of multiple types of switches Each switch class will be called to shutdown its own instances. --- mininet/net.py | 7 +++---- mininet/node.py | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/mininet/net.py b/mininet/net.py index 1c932f9..8edaee3 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -91,7 +91,7 @@ import re import select import signal from time import sleep -from itertools import chain +from itertools import chain, groupby from mininet.cli import CLI from mininet.log import info, error, debug, output @@ -408,10 +408,9 @@ class Mininet( object ): info( '*** Stopping %i terms\n' % len( self.terms ) ) self.stopXterms() info( '*** Stopping %i switches\n' % len( self.switches ) ) - if self.switches: - swclass = type( self.switches[ 0 ] ) + for swclass, switches in groupby( sorted( self.switches, key=type ), type ): if hasattr( swclass, 'batchShutdown' ): - swclass.batchShutdown( self.switches ) + swclass.batchShutdown( switches ) for switch in self.switches: info( switch.name + ' ' ) switch.stop() diff --git a/mininet/node.py b/mininet/node.py index fdc855e..54bfd23 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -993,7 +993,7 @@ class OVSSwitch( Switch ): "Call ovs-vsctl del-br on all OVSSwitches in a list" quietRun( 'ovs-vsctl ' + ' -- '.join( '--if-exists del-br %s' % s - for s in switches if type(s) == cls ) ) + for s in switches ) ) def dpctl( self, *args ): "Run ovs-ofctl command" @@ -1110,8 +1110,7 @@ class IVSSwitch(Switch): def batchShutdown( cls, switches ): "Kill each IVS switch, to be waited on later in stop()" for switch in switches: - if type(switch) == cls: - switch.cmd( 'kill %ivs' ) + switch.cmd( 'kill %ivs' ) def start( self, controllers ): "Start up a new IVS switch" From 163a66c64cb6cf084bd16a594954cac19b314171 Mon Sep 17 00:00:00 2001 From: Rich Lane Date: Thu, 22 May 2014 13:06:31 -0700 Subject: [PATCH 3/8] IVSSwitch: add an option to control the --verbose flag --- mininet/node.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index 27d1e16..a718ad2 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -1090,8 +1090,9 @@ OVSKernelSwitch = OVSSwitch class IVSSwitch(Switch): """IVS virtual switch""" - def __init__( self, name, **kwargs ): + def __init__( self, name, verbose=True, **kwargs ): Switch.__init__( self, name, **kwargs ) + self.verbose = verbose @classmethod def setup( cls ): @@ -1111,7 +1112,8 @@ class IVSSwitch(Switch): args = ['ivs'] args.extend( ['--name', self.name] ) args.extend( ['--dpid', self.dpid] ) - args.extend( ['--verbose'] ) + if self.verbose: + args.extend( ['--verbose'] ) for intf in self.intfs.values(): if not intf.IP(): args.extend( ['-i', intf.name] ) From 8b215af8183bdea8ee6294bc193c4900068c7af1 Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Wed, 28 May 2014 22:22:20 -0700 Subject: [PATCH 4/8] slight refactoring of util/vm/build.py to make it more extensible --- util/vm/build.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/util/vm/build.py b/util/vm/build.py index 3e0daa7..af39e05 100755 --- a/util/vm/build.py +++ b/util/vm/build.py @@ -781,6 +781,9 @@ def build( flavor='raring32server', tests=None, pre='', post='', memory=1024 ): def runTests( vm, tests=None, pre='', post='', prompt=Prompt ): "Run tests (list) in vm (pexpect object)" + if Branch: + checkOutBranch( vm, branch=Branch ) + vm.expect( prompt ) if not tests: tests = [] if pre: @@ -811,8 +814,8 @@ def getMininetVersion( vm ): return version -def bootAndRunTests( image, tests=None, pre='', post='', prompt=Prompt, - memory=1024, outputFile=None ): +def bootAndRun( image, prompt=Prompt, memory=1024, outputFile=None, + runFunction=None, **runArgs ): """Boot and test VM tests: list of tests to run pre: command line to run in VM before tests @@ -840,11 +843,9 @@ def bootAndRunTests( image, tests=None, pre='', post='', prompt=Prompt, login( vm ) log( '* Waiting for prompt after login' ) vm.expect( prompt ) - if Branch: - checkOutBranch( vm, branch=Branch ) - vm.expect( prompt ) - runTests( vm, tests=tests, pre=pre, post=post ) - # runTests eats its last prompt, but maybe it shouldn't... + # runFunction should begin with sendline and should eat its last prompt + if runFunction: + runFunction( vm, **runArgs ) log( '* Shutting down' ) vm.sendline( 'sudo shutdown -h now ' ) log( '* Waiting for shutdown' ) @@ -950,9 +951,8 @@ def parseArgs(): log( '* BUILD FAILED with exception: ', e ) exit( 1 ) for image in args.image: - bootAndRunTests( image, tests=args.test, pre=args.run, - post=args.post, memory=args.memory, - outputFile=args.out ) + bootAndRun( image, runFunction=runTests, tests=args.test, pre=args.run, + post=args.post, memory=args.memory, outputFile=args.out ) if not ( args.depend or args.list or args.clean or args.flavor or args.image ): parser.print_help() From e49c9d260018b973378c2d6379cd2af2c54c28da Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Fri, 6 Jun 2014 21:21:13 -0700 Subject: [PATCH 5/8] build.py: making ovf generation more generic --- util/vm/build.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/util/vm/build.py b/util/vm/build.py index af39e05..be809ec 100755 --- a/util/vm/build.py +++ b/util/vm/build.py @@ -158,7 +158,7 @@ def depend(): run( 'sudo apt-get -y update' ) run( 'sudo apt-get install -y' ' kvm cloud-utils genisoimage qemu-kvm qemu-utils' - ' e2fsprogs dnsmasq' + ' e2fsprogs dnsmasq curl' ' python-setuptools mtools zip' ) run( 'sudo easy_install pexpect' ) @@ -457,16 +457,16 @@ def boot( cow, kernel, initrd, logfile, memory=1024 ): return vm -def login( vm ): +def login( vm, user='mininet', password='mininet' ): "Log in to vm (pexpect object)" log( '* Waiting for login prompt' ) vm.expect( 'login: ' ) log( '* Logging in' ) - vm.sendline( 'mininet' ) + vm.sendline( user ) log( '* Waiting for password prompt' ) vm.expect( 'Password: ' ) log( '* Sending password' ) - vm.sendline( 'mininet' ) + vm.sendline( password ) log( '* Waiting for login...' ) @@ -628,9 +628,9 @@ OVFTemplate = """ The nat network - -A Mininet Virtual Machine (%(name)s) -mininet-vm + +%(vminfo)s (%(name)s) +%(vmname)s The kind of installed guest operating system %(osname)s @@ -640,10 +640,10 @@ OVFTemplate = """ hertz * 10^6 Number of Virtual CPUs -1 virtual CPU(s) +%(cpus)s virtual CPU(s) 1 3 -1 +%(cpus)s byte * 2^20 @@ -694,19 +694,23 @@ OVFTemplate = """ """ -def generateOVF( name, osname, osid, diskname, disksize, mem=1024 ): +def generateOVF( name, osname, osid, diskname, disksize, mem=1024, cpus=1, + vmname='Mininet-VM', vminfo='A Mininet Virtual Machine' ): """Generate (and return) OVF file "name.ovf" name: root name of OVF file to generate osname: OS name for OVF (Ubuntu | Ubuntu 64-bit) osid: OS ID for OVF (93 | 94 ) diskname: name of disk file disksize: size of virtual disk in bytes - mem: VM memory size in MB""" + mem: VM memory size in MB + cpus: # of virtual CPUs + vmname: Name for VM (default name when importing) + vmimfo: Brief description of VM for OVF""" ovf = name + '.ovf' filesize = stat( diskname )[ ST_SIZE ] params = dict( osname=osname, osid=osid, diskname=diskname, filesize=filesize, disksize=disksize, name=name, - mem=mem ) + mem=mem, cpus=cpus, vmname=vmname, vminfo=vminfo ) xmltext = OVFTemplate % params with open( ovf, 'w+' ) as f: f.write( xmltext ) From b3055067ace901a89c63a9c03eda7cbaafe07c83 Mon Sep 17 00:00:00 2001 From: Cody Burkard Date: Tue, 10 Jun 2014 18:38:10 -0700 Subject: [PATCH 6/8] fixed netParse bug that caused mininet crash when no ip prefix was specified --- mininet/util.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mininet/util.py b/mininet/util.py index b03e945..3dfa04c 100644 --- a/mininet/util.py +++ b/mininet/util.py @@ -281,6 +281,8 @@ def ipAdd( i, prefixLen=8, ipBaseNum=0x0a000000 ): def ipParse( ip ): "Parse an IP address and return an unsigned int." args = [ int( arg ) for arg in ip.split( '.' ) ] + while ( len(args) < 4 ): + args.append( 0 ) return ipNum( *args ) def netParse( ipstr ): @@ -290,6 +292,10 @@ def netParse( ipstr ): if '/' in ipstr: ip, pf = ipstr.split( '/' ) prefixLen = int( pf ) + #if no prefix is specified, set the prefix to 24 + else: + ip = ipstr + prefixLen = 24 return ipParse( ip ), prefixLen def checkInt( s ): From 00803bcd7f3e05c9caec0ace6333b02595101710 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Fri, 27 Jun 2014 13:05:10 -0700 Subject: [PATCH 7/8] Whitespace changes in OVSSwitch. --- mininet/node.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index 422ea15..783c949 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -1076,16 +1076,16 @@ class OVSSwitch( Switch ): self.cmd( 'ovs-vsctl add-br', self ) for intf in self.intfList(): if not intf.IP(): - self.cmd('ovs-vsctl add-port', self, intf ) - cmd = ('ovs-vsctl set Bridge %s ' % self + - 'other_config:datapath-id=%s ' % self.dpid + - '-- set-fail-mode %s %s ' % ( self, self.failMode ) + - '-- set-controller %s %s ' % ( self, clist ) ) + self.cmd( 'ovs-vsctl add-port', self, intf ) + cmd = ( 'ovs-vsctl set Bridge %s ' % self + + 'other_config:datapath-id=%s ' % self.dpid + + '-- set-fail-mode %s %s ' % ( self, self.failMode ) + + '-- set-controller %s %s ' % ( self, clist ) ) if not self.inband: cmd += ( '-- set bridge %s ' 'other-config:disable-in-band=true ' % self ) if self.datapath == 'user': - cmd += '-- set bridge %s datapath_type=netdev ' % self + cmd += '-- set bridge %s datapath_type=netdev ' % self # Reconnect quickly to controllers (1s vs. 15s max_backoff) for uuid in self.controllerUUIDs(): if uuid.count( '-' ) != 4: From 191df1cb731743dc938b5fac7268e358b0de69b0 Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Wed, 9 Jul 2014 17:47:25 -0700 Subject: [PATCH 8/8] Adding listen socket to UserSwitch when there is no listenPort set --- mininet/node.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index 96107f9..568d986 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -856,6 +856,8 @@ class UserSwitch( Switch ): '(openflow.org)' ) if self.listenPort: self.opts += ' --listen=ptcp:%i ' % self.listenPort + else: + self.opts += ' --listen=punix:/tmp/%s.listen' % self.name self.dpopts = dpopts @classmethod @@ -868,7 +870,7 @@ class UserSwitch( Switch ): "Run dpctl command" listenAddr = None if not self.listenPort: - listenAddr = 'unix:/tmp/' + self.name + listenAddr = 'unix:/tmp/%s.listen' % self.name else: listenAddr = 'tcp:127.0.0.1:%i' % self.listenPort return self.cmd( 'dpctl ' + ' '.join( args ) +