Merge branch 'of1.0' into testing

Conflicts:

	bin/mn
	mininet/cli.py
	mininet/moduledeps.py
	mininet/node.py
	mininet/topo.py
	util/install.sh
This commit is contained in:
Bob Lantz
2010-10-17 17:23:23 -07:00
10 changed files with 505 additions and 113 deletions
+159 -44
View File
@@ -1,31 +1,71 @@
Preliminary Mininet Installation/Configuration Notes Preliminary Mininet Installation/Configuration Notes
Alpha release, March 2010 Pre-Beta version, August 2010
--- ---
(Disclaimer: this is an early alpha release; things may be broken!) (Disclaimer: we're still pre-beta - things may be broken!)
The easiest way to get Mininet running is to start with one of our pre-built virtual machine images from: The supported installation methods for Mininet Pre-Beta are 1) using
a pre-built VM image, and 2) native installation on Ubuntu or Debian.
(Other distributions may be supported in the future - if you would
like to contribute an installation script, we would welcome it!)
http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetGettingStarted 1. Easiest "install" - use our pre-built VM image!
Once you have booted up the VM image, all you need to do to install The easiest way to get Mininet running is to start with one of our pre-built
Mininet into it is: virtual machine images from:
git clone git://yuba.stanford.edu/mininet.git http://openflow.org/foswiki/bin/view/OpenFlow/MininetGettingStarted
cd mininet
sudo make install
At this point, it should be possible to run a simple Mininet configuration Boot up the VM image, log in, and follow the instructions on the wiki page.
from the command line:
sudo mn An additional advantage of using the VM image is that it doesn't mess with
your native OS install or damage it in any way.
As an alternative, if you are Linux-savvy, do not wish to use the VM 2. Native installation for Ubuntu and Debian 5 (NEW for pre-beta!)
image, and wish to take on the challenge of installing Mininet and its
dependencies from scratch, the requirements are described below. If you are running Ubuntu or Debian 5, you may be able to use our handy
install.sh script, which is in mininet/util.
WARNING: install.sh is a bit intrusive and may possibly damage your OS
and/or home directory. Although we hope it won't do anything completely
terrible, you may want to look at the script before you run it, and you
should make sure your system and home directory are backed up just in case!
To install ALL of the software which we use for OpenFlow tutorials, you may
use
$ mininet/util/install.sh
This takes about 20-30 minutes.
Alternately, you can install just the pieces you need.
We recommend the following steps, in order:
a) On Debian 5, first install a Mininet-compatible kernel:
$ mininet/util/install.sh -k
Reboot and run 'uname -r' to make sure you're running the new kernel.
b) Install mininet and its dependencies:
$ mininet/util/install.sh -n
c) Install OpenFlow 1.0 and associated useful software
$ mininet/util/install.sh -f
d) Install Open vSwitch and its kernel module
$ mininet/util/install.sh -vm
e) If you wish to install the version of NOX we use in the tutorial:
$ mininet/util/install.sh -x
Good luck! Some additional installation notes are provided below, for
the brave and/or Linux-savvy, or those who are trying to understand what
is installed and why.
p.s. Note that only one instance of Mininet is currently supported on a single
machine - that's one reason we recommend using a VM to run it.
--- ---
@@ -36,47 +76,94 @@ compile kernels, apply patches, configure networks, write code, etc.. If
this is unfamiliar territory, or if you run into trouble, we recommend this is unfamiliar territory, or if you run into trouble, we recommend
using one of our pre-built virtual machine images (see above.) using one of our pre-built virtual machine images (see above.)
If you wish to try to create a VM to run Mininet, you may also wish
to look at the Wiki page:
http://openflow.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes
0. Obtaining Mininet
If you're reading this, you've already done it, but the command to
download mininet is:
git clone git://openflow.org/mininet.git
1. Core Mininet installation 1. Core Mininet installation
The core Mininet installation requires gcc, make, python, The core Mininet installation requires gcc, make, python,
and setuptools. and setuptools. On Ubuntu and Debian you may install them with:
# aptitude install gcc make python setuptools
To install Mininet itself, with root privileges: To install Mininet itself, with root privileges:
# cd mininet
# make install # make install
This places the mininet package in /usr/lib/python-2.5/site-packages/, This places the mininet package in /usr/lib/python-*/site-packages/,
so that 'import mininet' will work, and installs the primary mn so that 'import mininet' will work, and installs the primary mn
script (mn) as well as its helper utility (mnexec.) script (mn) as well as its helper utility (mnexec.)
2. Script-based kernel and OpenFlow installation for Debian On Ubuntu and Debian, Mininet's dependencies and core files may also be
installed using mininet/util/install.sh -n
If you are running debian-stable, you may be able to use the 2. Installation script for Ubuntu/Debian Lenny
If you are running Ubuntu 10.04 or Debian Lenny, you may be able to use the
util/install.sh script to install a compatible Linux kernel as well as util/install.sh script to install a compatible Linux kernel as well as
other software including the OpenFlow reference implementation, the Open other software including the OpenFlow reference implementation, the Open
vSwitch switch implementation, and the NOX OpenFlow controller. Assuming vSwitch switch implementation, and the NOX OpenFlow controller.
the mininet source tree is installed in ~/mininet, the steps to run
install.sh are as follows: Many different installation options are possible by passing different
options to install.sh; install.sh -h lists them all.
Assuming the mininet source tree is installed in ~/mininet, the steps to run
install.sh to install EVERYTHING we use for OpenFlow tutorials are:
% cd % cd
% time ~/mininet/util/install.sh % time ~/mininet/util/install.sh # installs tons of stuff
% sudo reboot # to load new kernel % sudo reboot # to load new kernel
% ~/mininet/util/install.sh -c # to clean out unneeded kernel stuff % ~/mininet/util/install.sh -c # to clean out unneeded kernel stuff
If install.sh cannot be used for some reason, the kernel and This installs a lot of useful software, but it will take a while (30
OpenFlow software requirements are descibed in steps [3] and [4], minutes or more, depending on your network connection, computer, etc..)
Probably the minimal semi-useful configuration would be to install
Mininet itself, kernel support if necessary, and either the
reference OpenFlow switch or Open vSwitch. This could be installed
as follows:
% sudo ~/mininet/util/install.sh -knvm
Respectively, this installs kernel support, core mininet dependencies,
Open vSwitch, and the Open vSwitch kernel module. If a new kernel was
installed, then a reboot may be required.
If install.sh cannot be used for some reason (e.g. you're on Fedora
or some other Linux - please don't say CentOS) or if you don't want to
install all of these components (they're useful!), the kernel and
OpenFlow software requirements are described in steps [3] and [4],
which follow. which follow.
If you successfully used install.sh, proceed to step [5]. If you successfully used install.sh, congratulations! You're basically
done. Proceed to step [6] for additional advice.
3. Linux Kernel requirements 3. Linux Kernel requirements
Mininet requires a kernel built with network namespace support enabled, Mininet requires a kernel built with network namespace support enabled,
i.e. with CONFIG_NET_NS=Y i.e. with CONFIG_NET_NS=Y, such as the kernel shipped with
Ubuntu 10.04 LTS, currently 2.6.32. On Ubuntu 10.04, you should not need
to install or build a custom kernel, although 2.6.33+ is faster at
tearing down virtual ethernet pairs.
If your kernel doesn't support it, you will need to build and install a For Ubuntu and Debian, we provide a 2.6.33 kernel package which you may be
kernel that does! >= 2.6.33 works better, but may be harder to get able to install using "util/install.sh -k". Note our kernel package
working, depending on your Linux distribution. requires an ext2 or ext3 root file system, so it won't work if you have
a default Ubuntu install, which uses ext4.
If your kernel wasn't compiled with CONFIG_NET_NS=Y, you will need to
build and install a kernel that does! >= 2.6.33 works better, but may
be harder to get working, depending on your Linux distribution.
A script for building Debian packages for 2.6.33.1 is provided in A script for building Debian packages for 2.6.33.1 is provided in
mininet/util/kbuild. You may wish to read it, as it applies patches mininet/util/kbuild. You may wish to read it, as it applies patches
@@ -102,23 +189,19 @@ using one of our pre-built virtual machine images (see above.)
Mininet requires either the reference OpenFlow switch implementation Mininet requires either the reference OpenFlow switch implementation
(from openflowswitch.org) or Open vSwitch (openvswitch.org) to be (from openflowswitch.org) or Open vSwitch (openvswitch.org) to be
installed. "make test" requires the reference user and kernel space installed. "make test" requires the reference user space
implementations as well as Open vSwitch. Note the kernel implementation implementations as well as Open vSwitch. Note the reference kernel
is not currently included in OpenFlow 1.0. implementation is not currently included in OpenFlow 1.0.
To switch to the most recent OpenFlow 0.8.9 release branch (the most On Ubuntu and Debian, the install.sh script may be used with the '-f'
recent one with full NOX support and kernel datapath support) in your option to install the OpenFlow reference implementation, the '-v' option
OpenFlow git tree: to build Open vSwitch, and the '-m' option to install the Open vSwitch
kernel module into /lib/modules (note: you must build Open vSwitch first!)
git checkout -b release/0.8.9 remotes/origin/release/0.8.9
A patch to enable datapath.c to compile with recent kernels
is included in util/openflow-patches/datapath.patch.
Mininet will automatically load and remove kernel module dependencies Mininet will automatically load and remove kernel module dependencies
for supported switch types, using modprobe and rmmod - but these for supported switch types, using modprobe and rmmod - but these
modules must be in a location where modprobe can find them (i.e. modules must be in a location where modprobe can find them (e.g.
/lib/modules/...) something like /lib/modules/`uname -r`/kernel/drivers/net/)
The reference OpenFlow controller (controller(8)) only supports 16 The reference OpenFlow controller (controller(8)) only supports 16
switches by default! If you wish to run a network with more than 16 switches by default! If you wish to run a network with more than 16
@@ -128,6 +211,9 @@ using one of our pre-built virtual machine images (see above.)
5. Other software dependencies 5. Other software dependencies
On Ubuntu and Debian, other Mininet dependencies may be installed using
the '-n' option of the install.sh script.
To run the iperf test, you need to install iperf: To run the iperf test, you need to install iperf:
sudo aptitude/yum install iperf sudo aptitude/yum install iperf
@@ -141,8 +227,14 @@ using one of our pre-built virtual machine images (see above.)
Some examples may have additional requirements - consult the specific Some examples may have additional requirements - consult the specific
example file for details. example file for details.
The install.sh script has an '-x' option to install the version of
NOX from the OpenFlow tutorial.
6. Other notes and recommendations 6. Other notes and recommendations
If you did not install certain useful packages and you wish to later,
it may be possible to install them using install.sh.
Mininet should be run either on a machine with Mininet should be run either on a machine with
no other important processes, or on a virtual machine (recommended!) no other important processes, or on a virtual machine (recommended!)
@@ -151,3 +243,26 @@ using one of our pre-built virtual machine images (see above.)
Good luck! Good luck!
--- ---
Historical information on OpenFlow 0.8.9 and the reference kernel module:
The kernel reference implementation has been deprecated, but it may
be possible to get it work with Mininet.
To switch to the most recent OpenFlow 0.8.9 release branch (the most
recent one with full NOX support and kernel datapath support) in your
OpenFlow git tree:
git checkout -b release/0.8.9 remotes/origin/release/0.8.9
A patch to enable datapath.c to compile with recent kernels
is included in util/openflow-patches/datapath.patch.
In OpenFlow 1.0, switch port numbering starts at 1 (for better or for worse.)
To run with previous versions of OpenFlow, it may be necessary
to change SWITCH_PORT_BASE from 1 to 0 in node.py.
+31 -1
View File
@@ -55,7 +55,7 @@ TESTS = [ 'cli', 'build', 'pingall', 'pingpair', 'iperf', 'all', 'iperfudp',
'none' ] 'none' ]
ALTSPELLING = { 'pingall': 'pingAll', 'pingpair': 'pingPair', ALTSPELLING = { 'pingall': 'pingAll', 'pingpair': 'pingPair',
'iperfudp': 'iperfUdp', 'iperfUDP': 'iperfUdp' } 'iperfudp': 'iperfUdp', 'iperfUDP': 'iperfUdp', 'prefixlen': 'prefixLen' }
def buildTopo( topo ): def buildTopo( topo ):
"Create topology from string with format (object, arg1, arg2,...)." "Create topology from string with format (object, arg1, arg2,...)."
@@ -176,11 +176,25 @@ class MininetRunner( object ):
' controller]' ) ' controller]' )
opts.add_option( '--innamespace', action='store_true', opts.add_option( '--innamespace', action='store_true',
default=False, help='sw and ctrl in namespace?' ) default=False, help='sw and ctrl in namespace?' )
<<<<<<< HEAD:bin/mn
=======
opts.add_option( '--listenport', type='int', default=6634,
help='[base port for passive switch listening'
' controller]' )
opts.add_option( '--nolistenport', action='store_true',
default=False, help="don't use passive listening port")
>>>>>>> of1.0:bin/mn
opts.add_option( '--pre', type='string', default=None, opts.add_option( '--pre', type='string', default=None,
help='[CLI script to run before tests]' ) help='[CLI script to run before tests]' )
opts.add_option( '--post', type='string', default=None, opts.add_option( '--post', type='string', default=None,
help='[CLI script to run after tests]' ) help='[CLI script to run after tests]' )
<<<<<<< HEAD:bin/mn
=======
opts.add_option( '--prefixlen', type='int', default=8,
help='[prefix length (e.g. /8) for automatic '
'network configuration]' )
>>>>>>> of1.0:bin/mn
self.options, self.args = opts.parse_args() self.options, self.args = opts.parse_args()
def setup( self ): def setup( self ):
@@ -217,15 +231,31 @@ class MininetRunner( object ):
if self.validate: if self.validate:
self.validate( self.options ) self.validate( self.options )
<<<<<<< HEAD:bin/mn
controllerParams = ControllerParams( '10.0.0.0', 8 ) controllerParams = ControllerParams( '10.0.0.0', 8 )
=======
# We should clarify what this is actually for...
# It seems like it should be default values for the
# *data* network, so it may be misnamed.
controllerParams = ControllerParams( '10.0.0.0',
self.options.prefixlen)
>>>>>>> of1.0:bin/mn
inNamespace = self.options.innamespace inNamespace = self.options.innamespace
xterms = self.options.xterms xterms = self.options.xterms
mac = self.options.mac mac = self.options.mac
arp = self.options.arp arp = self.options.arp
listenPort = None
if not self.options.nolistenport:
listenPort = self.options.listenport
mn = Mininet( topo, switch, host, controller, controllerParams, mn = Mininet( topo, switch, host, controller, controllerParams,
inNamespace=inNamespace, inNamespace=inNamespace,
xterms=xterms, autoSetMacs=mac, xterms=xterms, autoSetMacs=mac,
<<<<<<< HEAD:bin/mn
autoStaticArp=arp ) autoStaticArp=arp )
=======
autoStaticArp=arp, listenPort=listenPort )
>>>>>>> of1.0:bin/mn
if self.options.pre: if self.options.pre:
CLI( mn, script=self.options.pre ) CLI( mn, script=self.options.pre )
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/python
"This example doesn't use OpenFlow, but attempts to run sshd in a namespace."
from mininet.node import Host
print "*** Creating nodes"
h1 = Host( 'h1' )
root = Host( 'root', inNamespace=False )
print "*** Creating links"
h1.linkTo( root )
print "*** Configuring nodes"
h1.setIP( h1.intfs[ 0 ], '10.0.0.1', 8 )
root.setIP( root.intfs[ 0 ], '10.0.0.2', 8 )
print "*** Creating banner file"
f = open( '/tmp/%s.banner' % h1.name, 'w' )
f.write( 'Welcome to %s at %s\n' % ( h1.name, h1.IP() ) )
f.close()
print "*** Running sshd"
h1.cmd( '/usr/sbin/sshd -o "Banner /tmp/%s.banner"' % h1.name )
print "*** You may now ssh into", h1.name, "at", h1.IP()
+1 -2
View File
@@ -448,8 +448,7 @@ class ConsoleApp( Frame ):
def assign( obj, **kwargs ): def assign( obj, **kwargs ):
"Set a bunch of fields in an object." "Set a bunch of fields in an object."
for name, value in kwargs.items(): obj.__dict__.update( kwargs )
setattr( obj, name, value )
class Object( object ): class Object( object ):
"Generic object you can stuff junk into." "Generic object you can stuff junk into."
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/python
"""
This example creates a multi-controller network from
semi-scratch; note a topo object could also be used and
would be passed into the Mininet() constructor.
"""
from mininet.net import Mininet
from mininet.node import Controller, OVSKernelSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel
Switch = OVSKernelSwitch
def addHost( net, N ):
"Create host hN and add to net."
name = 'h%d' % N
ip = '10.0.0.%d' % N
return net.addHost( name, ip=ip )
def multiControllerNet():
"Create a network with multiple controllers."
net = Mininet( controller=Controller, switch=Switch)
print "*** Creating controllers"
c1 = net.addController( 'c1', port=6633 )
c2 = net.addController( 'c2', port=6634 )
print "*** Creating switches"
s1 = net.addSwitch( 's1' )
s2 = net.addSwitch( 's2' )
print "*** Creating hosts"
hosts1 = [ addHost( net, n ) for n in 3, 4 ]
hosts2 = [ addHost( net, n ) for n in 5, 6 ]
print "*** Creating links"
for h in hosts1:
s1.linkTo( h )
for h in hosts2:
s2.linkTo( h )
s1.linkTo( s2 )
print "*** Starting network"
net.build()
c1.start()
c2.start()
s1.start( [ c1 ] )
s2.start( [ c2 ] )
print "*** Testing network"
net.pingAll()
print "*** Running CLI"
CLI( net )
print "*** Stopping network"
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' ) # for CLI output
multiControllerNet()
+16 -1
View File
@@ -272,6 +272,20 @@ class CLI( Cmd ):
error( 'error reading file %s\n' % args[ 0 ] ) error( 'error reading file %s\n' % args[ 0 ] )
self.inputFile = None self.inputFile = None
def do_dpctl( self, line ):
"Run dpctl command on all switches."
args = line.split()
if len(args) == 0:
error( 'usage: dpctl command [arg1] [arg2] ...\n' )
return
if not self.mn.listenPort:
error( "can't run dpctl w/no passive listening port\n")
return
for sw in self.mn.switches:
output( '*** ' + sw.name + ' ' + ('-' * 72) + '\n' )
output( sw.cmd( 'dpctl ' + ' '.join(args) +
' tcp:127.0.0.1:%i' % sw.listenPort ) )
def default( self, line ): def default( self, line ):
"""Called on an input line when the command prefix is not recognized. """Called on an input line when the command prefix is not recognized.
Overridden to run shell commands when a node is the first CLI argument. Overridden to run shell commands when a node is the first CLI argument.
@@ -314,7 +328,8 @@ class CLI( Cmd ):
while True: while True:
try: try:
bothPoller.poll() bothPoller.poll()
if self.inputFile: # XXX BL: this doesn't quite do what we want.
if False and self.inputFile:
key = self.inputFile.read( 1 ) key = self.inputFile.read( 1 )
if key is not '': if key is not '':
node.write(key) node.write(key)
+11 -9
View File
@@ -37,7 +37,7 @@ def moduleDeps( subtract=None, add=None ):
info( '*** Removing ' + mod + '\n' ) info( '*** Removing ' + mod + '\n' )
rmmodOutput = rmmod( mod ) rmmodOutput = rmmod( mod )
if rmmodOutput: if rmmodOutput:
error( 'Error removing ' + mod + '\n%s' % rmmodOutput ) error( 'Error removing ' + mod + ': "%s">\n' % rmmodOutput )
exit( 1 ) exit( 1 )
if mod in lsmod(): if mod in lsmod():
error( 'Failed to remove ' + mod + '; still there!\n' ) error( 'Failed to remove ' + mod + '; still there!\n' )
@@ -47,20 +47,22 @@ def moduleDeps( subtract=None, add=None ):
info( '*** Loading ' + mod + '\n' ) info( '*** Loading ' + mod + '\n' )
modprobeOutput = modprobe( mod ) modprobeOutput = modprobe( mod )
if modprobeOutput: if modprobeOutput:
error( 'Error inserting ' + mod + ';\n See INSTALL.\n%s' % error( 'Error inserting ' + mod +
modprobeOutput ) ' - is it installed and available via modprobe?\n' +
exit( 1 ) 'Error was: "%s"\n' % modprobeOutput )
if mod not in lsmod(): if mod not in lsmod():
error( 'Failed to insert ' + mod + '\n' ) error( 'Failed to insert ' + mod + ' - quitting.\n' )
exit( 1 ) exit( 1 )
else: else:
debug( '*** ' + mod + ' already loaded\n' ) debug( '*** ' + mod + ' already loaded\n' )
def pathCheck( *args ):
def pathCheck( *args, **kwargs ):
"Make sure each program in *args can be found in $PATH." "Make sure each program in *args can be found in $PATH."
moduleName = kwargs.get( 'moduleName', 'it' )
for arg in args: for arg in args:
if not quietRun( 'which ' + arg ): if not quietRun( 'which ' + arg ):
error( 'Cannot find required executable %s -' error( 'Cannot find required executable %s.\n' % arg +
' is it installed somewhere in your $PATH?\n(%s)\n' % 'Please make sure that %s is installed ' % moduleName +
( arg, environ[ 'PATH' ] ) ) 'and available in your $PATH:\n(%s)\n' % environ[ 'PATH' ] )
exit( 1 ) exit( 1 )
+20 -10
View File
@@ -94,7 +94,7 @@ from time import sleep
from mininet.cli import CLI 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, UserSwitch, KernelSwitch, Controller from mininet.node import Host, UserSwitch, OVSKernelSwitch, Controller
from mininet.node import ControllerParams from mininet.node import ControllerParams
from mininet.util import quietRun, fixLimits from mininet.util import quietRun, fixLimits
from mininet.util import createLink, macColonHex, ipStr, ipParse from mininet.util import createLink, macColonHex, ipStr, ipParse
@@ -103,12 +103,12 @@ from mininet.term import cleanUpScreens, makeTerms
class Mininet( object ): class Mininet( object ):
"Network emulation with hosts spawned in network namespaces." "Network emulation with hosts spawned in network namespaces."
def __init__( self, topo=None, switch=KernelSwitch, host=Host, def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
controller=Controller, controller=Controller,
cparams=ControllerParams( '10.0.0.0', 8 ), cparams=ControllerParams( '10.0.0.0', 8 ),
build=True, xterms=False, cleanup=False, build=True, xterms=False, cleanup=False,
inNamespace=False, inNamespace=False,
autoSetMacs=False, autoStaticArp=False ): autoSetMacs=False, autoStaticArp=False, listenPort=None ):
"""Create Mininet object. """Create Mininet object.
topo: Topo (topology) object or None topo: Topo (topology) object or None
switch: Switch class switch: Switch class
@@ -120,7 +120,9 @@ class Mininet( object ):
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? autoSetMacs: set MAC addrs from topo?
autoStaticArp: set all-pairs static MAC addrs?""" autoStaticArp: set all-pairs static MAC addrs?
listenPort: base listening port to open; will be incremented for
each additional switch in the net if inNamespace=False"""
self.switch = switch self.switch = switch
self.host = host self.host = host
self.controller = controller self.controller = controller
@@ -131,6 +133,7 @@ class Mininet( object ):
self.cleanup = cleanup self.cleanup = cleanup
self.autoSetMacs = autoSetMacs self.autoSetMacs = autoSetMacs
self.autoStaticArp = autoStaticArp self.autoStaticArp = autoStaticArp
self.listenPort = listenPort
self.hosts = [] self.hosts = []
self.switches = [] self.switches = []
@@ -162,25 +165,32 @@ class Mininet( object ):
"""Add switch. """Add switch.
name: name of switch to add name: name of switch to add
mac: default MAC address for kernel/OVS switch intf 0 mac: default MAC address for kernel/OVS switch intf 0
returns: added switch""" returns: added switch
side effect: increments the listenPort member variable."""
if self.switch == UserSwitch: if self.switch == UserSwitch:
sw = self.switch( name, defaultMAC=mac, defaultIP=ip, sw = self.switch( name, listenPort=self.listenPort,
inNamespace=self.inNamespace ) defaultMAC=mac, defaultIP=ip, inNamespace=self.inNamespace )
else: else:
sw = self.switch( name, defaultMAC=mac, defaultIP=ip, dp=self.dps, sw = self.switch( name, listenPort=self.listenPort,
defaultMAC=mac, defaultIP=ip, dp=self.dps,
inNamespace=self.inNamespace ) inNamespace=self.inNamespace )
if not self.inNamespace and self.listenPort:
self.listenPort += 1
self.dps += 1 self.dps += 1
self.switches.append( sw ) self.switches.append( sw )
self.nameToNode[ name ] = sw self.nameToNode[ name ] = sw
return sw return sw
def addController( self, name='c0', **kwargs ): def addController( self, name='c0', controller=None, **kwargs ):
"""Add controller. """Add controller.
controller: Controller class""" controller: Controller class"""
controller_new = self.controller( name, **kwargs ) if not controller:
controller = self.controller
controller_new = controller( name, **kwargs )
if controller_new: # allow controller-less setups if controller_new: # allow controller-less setups
self.controllers.append( controller_new ) self.controllers.append( controller_new )
self.nameToNode[ name ] = controller_new self.nameToNode[ name ] = controller_new
return controller_new
# Control network support: # Control network support:
# #
+32 -17
View File
@@ -200,7 +200,6 @@ class Node( object ):
"""Monitor and return the output of a command. """Monitor and return the output of a command.
Set self.waiting to False if command has completed. Set self.waiting to False if command has completed.
timeoutms: timeout in ms or None to wait indefinitely.""" timeoutms: timeout in ms or None to wait indefinitely."""
assert self.waiting
self.waitReadable( timeoutms ) self.waitReadable( timeoutms )
data = self.read( 1024 ) data = self.read( 1024 )
# Look for PID # Look for PID
@@ -434,9 +433,19 @@ class Switch( Node ):
portBase = SWITCH_PORT_BASE # 0 for OF < 1.0, 1 for OF >= 1.0 portBase = SWITCH_PORT_BASE # 0 for OF < 1.0, 1 for OF >= 1.0
def __init__( self, name, opts='', **kwargs): def __init__( self, name, opts='', listenPort=None, **kwargs):
Node.__init__( self, name, **kwargs ) Node.__init__( self, name, **kwargs )
self.opts = opts self.opts = opts
self.listenPort = listenPort
if self.listenPort:
self.opts += ' --listen=ptcp:%i ' % self.listenPort
def defaultIntf( self ):
"Return interface for HIGHEST port"
ports = self.intfs.keys()
if ports:
intf = self.intfs[ max( ports ) ]
return intf
def sendCmd( self, *cmd, **kwargs ): def sendCmd( self, *cmd, **kwargs ):
"""Send command to Node. """Send command to Node.
@@ -455,11 +464,14 @@ class UserSwitch( Switch ):
"""Init. """Init.
name: name for the switch""" name: name for the switch"""
Switch.__init__( self, name, **kwargs ) Switch.__init__( self, name, **kwargs )
pathCheck( 'ofdatapath', 'ofprotocol' ) pathCheck( 'ofdatapath', 'ofprotocol',
moduleName='the OpenFlow reference user switch (openflow.org)' )
@staticmethod @staticmethod
def setup(): def setup():
"Ensure any dependencies are loaded; if not, try to load them." "Ensure any dependencies are loaded; if not, try to load them."
if not os.path.exists( '/dev/net/tun' ):
moduleDeps( add=TUN ) moduleDeps( add=TUN )
def start( self, controllers ): def start( self, controllers ):
@@ -478,7 +490,7 @@ class UserSwitch( Switch ):
if self.inNamespace: if self.inNamespace:
intfs = intfs[ :-1 ] intfs = intfs[ :-1 ]
self.cmd( 'ofdatapath -i ' + ','.join( intfs ) + self.cmd( 'ofdatapath -i ' + ','.join( intfs ) +
' punix:/tmp/' + self.name + mac_str + ' punix:/tmp/' + self.name + mac_str + ' --no-slicing ' +
' 1> ' + ofdlog + ' 2> ' + ofdlog + ' &' ) ' 1> ' + ofdlog + ' 2> ' + ofdlog + ' &' )
self.cmd( 'ofprotocol unix:/tmp/' + self.name + self.cmd( 'ofprotocol unix:/tmp/' + self.name +
' tcp:%s:%d' % ( controller.IP(), controller.port ) + ' tcp:%s:%d' % ( controller.IP(), controller.port ) +
@@ -511,8 +523,10 @@ class KernelSwitch( Switch ):
@staticmethod @staticmethod
def setup(): def setup():
"Ensure any dependencies are loaded; if not, try to load them." "Ensure any dependencies are loaded; if not, try to load them."
moduleDeps( subtract = OVS_KMOD, add = OF_KMOD ) pathCheck( 'ofprotocol',
pathCheck( 'ofprotocol' ) moduleName='the OpenFlow reference kernel switch'
' (openflow.org) (NOTE: not available in OpenFlow 1.0!)' )
moduleDeps( subtract=OVS_KMOD, add=OF_KMOD )
def start( self, controllers ): def start( self, controllers ):
"Start up reference kernel datapath." "Start up reference kernel datapath."
@@ -559,14 +573,15 @@ class OVSKernelSwitch( Switch ):
self.intf = self.dp self.intf = self.dp
if self.inNamespace: if self.inNamespace:
error( "OVSKernelSwitch currently only works" error( "OVSKernelSwitch currently only works"
" in the root namespace." ) " in the root namespace.\n" )
exit( 1 ) exit( 1 )
@staticmethod @staticmethod
def setup(): def setup():
"Ensure any dependencies are loaded; if not, try to load them." "Ensure any dependencies are loaded; if not, try to load them."
moduleDeps( subtract = OF_KMOD, add = OVS_KMOD ) pathCheck( 'ovs-dpctl', 'ovs-openflowd',
pathCheck( 'ovs-dpctl', 'ovs-openflowd' ) moduleName='Open vSwitch (openvswitch.org)')
moduleDeps( subtract=OF_KMOD, add=OVS_KMOD )
def start( self, controllers ): def start( self, controllers ):
"Start up kernel datapath." "Start up kernel datapath."
@@ -607,10 +622,10 @@ class Controller( Node ):
"""A Controller is a Node that is running (or has execed?) an """A Controller is a Node that is running (or has execed?) an
OpenFlow controller.""" OpenFlow controller."""
def __init__( self, name, inNamespace=False, controller='controller', def __init__( self, name, inNamespace=False, command='controller',
cargs='-v ptcp:', cdir=None, defaultIP="127.0.0.1", cargs='-v ptcp:%d', cdir=None, defaultIP="127.0.0.1",
port=6633 ): port=6633 ):
self.controller = controller self.command = command
self.cargs = cargs self.cargs = cargs
self.cdir = cdir self.cdir = cdir
self.port = port self.port = port
@@ -620,17 +635,17 @@ class Controller( Node ):
def start( self ): def start( self ):
"""Start <controller> <args> on controller. """Start <controller> <args> on controller.
Log to /tmp/cN.log""" Log to /tmp/cN.log"""
pathCheck( self.controller ) pathCheck( self.command )
cout = '/tmp/' + self.name + '.log' cout = '/tmp/' + self.name + '.log'
if self.cdir is not None: if self.cdir is not None:
self.cmd( 'cd ' + self.cdir ) self.cmd( 'cd ' + self.cdir )
self.cmd( self.controller + ' ' + self.cargs + self.cmd( self.command + ' ' + self.cargs % self.port +
' 1>' + cout + ' 2>' + cout + '&' ) ' 1>' + cout + ' 2>' + cout + '&' )
self.execed = False self.execed = False
def stop( self ): def stop( self ):
"Stop controller." "Stop controller."
self.cmd( 'kill %' + self.controller ) self.cmd( 'kill %' + self.command )
self.terminate() self.terminate()
def IP( self, intf=None ): def IP( self, intf=None ):
@@ -668,8 +683,8 @@ class NOX( Controller ):
noxCoreDir = os.environ[ 'NOX_CORE_DIR' ] noxCoreDir = os.environ[ 'NOX_CORE_DIR' ]
Controller.__init__( self, name, Controller.__init__( self, name,
controller=noxCoreDir + '/nox_core', command=noxCoreDir + '/nox_core',
cargs='--libdir=/usr/local/lib -v -i ptcp: ' + cargs='--libdir=/usr/local/lib -v -i ptcp:%s ' % self.port +
' '.join( noxArgs ), ' '.join( noxArgs ),
cdir=noxCoreDir, **kwargs ) cdir=noxCoreDir, **kwargs )
+130 -14
View File
@@ -9,19 +9,38 @@ set -e
set -o nounset set -o nounset
# Location of CONFIG_NET_NS-enabled kernel(s) # Location of CONFIG_NET_NS-enabled kernel(s)
KERNEL_LOC=http://www.stanford.edu/~brandonh KERNEL_LOC=http://www.openflow.org/downloads/mininet
test -e /etc/debian_version && DIST="Debian"
grep Ubuntu /etc/lsb-release &> /dev/null && DIST="Ubuntu"
# Kernel params # Kernel params
# These kernels have been tried: # These kernels have been tried:
<<<<<<< HEAD:util/install.sh
KERNEL_NAME=2.6.33.1-mininet KERNEL_NAME=2.6.33.1-mininet
#KERNEL_NAME=`uname -r` #KERNEL_NAME=`uname -r`
KERNEL_HEADERS=linux-headers-${KERNEL_NAME}_${KERNEL_NAME}-10.00.Custom_i386.deb KERNEL_HEADERS=linux-headers-${KERNEL_NAME}_${KERNEL_NAME}-10.00.Custom_i386.deb
KERNEL_IMAGE=linux-image-${KERNEL_NAME}_${KERNEL_NAME}-10.00.Custom_i386.deb KERNEL_IMAGE=linux-image-${KERNEL_NAME}_${KERNEL_NAME}-10.00.Custom_i386.deb
=======
if [ "$DIST" = "Debian" ]; then
KERNEL_NAME=2.6.33.1-mininet
KERNEL_HEADERS=linux-headers-${KERNEL_NAME}_${KERNEL_NAME}-10.00.Custom_i386.deb
KERNEL_IMAGE=linux-image-${KERNEL_NAME}_${KERNEL_NAME}-10.00.Custom_i386.deb
elif [ "$DIST" = "Ubuntu" ]; then
KERNEL_NAME=`uname -r`
KERNEL_HEADERS=linux-headers-${KERNEL_NAME}
else
echo "Install.sh currently only supports Ubuntu and Debian."
exit 1
fi
echo "Detected Linux distribution: $DIST"
>>>>>>> of1.0:util/install.sh
# Kernel Deb pkg to be removed: # Kernel Deb pkg to be removed:
KERNEL_IMAGE_OLD=linux-image-2.6.26-2-686 KERNEL_IMAGE_OLD=linux-image-2.6.26-2-686
DRIVERS_DIR=/lib/modules/${KERNEL_NAME}/kernel/drivers DRIVERS_DIR=/lib/modules/${KERNEL_NAME}/kernel/drivers/net
#OVS_RELEASE=openvswitch-1.0.1 #OVS_RELEASE=openvswitch-1.0.1
OVS_RELEASE=openvswitch # release 1.0.1 doesn't work with veth pairs. OVS_RELEASE=openvswitch # release 1.0.1 doesn't work with veth pairs.
@@ -29,12 +48,14 @@ OVS_DIR=~/$OVS_RELEASE
OVS_KMOD=openvswitch_mod.ko OVS_KMOD=openvswitch_mod.ko
function kernel { function kernel {
echo "Install new kernel..." echo "Install Mininet-compatible kernel"
sudo apt-get update sudo apt-get update
if [ "$DIST" = "Debian" ]; then
# The easy approach: download pre-built linux-image and linux-headers packages: # The easy approach: download pre-built linux-image and linux-headers packages:
wget $KERNEL_LOC/$KERNEL_HEADERS wget -c $KERNEL_LOC/$KERNEL_HEADERS
wget $KERNEL_LOC/$KERNEL_IMAGE wget -c $KERNEL_LOC/$KERNEL_IMAGE
#Install custom linux headers and image: #Install custom linux headers and image:
sudo dpkg -i $KERNEL_IMAGE $KERNEL_HEADERS sudo dpkg -i $KERNEL_IMAGE $KERNEL_HEADERS
@@ -51,6 +72,8 @@ function kernel {
sudo update-grub sudo update-grub
# The default should be the new kernel. Otherwise, you may need to modify /boot/grub/menu.lst to set the default to the entry corresponding to the kernel you just installed. # The default should be the new kernel. Otherwise, you may need to modify /boot/grub/menu.lst to set the default to the entry corresponding to the kernel you just installed.
fi
} }
function kernel_clean { function kernel_clean {
@@ -65,14 +88,20 @@ function kernel_clean {
# Install Mininet deps # Install Mininet deps
function mn_deps { function mn_deps {
#Install dependencies: echo "Installing Mininet dependencies"
sudo apt-get install -y screen psmisc xterm ssh iperf iproute python-setuptools sudo aptitude install -y gcc make screen psmisc xterm ssh iperf iproute \
python-setuptools python-networkx
#Add sysctl parameters as noted in the INSTALL file to increase kernel limits to support larger setups: #Add sysctl parameters as noted in the INSTALL file to increase kernel limits to support larger setups:
sudo su -c "cat /home/mininet/mininet/util/sysctl_addon >> /etc/sysctl.conf" sudo su -c "cat $HOME/mininet/util/sysctl_addon >> /etc/sysctl.conf"
#Load new sysctl settings: #Load new sysctl settings:
sudo sysctl -p sudo sysctl -p
echo "Installing Mininet core"
pushd ~/mininet
sudo make install
popd
} }
# The following will cause a full OF install, covering: # The following will cause a full OF install, covering:
@@ -109,7 +138,12 @@ function of {
sudo apt-get remove -y avahi-daemon sudo apt-get remove -y avahi-daemon
# Disable IPv6. Add to /etc/modprobe.d/blacklist: # Disable IPv6. Add to /etc/modprobe.d/blacklist:
sudo sh -c "echo -e 'blacklist net-pf-10\nblacklist ipv6' >> /etc/modprobe.d/blacklist" if [ "$DIST" = "Ubuntu" ]; then
BLACKLIST=/etc/modprobe.d/blacklist.conf
else
BLACKLIST=/etc/modprobe.d/blacklist
fi
sudo sh -c "echo 'blacklist net-pf-10\nblacklist ipv6' >> $BLACKLIST"
} }
# Install OpenVSwitch # Install OpenVSwitch
@@ -117,13 +151,23 @@ function of {
function ovs { function ovs {
echo "Installing OpenVSwitch..." echo "Installing OpenVSwitch..."
if [ "$DIST" = "Debian" ]; then
sudo aptitude -y install pkg-config gcc make git-core python-dev libssl-dev
#Install Autoconf 2.63+ backport from Debian Backports repo: #Install Autoconf 2.63+ backport from Debian Backports repo:
#Instructions from http://backports.org/dokuwiki/doku.php?id=instructions #Instructions from http://backports.org/dokuwiki/doku.php?id=instructions
sudo su -c "echo 'deb http://www.backports.org/debian lenny-backports main contrib non-free' >> /etc/apt/sources.list" sudo su -c "echo 'deb http://www.backports.org/debian lenny-backports main contrib non-free' >> /etc/apt/sources.list"
sudo apt-get update sudo apt-get update
sudo apt-get -y --force-yes install debian-backports-keyring sudo apt-get -y --force-yes install debian-backports-keyring
sudo apt-get -y --force-yes -t lenny-backports install autoconf sudo apt-get -y --force-yes -t lenny-backports install autoconf
fi
<<<<<<< HEAD:util/install.sh
=======
if [ "$DIST" = "Ubuntu" ]; then
sudo apt-get -y install $KERNEL_HEADERS
fi
>>>>>>> of1.0:util/install.sh
#Install OVS from release #Install OVS from release
cd ~/ cd ~/
#wget http://openvswitch.org/releases/${OVS_RELEASE}.tar.gz #wget http://openvswitch.org/releases/${OVS_RELEASE}.tar.gz
@@ -132,7 +176,17 @@ function ovs {
git clone git://openvswitch.org/openvswitch git clone git://openvswitch.org/openvswitch
cd $OVS_RELEASE cd $OVS_RELEASE
./boot.sh ./boot.sh
<<<<<<< HEAD:util/install.sh
./configure --with-l26=/lib/modules/${KERNEL_NAME}/build ./configure --with-l26=/lib/modules/${KERNEL_NAME}/build
=======
BUILDDIR=/lib/modules/${KERNEL_NAME}/build
if [ ! -e $BUILDDIR ]; then
echo "Creating build directory $BUILDDIR"
sudo mkdir -p $BUILDDIR
fi
opts="--with-l26=$BUILDDIR"
./configure $opts
>>>>>>> of1.0:util/install.sh
make make
sudo make install sudo make install
} }
@@ -142,8 +196,14 @@ function nox {
echo "Installing NOX w/tutorial files..." echo "Installing NOX w/tutorial files..."
#Install NOX deps: #Install NOX deps:
sudo apt-get -y install autoconf automake g++ libtool python python-twisted swig libboost1.35-dev libxerces-c2-dev libssl-dev make sudo apt-get -y install autoconf automake g++ libtool python python-twisted swig libxerces-c2-dev libssl-dev make
if [ "$DIST" = "Debian" ]; then
sudo apt-get -y install libboost1.35-dev
elif [ "$DIST" = "Ubuntu" ]; then
sudo apt-get -y install python-dev libboost-dev
sudo apt-get -y install libboost-filesystem-dev
sudo apt-get -y install libboost-test-dev
fi
#Install NOX optional deps: #Install NOX optional deps:
sudo apt-get install -y libsqlite3-dev python-simplejson sudo apt-get install -y libsqlite3-dev python-simplejson
@@ -154,8 +214,15 @@ function nox {
# With later autoconf versions this doesn't quite work: # With later autoconf versions this doesn't quite work:
./boot.sh --apps-core || true ./boot.sh --apps-core || true
<<<<<<< HEAD:util/install.sh
# So use this instead: # So use this instead:
autoreconf --install --force autoreconf --install --force
=======
if [ "$DIST" = "Debian" ]; then
# So use this instead:
autoreconf --install --force
fi
>>>>>>> of1.0:util/install.sh
mkdir build mkdir build
cd build cd build
../configure --with-python=yes ../configure --with-python=yes
@@ -194,7 +261,11 @@ function cbench {
git clone git://www.openflow.org/oflops.git git clone git://www.openflow.org/oflops.git
cd oflops cd oflops
sh boot.sh sh boot.sh
<<<<<<< HEAD:util/install.sh
./configure --with-openflow-src-dir=/home/mininet/openflow ./configure --with-openflow-src-dir=/home/mininet/openflow
=======
./configure --with-openflow-src-dir=$HOME/openflow
>>>>>>> of1.0:util/install.sh
make make
sudo make install || true # make install fails; force past this sudo make install || true # make install fails; force past this
} }
@@ -221,12 +292,23 @@ function other {
git config --global color.branch auto git config --global color.branch auto
#Reduce boot screen opt-out delay. Modify timeout in /boot/grub/menu.lst to 1: #Reduce boot screen opt-out delay. Modify timeout in /boot/grub/menu.lst to 1:
<<<<<<< HEAD:util/install.sh
sudo sed -i -e 's/^timeout.*$/timeout 1/' /boot/grub/menu.lst sudo sed -i -e 's/^timeout.*$/timeout 1/' /boot/grub/menu.lst
# Clean unneeded debs: # Clean unneeded debs:
rm -f ~/linux-headers-* ~/linux-image-* rm -f ~/linux-headers-* ~/linux-image-*
} }
=======
if [ "$DIST" = "Debian" ]; then
sudo sed -i -e 's/^timeout.*$/timeout 1/' /boot/grub/menu.lst
fi
# Clean unneeded debs:
rm -f ~/linux-headers-* ~/linux-image-*
}
>>>>>>> of1.0:util/install.sh
# Script to copy built OVS kernel module to where modprobe will # Script to copy built OVS kernel module to where modprobe will
# find them automatically. Removes the need to keep an environment variable # find them automatically. Removes the need to keep an environment variable
# for insmod usage, and works nicely with multiple kernel versions. # for insmod usage, and works nicely with multiple kernel versions.
@@ -243,7 +325,10 @@ function modprobe {
function all { function all {
echo "Running all commands..." echo "Running all commands..."
if [ "$DIST" != "Ubuntu" ]; then
# Ubuntu ships with Mininet-compatible kernel
kernel kernel
fi
mn_deps mn_deps
of of
ovs ovs
@@ -264,27 +349,58 @@ function vm_clean {
sudo rm -rf openvswitch*.tar.gz sudo rm -rf openvswitch*.tar.gz
# Remove sensistive files # Remove sensistive files
<<<<<<< HEAD:util/install.sh
history -c history -c
rm ~/.bash_history # history -c doesn't seem to work for some reason rm ~/.bash_history # history -c doesn't seem to work for some reason
=======
history -c # note this won't work if you have multiple bash sessions
rm -f ~/.bash_history # need to clear in memory and remove on disk
>>>>>>> of1.0:util/install.sh
rm -f ~/.ssh/id_rsa* ~/.ssh/known_hosts rm -f ~/.ssh/id_rsa* ~/.ssh/known_hosts
sudo rm ~/.ssh/authorized_keys2 sudo rm -f ~/.ssh/authorized_keys2
# Remove Mininet files # Remove Mininet files
#sudo rm -f /lib/modules/python2.5/site-packages/mininet* #sudo rm -f /lib/modules/python2.5/site-packages/mininet*
#sudo rm -f /usr/bin/mnexec #sudo rm -f /usr/bin/mnexec
# Clear optional dev script for SSH keychain load on boot # Clear optional dev script for SSH keychain load on boot
<<<<<<< HEAD:util/install.sh
rm ~/.bash_profile rm ~/.bash_profile
=======
rm -f ~/.bash_profile
>>>>>>> of1.0:util/install.sh
# Clear git changes # Clear git changes
git config --global user.name "None" git config --global user.name "None"
git config --global user.email "None" git config --global user.email "None"
#sudo rm -rf ~/mininet # Remove mininet install script
rm -f install-mininet.sh
} }
function usage { function usage {
printf "Usage: %s: [-acdfhkmntvxy] args\n" $(basename $0) >&2 printf 'Usage: %s [-acdfhkmntvxy]\n\n' $(basename $0) >&2
printf 'This install script attempts to install useful packages\n' >&2
printf 'for Mininet. It should (hopefully) work on Ubuntu 10.04 and\n' >&2
printf 'Debian 5.0 (Lenny). If you run into trouble, try\n' >&2
printf 'installing one thing at a time, and looking at the \n' >&2
printf 'specific installation function in this script.\n\n' >&2
printf 'options:\n' >&2
printf -- ' -a: (default) install (A)ll packages - good luck!\n' >&2
printf -- ' -c: (C)lean up after kernel install\n' >&2
printf -- ' -d: (D)elete some sensitive files from a VM image\n' >&2
printf -- ' -f: install open(F)low\n' >&2
printf -- ' -h: print this (H)elp message\n' >&2
printf -- ' -k: install new (K)ernel\n' >&2
printf -- ' -m: install Open vSwitch kernel (M)odule\n' >&2
printf -- ' -n: install mini(N)et dependencies + core files\n' >&2
printf -- ' -t: install o(T)her stuff\n' >&2
printf -- ' -v: install open (V)switch\n' >&2
printf -- ' -x: install NO(X) OpenFlow controller\n' >&2
printf -- ' -y: install (A)ll packages\n' >&2
exit 2 exit 2
} }