From 32b122bf42050ee3090e7c824c67266a4cb415fe Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Wed, 4 Aug 2010 21:56:04 -0700 Subject: [PATCH 01/72] Update VM install for 1.0 Remove all OpenFlow Ref kmod stuff. --- util/install.sh | 116 +++++++++++++++----------------------- util/ovs-fix-2.6.33.patch | 51 ----------------- 2 files changed, 45 insertions(+), 122 deletions(-) delete mode 100644 util/ovs-fix-2.6.33.patch diff --git a/util/install.sh b/util/install.sh index 1328631..416c217 100755 --- a/util/install.sh +++ b/util/install.sh @@ -13,9 +13,7 @@ KERNEL_LOC=http://www.stanford.edu/~brandonh # Kernel params # These kernels have been tried: -#KERNEL_NAME=2.6.29.6-custom -#KERNEL_NAME=2.6.33-custom -KERNEL_NAME=2.6.33.1-custom +KERNEL_NAME=2.6.33.1-mininet #KERNEL_NAME=`uname -r` 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 @@ -25,12 +23,9 @@ KERNEL_IMAGE_OLD=linux-image-2.6.26-2-686 DRIVERS_DIR=/lib/modules/${KERNEL_NAME}/kernel/drivers -OVS_RELEASE=openvswitch-0.99.2 -#OVS_RELEASE=openvswitch +OVS_RELEASE=openvswitch-1.0.1 OVS_DIR=~/$OVS_RELEASE OVS_KMOD=openvswitch_mod.ko -OF_DIR=~/openflow -OF_KMOD=ofdatapath.ko function kernel { echo "Install new kernel..." @@ -81,7 +76,6 @@ function mn_deps { # The following will cause a full OF install, covering: # -user switch -# -kernel switch # -dissector # The instructions below are an abbreviated version from # http://www.openflowswitch.org/wk/index.php/Debian_Install @@ -93,15 +87,10 @@ function of { sudo apt-get install -y git-core automake m4 pkg-config libtool make libc6-dev autoconf autotools-dev gcc git clone git://openflowswitch.org/openflow.git cd ~/openflow - git fetch - sudo regress/scripts/install_deps.pl # Resume the install: - #git checkout -b release/0.8.9 origin/release/0.8.9 - # Use temp 0.8.9 branch that compiles: - git checkout -b devel/brandonh/nlfix origin/devel/brandonh/nlfix ./boot.sh - ./configure --with-l26=/lib/modules/${KERNEL_NAME} + ./configure make sudo make install @@ -134,11 +123,6 @@ function ovs { sudo apt-get -y --force-yes install debian-backports-keyring sudo apt-get -y --force-yes -t lenny-backports install autoconf - #Install OVS from git - #git clone git://openvswitch.org/openvswitch - #cd openvswitch - #./boot.sh - #Install OVS from release cd ~/ wget http://openvswitch.org/releases/${OVS_RELEASE}.tar.gz @@ -150,9 +134,9 @@ function ovs { sudo make install } -# Install NOX +# Install NOX with tutorial files function nox { - echo "Install NOX..." + echo "Installing NOX w/tutorial files..." #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 @@ -162,13 +146,11 @@ function nox { #Install NOX: cd ~/ - #git clone git://noxrepo.org/noxcore - # Temporary tutorial repo git clone git://openflowswitch.org/nox-tutorial noxcore cd noxcore # With later autoconf versions this doesn't quite work: - ./boot.sh || true + ./boot.sh --apps-core || true # So use this instead: autoreconf --install --force mkdir build @@ -185,6 +167,35 @@ function nox { #./nox_core -v -i ptcp: } +# Install OFtest +function oftest { + echo "Installing oftest..." + + #Install deps: + sudo apt-get install -y tcpdump python-scapy + + #Install oftest: + cd ~/ + git clone git://openflow.org/oftest + cd oftest + cd tools/munger + sudo make install +} + +# Install cbench +function cbench { + echo "Installing cbench..." + + sudo apt-get install -y libsnmp-dev + cd ~/ + git clone git://www.openflow.org/oflops.git + cd oflops + sh boot.sh + ./configure --with-openflow-src-dir=/home/mininet/openflow + make + sudo make install || true # make install fails; force past this +} + function other { echo "Doing other setup tasks..." @@ -208,60 +219,22 @@ function other { #Reduce boot screen opt-out delay. Modify timeout in /boot/grub/menu.lst to 1: sudo sed -i -e 's/^timeout.*$/timeout 1/' /boot/grub/menu.lst + + # Clean unneeded debs: + rm -f ~/linux-headers-* ~/linux-image-* } -function of_33 { - echo "Installing OpenFlow..." - cd ~/ - cd openflow - ./configure --with-l26=/lib/modules/${KERNEL_NAME} - make - sudo make install -} - -# OVS v0.99.2 does not build on 2.6.33, and the master branch of OVS includes -# patches for OF1.0 support. It doesn't look like there's a supported branch -# for v0.99, so the script below applies a patch for this. -# Since the patch is in a makefile, we'll have to steal the makefile builder, -# boot.sh, from the OVS git repo. -function ovs_33 { - echo "Installing OpenVSwitch..." - cd ~/ - git clone git://openvswitch.org/openvswitch - cp openvswitch/boot.sh $OVS_RELEASE - rm -rf openvswitch - cd ~/$OVS_RELEASE - git apply ~/mininet/util/ovs-fix-2.6.33.patch - ./boot.sh - ./configure --with-l26=/lib/modules/${KERNEL_NAME}/build - make - sudo make install -} - -function linux_33 { - kernel - of_33 - ovs_33 - modprobe - - # Clean unneeded debs: - rm -f ~/linux-headers-* ~/linux-image-* -} - -# Script to copy built OVS and OF kernel modules 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 -# for each, and works nicely with multiple kernel versions. +# for insmod usage, and works nicely with multiple kernel versions. # -# The downside is that after each recompilation of OVS or OF you'll need to +# The downside is that after each recompilation of OVS you'll need to # re-run this script. If you're using only one kernel version, then it may be # a good idea to use a symbolic link in place of the copy below. function modprobe { echo "Setting up modprobe for OVS kmod..." + sudo cp $OVS_DIR/datapath/linux-2.6/$OVS_KMOD $DRIVERS_DIR - - echo "Setting up modprobe for OF kmod..." - sudo cp $OF_DIR/datapath/linux-2.6/$OF_KMOD $DRIVERS_DIR - sudo depmod -a ${KERNEL_NAME} } @@ -273,6 +246,8 @@ function all { ovs modprobe nox + oftest + cbench other echo "Please reboot, then run ./mininet/util/install.sh -c to remove unneeded packages." echo "Enjoy Mininet!" @@ -310,7 +285,7 @@ if [ $# -eq 0 ] then all else - while getopts 'acdfhkmntvxy' OPTION + while getopts 'acdfhkmntvx' OPTION do case $OPTION in a) all;; @@ -324,7 +299,6 @@ else t) other;; v) ovs;; x) nox;; - y) linux_33;; ?) usage;; esac done diff --git a/util/ovs-fix-2.6.33.patch b/util/ovs-fix-2.6.33.patch deleted file mode 100644 index ee75363..0000000 --- a/util/ovs-fix-2.6.33.patch +++ /dev/null @@ -1,51 +0,0 @@ ->From 0ccd7844bbe9f6014d162c573e796c8c6f3f707b Mon Sep 17 00:00:00 2001 -From: Ben Pfaff -Date: Tue, 23 Mar 2010 09:27:08 -0700 -Subject: [PATCH] datapath: Support 2.6.33 kernel layout in build system. - -The 2.6.33 kernel moves generated header files to include/generated, so -we need to look for autoconf.h there. - -Reported-by: Brandon Heller ---- - acinclude.m4 | 5 +++-- - datapath/linux-2.6/Makefile.main.in | 7 +++++-- - 2 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/acinclude.m4 b/acinclude.m4 -index e38676f..abbc57e 100644 ---- a/acinclude.m4 -+++ b/acinclude.m4 -@@ -70,8 +70,9 @@ AC_DEFUN([OVS_CHECK_LINUX26], [ - AC_ERROR([Linux kernel in build tree $KBUILD26 (source tree $KSRC26) is not version 2.6]) - fi - fi -- if ! test -e "$KBUILD26"/include/linux/version.h || \ -- ! test -e "$KBUILD26"/include/linux/autoconf.h; then -+ if test ! -e "$KBUILD26"/include/linux/version.h || \ -+ (test ! -e "$KBUILD26"/include/linux/autoconf.h && \ -+ test ! -e "$KBUILD26"/include/generated/autoconf.h); then - AC_MSG_ERROR([Linux kernel source in $KBUILD26 is not configured]) - fi - OVS_CHECK_LINUX26_COMPAT -diff --git a/datapath/linux-2.6/Makefile.main.in b/datapath/linux-2.6/Makefile.main.in -index fd231e6..cb2a042 100644 ---- a/datapath/linux-2.6/Makefile.main.in -+++ b/datapath/linux-2.6/Makefile.main.in -@@ -42,9 +42,12 @@ ifeq (,$(wildcard $(VERSION_FILE))) - $(error Linux kernel source not configured - missing version.h) - endif - --CONFIG_FILE := $(KSRC)/include/linux/autoconf.h -+CONFIG_FILE := $(KSRC)/include/generated/autoconf.h - ifeq (,$(wildcard $(CONFIG_FILE))) -- $(error Linux kernel source not configured - missing autoconf.h) -+ CONFIG_FILE := $(KSRC)/include/linux/autoconf.h -+ ifeq (,$(wildcard $(CONFIG_FILE))) -+ $(error Linux kernel source not configured - missing autoconf.h) -+ endif - endif - - default: --- -1.6.6.1 From 6aa7f3493bcb7fed959436b8e660362e3c9ed3e1 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Thu, 5 Aug 2010 16:56:50 -0700 Subject: [PATCH 02/72] Add missing dep for cbench --- util/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/install.sh b/util/install.sh index 416c217..7694baf 100755 --- a/util/install.sh +++ b/util/install.sh @@ -186,7 +186,7 @@ function oftest { function cbench { echo "Installing cbench..." - sudo apt-get install -y libsnmp-dev + sudo apt-get install -y libsnmp-dev libpcap-dev cd ~/ git clone git://www.openflow.org/oflops.git cd oflops From a434c3d1b6e5bee5f17463b805cf655ee699b152 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Fri, 6 Aug 2010 00:36:39 -0700 Subject: [PATCH 03/72] vm: Use OVS git release OVS1.0.1 does not work with veth pairs. --- util/install.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/util/install.sh b/util/install.sh index 7694baf..957f67d 100755 --- a/util/install.sh +++ b/util/install.sh @@ -23,7 +23,8 @@ KERNEL_IMAGE_OLD=linux-image-2.6.26-2-686 DRIVERS_DIR=/lib/modules/${KERNEL_NAME}/kernel/drivers -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_DIR=~/$OVS_RELEASE OVS_KMOD=openvswitch_mod.ko @@ -125,8 +126,10 @@ function ovs { #Install OVS from release cd ~/ - wget http://openvswitch.org/releases/${OVS_RELEASE}.tar.gz - tar xzf ${OVS_RELEASE}.tar.gz + #wget http://openvswitch.org/releases/${OVS_RELEASE}.tar.gz + #tar xzf ${OVS_RELEASE}.tar.gz + #cd $OVS_RELEASE + git clone git://openvswitch.org/openvswitch cd $OVS_RELEASE ./configure --with-l26=/lib/modules/${KERNEL_NAME}/build From cd19cf520f4c650f88cd86f4e45ab52dbc57548d Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Fri, 6 Aug 2010 00:44:29 -0700 Subject: [PATCH 04/72] vm: Forgot to run boot.sh --- util/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/install.sh b/util/install.sh index 957f67d..bd060e9 100755 --- a/util/install.sh +++ b/util/install.sh @@ -131,7 +131,7 @@ function ovs { #cd $OVS_RELEASE git clone git://openvswitch.org/openvswitch cd $OVS_RELEASE - + ./boot.sh ./configure --with-l26=/lib/modules/${KERNEL_NAME}/build make sudo make install From 72ddde869cc4701601cca5abb130851bf0728ce4 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Fri, 6 Aug 2010 01:15:33 -0700 Subject: [PATCH 05/72] vm: Remove SSH keychain load-on-boot script --- util/install.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/install.sh b/util/install.sh index bd060e9..dd84f84 100755 --- a/util/install.sh +++ b/util/install.sh @@ -265,6 +265,7 @@ function vm_clean { # Remove sensistive files history -c + rm ~/.bash_history # history -c doesn't seem to work for some reason rm -f ~/.ssh/id_rsa* ~/.ssh/known_hosts sudo rm ~/.ssh/authorized_keys2 @@ -272,6 +273,9 @@ function vm_clean { #sudo rm -f /lib/modules/python2.5/site-packages/mininet* #sudo rm -f /usr/bin/mnexec + # Clear optional dev script for SSH keychain load on boot + rm ~/.bash_profile + # Clear git changes git config --global user.name "None" git config --global user.email "None" From 81d27b3c5619d5564ad49d0d0bdaea878f97917c Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Fri, 6 Aug 2010 10:34:17 -0700 Subject: [PATCH 06/72] Fix --mac breakage The OVS interface for this moved to ovs-openflowd. This functionality was never there for the user-space switch. Now it's in. --- mininet/node.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index 7609318..05f1921 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -433,11 +433,15 @@ class UserSwitch( Switch ): ofdlog = '/tmp/' + self.name + '-ofd.log' ofplog = '/tmp/' + self.name + '-ofp.log' self.cmd( 'ifconfig lo up' ) + mac_str = '' + if self.defaultMAC: + # ofdatapath expects a string of hex digits with no colons. + mac_str = ' -d ' + ''.join( self.defaultMAC.split( ':' ) ) intfs = sorted( self.intfs.values() ) if self.inNamespace: intfs = intfs[ :-1 ] self.cmd( 'ofdatapath -i ' + ','.join( intfs ) + - ' punix:/tmp/' + self.name + + ' punix:/tmp/' + self.name + mac_str + ' 1> ' + ofdlog + ' 2> ' + ofdlog + ' &' ) self.cmd( 'ofprotocol unix:/tmp/' + self.name + ' tcp:%s:%d' % ( controller.IP(), controller.port ) + @@ -533,9 +537,12 @@ class OVSKernelSwitch( Switch ): # then create a new one monitoring the given interfaces quietRun( 'ovs-dpctl del-dp ' + self.dp ) self.cmd( 'ovs-dpctl add-dp ' + self.dp ) + mac_str = '' if self.defaultMAC: - mac = self.defaultMAC - self.cmd( 'ifconfig', self.intf, 'hw', 'ether', mac ) + # ovs-openflowd expects a string of exactly 16 hex digits with no + # colons. + mac_str = ' --datapath-id=0000' + \ + ''.join( self.defaultMAC.split( ':' ) ) + ' ' ports = sorted( self.ports.values() ) if len( ports ) != ports[ -1 ] + 1: raise Exception( 'only contiguous, zero-indexed port ranges' @@ -546,7 +553,7 @@ class OVSKernelSwitch( Switch ): controller = controllers[ 0 ] self.cmd( 'ovs-openflowd ' + self.dp + ' tcp:%s:%d' % ( controller.IP(), controller.port ) + - ' --fail=closed ' + self.opts + + ' --fail=closed ' + self.opts + mac_str + ' 1>' + ofplog + ' 2>' + ofplog + '&' ) self.execed = False From d26abda426c15fea9a87e0ee5e92bc223dde23e4 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Fri, 6 Aug 2010 10:38:15 -0700 Subject: [PATCH 07/72] Small OVS API change --- mininet/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index 05f1921..ba62514 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -553,7 +553,7 @@ class OVSKernelSwitch( Switch ): controller = controllers[ 0 ] self.cmd( 'ovs-openflowd ' + self.dp + ' tcp:%s:%d' % ( controller.IP(), controller.port ) + - ' --fail=closed ' + self.opts + mac_str + + ' --fail=secure ' + self.opts + mac_str + ' 1>' + ofplog + ' 2>' + ofplog + '&' ) self.execed = False From e9d4482e421db2a8170e26d2b1671e3973b17af5 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Fri, 6 Aug 2010 10:39:39 -0700 Subject: [PATCH 08/72] Set default switch type to OVS --- bin/mn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mn b/bin/mn index 1fca885..42b3e25 100755 --- a/bin/mn +++ b/bin/mn @@ -33,7 +33,7 @@ TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ), 'single': SingleSwitchTopo, 'tree': TreeTopo } -SWITCHDEF = 'kernel' +SWITCHDEF = 'ovsk' SWITCHES = { 'kernel': KernelSwitch, 'user': UserSwitch, 'ovsk': OVSKernelSwitch } From 956546acc77e035e49d5700336c316b92250d50e Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Mon, 9 Aug 2010 23:14:10 -0700 Subject: [PATCH 09/72] Change port base from 0 to 1 OpenFlow versions > v0.9 require this. Only tested w/FatTree topo - it's almost a guarantee that this breaks every other topology. --- mininet/node.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index ba62514..759ee85 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -52,6 +52,9 @@ from mininet.log import info, error, debug from mininet.util import quietRun, makeIntfPair, moveIntf, isShellBuiltin from mininet.moduledeps import moduleDeps, OVS_KMOD, OF_KMOD, TUN +PORT_BASE = 1 # Port numbering to start from. OF > v0.9 is 1-indexed. + + class Node( object ): """A virtual network node is simply a shell in a network namespace. We communicate with it using pipes.""" @@ -258,7 +261,7 @@ class Node( object ): "Return the next port number to allocate." if len( self.ports ) > 0: return max( self.ports.values() ) + 1 - return 0 + return PORT_BASE def addIntf( self, intf, port=None ): """Add an interface. @@ -544,8 +547,9 @@ class OVSKernelSwitch( Switch ): mac_str = ' --datapath-id=0000' + \ ''.join( self.defaultMAC.split( ':' ) ) + ' ' ports = sorted( self.ports.values() ) - if len( ports ) != ports[ -1 ] + 1: - raise Exception( 'only contiguous, zero-indexed port ranges' + print ports + if len( ports ) != ports[ -1 ]: + raise Exception( 'only contiguous, one-indexed port ranges ' 'supported: %s' % self.intfs ) intfs = [ self.intfs[ port ] for port in ports ] self.cmd( 'ovs-dpctl', 'add-if', self.dp, ' '.join( intfs ) ) From 1a52deeea6c583d965457a5dc5a27cdf4dd1ff74 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Tue, 10 Aug 2010 02:05:20 -0700 Subject: [PATCH 10/72] Remove print statement left in --- mininet/node.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index 759ee85..b22e9c7 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -547,7 +547,6 @@ class OVSKernelSwitch( Switch ): mac_str = ' --datapath-id=0000' + \ ''.join( self.defaultMAC.split( ':' ) ) + ' ' ports = sorted( self.ports.values() ) - print ports if len( ports ) != ports[ -1 ]: raise Exception( 'only contiguous, one-indexed port ranges ' 'supported: %s' % self.intfs ) From 60a39a7241e16dfd013e1043f8889605ffc36bbb Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Mon, 26 Jul 2010 11:07:04 -0700 Subject: [PATCH 11/72] Add ability to specify hosts for iperf test --- mininet/cli.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/mininet/cli.py b/mininet/cli.py index 8bfa424..c227744 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -148,8 +148,23 @@ class CLI( Cmd ): self.mn.pingPair() def do_iperf( self, line ): - "Simple iperf TCP test between two hosts." - self.mn.iperf() + "Simple iperf TCP test between two (optionally specified) hosts." + args = line.split() + if not args: + self.mn.iperf() + elif len(args) == 2: + hosts = [] + err = False + for arg in args: + if arg not in self.nodemap: + err = True + error( "node '%s' not in network\n" % arg ) + else: + hosts.append( self.nodemap[ arg ] ) + if not err: + self.mn.iperf( hosts ) + else: + error( 'invalid number of args: iperf src dst\n' ) def do_iperfudp( self, line ): "Simple iperf UDP test between two hosts." From 57aae3e103bf42642b077f63f590c8bc4653c70d Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Tue, 10 Aug 2010 04:28:18 -0700 Subject: [PATCH 12/72] Add more param choices for iperf udp on CLI --- mininet/cli.py | 21 ++++++++++++++++++--- mininet/net.py | 4 ---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/mininet/cli.py b/mininet/cli.py index c227744..3ce7ae0 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -167,10 +167,25 @@ class CLI( Cmd ): error( 'invalid number of args: iperf src dst\n' ) def do_iperfudp( self, line ): - "Simple iperf UDP test between two hosts." + "Simple iperf TCP test between two (optionally specified) hosts." args = line.split() - udpBw = args[ 0 ] if len( args ) else '10M' - self.mn.iperfUdp( udpBw ) + if not args: + self.mn.iperf( l4Type='UDP' ) + elif len(args) == 3: + udpBw = args[ 0 ] + hosts = [] + err = False + for arg in args[ 1:3 ]: + if arg not in self.nodemap: + err = True + error( "node '%s' not in network\n" % arg ) + else: + hosts.append( self.nodemap[ arg ] ) + if not err: + self.mn.iperf( hosts, l4Type='UDP', udpBw=udpBw ) + else: + error( 'invalid number of args: iperfudp bw src dst\n' + + 'bw examples: 10M\n' ) def do_intfs( self, line ): "List interfaces." diff --git a/mininet/net.py b/mininet/net.py index 9c1b057..5f1bb44 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -505,10 +505,6 @@ class Mininet( object ): output( '*** Results: %s\n' % result ) return result - def iperfUdp( self, udpBw='10M' ): - "Run iperf UDP test." - return self.iperf( l4Type='UDP', udpBw=udpBw ) - def configLinkStatus( self, src, dst, status ): """Change status of src <-> dst links. src: node name From 9d0dbe488af6706ca095eb8529dbb5a98f7bff4c Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 10 Aug 2010 18:47:15 -0700 Subject: [PATCH 13/72] Added "source" command and restored echo after noecho command. Interactive commands should "work", sort of. --- mininet/cli.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/mininet/cli.py b/mininet/cli.py index 3ce7ae0..11b1640 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -50,6 +50,7 @@ class CLI( Cmd ): self.stdin = stdin self.inPoller = poll() self.inPoller.register( stdin ) + self.inputFile = None Cmd.__init__( self ) info( '*** Starting CLI:\n' ) while True: @@ -247,7 +248,26 @@ class CLI( Cmd ): if self.isatty(): quietRun( 'stty -echo' ) self.default( line ) - # default() fixes tty + if self.isatty(): + quietRun( 'stty echo' ) + + def do_source( self, line ): + "Read commands from an input file." + args = line.split() + if len(args) != 1: + error( 'usage: source \n' ) + return + try: + self.inputFile = open( args[ 0 ] ) + while True: + line = self.inputFile.readline() + if len( line ) > 0: + self.onecmd( line ) + else: + break + except IOError: + pass + self.inputFile = None def default( self, line ): """Called on an input line when the command prefix is not recognized. @@ -256,7 +276,7 @@ class CLI( Cmd ): corresponding IP addrs.""" first, args, line = self.parseline( line ) - if len(args) > 0 and args[ -1 ] == '\n': + if args and len(args) > 0 and args[ -1 ] == '\n': args = args[ :-1 ] rest = args.split( ' ' ) @@ -273,6 +293,7 @@ class CLI( Cmd ): self.waitForNode( node ) else: error( '*** Unknown command: %s\n' % first ) + # pylint: enable-msg=W0613,R0201 @@ -291,6 +312,12 @@ class CLI( Cmd ): while True: try: bothPoller.poll() + if self.inputFile: + key = self.inputFile.read( 1 ) + if key is not '': + node.write(key) + else: + self.inputFile = None if isReadable( self.inPoller ): key = self.stdin.read( 1 ) node.write( key ) From dde9c91dcff22d62df97700a0ec46bb38e756e1a Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 10 Aug 2010 18:57:00 -0700 Subject: [PATCH 14/72] Added error message if we can't read script file. --- mininet/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mininet/cli.py b/mininet/cli.py index 11b1640..fa8a50b 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -266,7 +266,7 @@ class CLI( Cmd ): else: break except IOError: - pass + error( 'error reading file %s\n' % args[ 0 ] ) self.inputFile = None def default( self, line ): From b78c93820155719e12d2d355360cc0702e2dde5c Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Sun, 18 Jul 2010 19:15:06 -0700 Subject: [PATCH 15/72] Changed license to OpenFlow license. --- LICENSE | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/LICENSE b/LICENSE index a5ba614..d81e2d3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,10 +1,29 @@ -Mininet alpha release license +Mininet Pre-Beta License -(c) 2009-2010 Bob Lantz and Brandon Heller +Copyright (c) 2009-2010 Bob Lantz and Brandon Heller -Mininet is currently in *limited alpha release*. We encourage you to -experiment with it and hope that you will provide us with feedback on -features, documentation, and how you're using it. We plan to make it -available publicly via a GPL or BSD license (probably in April), but please -don't distribute the code or URLs yet! The feedback you provide will help -us improve Mininet for general release. +We are making Mininet available for public use and benefit with the +expectation that others will use, modify and enhance the Software and +contribute those enhancements back to the community. However, since we +would like to make the Software available for broadest use, with as few +restrictions as possible permission is hereby granted, free of charge, to +any person obtaining a copy of this Software to deal in the Software +under the copyrights without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +The name and trademarks of copyright holder(s) may NOT be used in +advertising or publicity pertaining to the Software or any derivatives +without specific, written prior permission. From 52082ff3f9c0447c1209b7d4c63aa01222c24a08 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 16 Aug 2010 14:49:02 -0700 Subject: [PATCH 16/72] mininet.node.SWITCH_PORT_BASE specifies first switch port number. This should be mostly cosmetic, but it causes switches to number their ports consistently with OpenFlow 1.0, which starts at 1. For older versions of OpenFlow, SWITCH_PORT_BASE may be set to zero. --- mininet/node.py | 11 +++++++---- mininet/topo.py | 23 +++++++++++++---------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index b22e9c7..403ed00 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -48,12 +48,11 @@ import select from subprocess import Popen, PIPE, STDOUT from time import sleep -from mininet.log import info, error, debug +from mininet.log import info, error, warn, debug from mininet.util import quietRun, makeIntfPair, moveIntf, isShellBuiltin from mininet.moduledeps import moduleDeps, OVS_KMOD, OF_KMOD, TUN -PORT_BASE = 1 # Port numbering to start from. OF > v0.9 is 1-indexed. - +SWITCH_PORT_BASE = 1 # For OF > 0.9, switch ports start at 1 rather than zero class Node( object ): """A virtual network node is simply a shell in a network namespace. @@ -62,6 +61,8 @@ class Node( object ): inToNode = {} # mapping of input fds to nodes outToNode = {} # mapping of output fds to nodes + portBase = 0 # Nodes always start with eth0/port0, even in OF 1.0 + def __init__( self, name, inNamespace=True, defaultMAC=None, defaultIP=None, **kwargs ): """name: name of node @@ -261,7 +262,7 @@ class Node( object ): "Return the next port number to allocate." if len( self.ports ) > 0: return max( self.ports.values() ) + 1 - return PORT_BASE + return self.portBase def addIntf( self, intf, port=None ): """Add an interface. @@ -401,6 +402,8 @@ class Switch( Node ): """A Switch is a Node that is running (or has execed?) an OpenFlow switch.""" + portBase = SWITCH_PORT_BASE # 0 for OF < 1.0, 1 for OF >= 1.0 + def __init__( self, name, opts='', **kwargs): Node.__init__( self, name, **kwargs ) self.opts = opts diff --git a/mininet/topo.py b/mininet/topo.py index 3cb80ae..9547fa1 100644 --- a/mininet/topo.py +++ b/mininet/topo.py @@ -12,7 +12,7 @@ setup for testing, and can even be emulated with the Mininet package. ''' from networkx.classes.graph import Graph - +from mininet.node import SWITCH_PORT_BASE class NodeID(object): '''Topo node identifier.''' @@ -127,15 +127,18 @@ class Topo(object): @param src source switch DPID @param dst destination switch DPID ''' + src_base = SWITCH_PORT_BASE if self.is_switch(src) else 0 + dst_base = SWITCH_PORT_BASE if self.is_switch(dst) else 0 if src not in self.ports: self.ports[src] = {} if dst not in self.ports[src]: - self.ports[src][dst] = len(self.ports[src]) # num outlinks - + # num outlinks + self.ports[src][dst] = len(self.ports[src]) + src_base if dst not in self.ports: self.ports[dst] = {} if src not in self.ports[dst]: - self.ports[dst][src] = len(self.ports[dst]) # num outlinks + # num outlinks + self.ports[dst][src] = len(self.ports[dst]) + dst_base def node_enabled(self, dpid): '''Is node connected, admin on, powered on, and fault-free? @@ -178,6 +181,11 @@ class Topo(object): ''' return [str(self.id_gen(dpid = dpid)) for dpid in dpids] + def is_switch(self, n): + '''Returns true if node is a switch.''' + return self.node_info[n].is_switch + + def switches(self, enabled = True): '''Return switches. @@ -185,12 +193,7 @@ class Topo(object): @return dpids list of dpids ''' - - def is_switch(n): - '''Returns true if node is a switch.''' - return self.node_info[n].is_switch - - nodes = [n for n in self.g.nodes() if is_switch(n)] + nodes = [n for n in self.g.nodes() if self.is_switch(n)] return self.nodes_enabled(nodes, enabled) def hosts(self, enabled = True): From b7097daad47ba4abe51bef6e5ba979de78e9a4ab Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 16 Aug 2010 19:35:49 -0700 Subject: [PATCH 17/72] Pass make codecheck. --- mininet/cli.py | 1 - mininet/topo.py | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/mininet/cli.py b/mininet/cli.py index fa8a50b..b9dbc3f 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -293,7 +293,6 @@ class CLI( Cmd ): self.waitForNode( node ) else: error( '*** Unknown command: %s\n' % first ) - # pylint: enable-msg=W0613,R0201 diff --git a/mininet/topo.py b/mininet/topo.py index 9547fa1..07f74ef 100644 --- a/mininet/topo.py +++ b/mininet/topo.py @@ -132,12 +132,12 @@ class Topo(object): if src not in self.ports: self.ports[src] = {} if dst not in self.ports[src]: - # num outlinks + # num outlinks self.ports[src][dst] = len(self.ports[src]) + src_base if dst not in self.ports: self.ports[dst] = {} if src not in self.ports[dst]: - # num outlinks + # num outlinks self.ports[dst][src] = len(self.ports[dst]) + dst_base def node_enabled(self, dpid): @@ -185,7 +185,6 @@ class Topo(object): '''Returns true if node is a switch.''' return self.node_info[n].is_switch - def switches(self, enabled = True): '''Return switches. From 9de7873bc8e844a75da4939dd42461ba2827da2b Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 16 Aug 2010 19:36:00 -0700 Subject: [PATCH 18/72] Change to automatically update IP and MAC addresses. --- mininet/node.py | 52 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index 403ed00..0a713ac 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -48,7 +48,7 @@ import select from subprocess import Popen, PIPE, STDOUT from time import sleep -from mininet.log import info, error, warn, debug +from mininet.log import info, error, debug from mininet.util import quietRun, makeIntfPair, moveIntf, isShellBuiltin from mininet.moduledeps import moduleDeps, OVS_KMOD, OF_KMOD, TUN @@ -62,7 +62,7 @@ class Node( object ): outToNode = {} # mapping of output fds to nodes portBase = 0 # Nodes always start with eth0/port0, even in OF 1.0 - + def __init__( self, name, inNamespace=True, defaultMAC=None, defaultIP=None, **kwargs ): """name: name of node @@ -93,6 +93,7 @@ class Node( object ): self.ports = {} # dict of interface names to port numbers # replace with Port objects, eventually ? self.ips = {} # dict of interfaces to ip addresses as strings + self.macs = {} # dict of interfacesto mac addresses as strings self.connection = {} # remote node connected to each interface self.execed = False self.lastCmd = None @@ -367,21 +368,50 @@ class Node( object ): self.cmd( 'ip route flush root 0/0' ) return self.cmd( 'route add default ' + intf ) + def defaultIntf( self ): + "Return interface for lowest port" + ports = self.intfs.keys() + if ports: + return self.intfs[ min( ports ) ] + + _ipMatchRegex = re.compile( r'\d+\.\d+\.\d+\.\d+' ) + _macMatchRegex = re.compile( r'..:..:..:..:..:..' ) + def IP( self, intf=None ): "Return IP address of a node or specific interface." - if len( self.ips ) == 1: - return self.ips.values()[ 0 ] - if intf: - return self.ips.get( intf, None ) + if intf is None: + intf = self.defaultIntf() + if intf and not self.waiting: + self.updateIP( intf ) + return self.ips.get( intf, None ) def MAC( self, intf=None ): "Return MAC address of a node or specific interface." - if intf is None and len( self.intfs ) == 1: - intf = self.intfs.values()[ 0 ] + if intf is None: + intf = self.defaultIntf() + if intf and not self.waiting: + self.updateMAC( intf ) + return self.macs.get( intf, None ) + + def updateIP( self, intf ): + "Update IP address for an interface" + assert not self.waiting ifconfig = self.cmd( 'ifconfig ' + intf ) - macs = re.findall( '..:..:..:..:..:..', ifconfig ) - if len( macs ) > 0: - return macs[ 0 ] + ips = self._ipMatchRegex.findall( ifconfig ) + if ips: + self.ips[ intf ] = ips[ 0 ] + else: + self.ips[ intf ] = None + + def updateMAC( self, intf ): + "Update MAC address for an interface" + assert not self.waiting + ifconfig = self.cmd( 'ifconfig ' + intf ) + macs = self._macMatchRegex.findall( ifconfig ) + if macs: + self.macs[ intf ] = macs[ 0 ] + else: + self.macs[ intf ] = None def intfIsUp( self, intf ): "Check if an interface is up." From e3a1fbb0476ef6ba7684f3bdf6205e12c2519866 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 16 Aug 2010 20:21:08 -0700 Subject: [PATCH 19/72] Added support for pre- and post-test CLI scripts. --- bin/mn | 38 ++++++++++++++++++++++++++++---------- mininet/cli.py | 7 +++++-- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/bin/mn b/bin/mn index 42b3e25..7bb4256 100755 --- a/bin/mn +++ b/bin/mn @@ -17,6 +17,7 @@ import sys import time from mininet.clean import cleanup +from mininet.cli import CLI from mininet.log import lg, LEVELS, info from mininet.net import Mininet, init from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX @@ -50,9 +51,11 @@ CONTROLLERS = { 'ref': Controller, 'none': lambda name: None } # optional tests to run -TESTS = [ 'cli', 'build', 'pingAll', 'pingPair', 'iperf', 'all', 'iperfUdp', +TESTS = [ 'cli', 'build', 'pingall', 'pingpair', 'iperf', 'all', 'iperfudp', 'none' ] +ALTSPELLING = { 'pingall': 'pingAll', 'pingpair': 'pingPair', + 'iperfudp': 'iperfUdp', 'iperfUDP': 'iperfUdp' } def buildTopo( topo ): "Create topology from string with format (object, arg1, arg2,...)." @@ -99,6 +102,7 @@ class MininetRunner( object ): def __init__( self ): "Init." self.options = None + self.args = None # May be used someday for more CLI scripts self.validate = None self.parseArgs() @@ -170,9 +174,14 @@ class MininetRunner( object ): opts.add_option( '--port', type='int', default=6633, help='[port integer for a listening remote' ' controller]' ) - opts.add_option( '--inNamespace', action='store_true', + opts.add_option( '--innamespace', action='store_true', default=False, help='sw and ctrl in namespace?' ) - self.options = opts.parse_args()[ 0 ] + opts.add_option( '--pre', type='string', default=None, + help='[CLI script to run before tests]' ) + opts.add_option( '--post', type='string', default=None, + help='[CLI script to run after tests]' ) + + self.options, self.args = opts.parse_args() def setup( self ): "Setup and validate environment." @@ -209,7 +218,7 @@ class MininetRunner( object ): self.validate( self.options ) controllerParams = ControllerParams( '10.0.0.0', 8 ) - inNamespace = self.options.inNamespace + inNamespace = self.options.innamespace xterms = self.options.xterms mac = self.options.mac arp = self.options.arp @@ -217,20 +226,29 @@ class MininetRunner( object ): inNamespace=inNamespace, xterms=xterms, autoSetMacs=mac, autoStaticArp=arp ) + if self.options.pre: + CLI( mn, script=self.options.pre ) test = self.options.test + test = ALTSPELLING.get( test, test ) + + mn.start() + if test == 'none': - mn.start() - mn.stop() - elif test == 'cli': - mn.interact() + pass elif test == 'all': mn.start() mn.ping() mn.iperf() - mn.stop() + elif test == 'cli': + CLI( mn ) elif test != 'build': - mn.run( getattr( mn, test ) ) + getattr( mn, test )() + + if self.options.post: + CLI( mn, script=self.options.post ) + + mn.stop() elapsed = float( time.time() - start ) info( 'completed in %0.3f seconds\n' % elapsed ) diff --git a/mininet/cli.py b/mininet/cli.py index b9dbc3f..a884316 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -40,7 +40,7 @@ class CLI( Cmd ): prompt = 'mininet> ' - def __init__( self, mininet, stdin=sys.stdin ): + def __init__( self, mininet, stdin=sys.stdin, script=None ): self.mn = mininet self.nodelist = self.mn.controllers + self.mn.switches + self.mn.hosts self.nodemap = {} # map names to Node objects @@ -50,9 +50,12 @@ class CLI( Cmd ): self.stdin = stdin self.inPoller = poll() self.inPoller.register( stdin ) - self.inputFile = None + self.inputFile = script Cmd.__init__( self ) info( '*** Starting CLI:\n' ) + if self.inputFile: + self.do_source( self.inputFile ) + return while True: try: # Make sure no nodes are still waiting From 2c07d62b3c1d03ddae3463f4703b5da7107354b0 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 16 Aug 2010 23:00:43 -0700 Subject: [PATCH 20/72] Remove blank lines to pass code check. --- bin/mn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/mn b/bin/mn index 7bb4256..9e50cbf 100755 --- a/bin/mn +++ b/bin/mn @@ -231,9 +231,9 @@ class MininetRunner( object ): test = self.options.test test = ALTSPELLING.get( test, test ) - + mn.start() - + if test == 'none': pass elif test == 'all': From ab312967fef76a7d9bbc7dd10f18c901584c4302 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 16 Aug 2010 23:01:06 -0700 Subject: [PATCH 21/72] Added pathCheck for additional sanity when OF/OVS isn't installed. --- mininet/moduledeps.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mininet/moduledeps.py b/mininet/moduledeps.py index b21c629..f954e03 100644 --- a/mininet/moduledeps.py +++ b/mininet/moduledeps.py @@ -2,6 +2,7 @@ from mininet.util import quietRun from mininet.log import info, error, debug +from os import environ def lsmod(): "Return output of lsmod." @@ -54,3 +55,12 @@ def moduleDeps( subtract=None, add=None ): exit( 1 ) else: debug( '*** ' + mod + ' already loaded\n' ) + +def pathCheck( *args ): + "Make sure each program in *args can be found in $PATH." + for arg in args: + if not quietRun( 'which ' + arg ): + error( 'Cannot find required executable %s -' + ' is it installed somewhere in your $PATH?\n(%s)\n' % + ( arg, environ[ 'PATH' ] ) ) + exit( 1 ) From 2f40c8569161d52bd0144d6953605ba9ab16c209 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 16 Aug 2010 23:01:31 -0700 Subject: [PATCH 22/72] Added additional sanity checks for when OF/OVS isn't installed. --- mininet/node.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index 0a713ac..ad94ad6 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -50,7 +50,7 @@ from time import sleep from mininet.log import info, error, debug from mininet.util import quietRun, makeIntfPair, moveIntf, isShellBuiltin -from mininet.moduledeps import moduleDeps, OVS_KMOD, OF_KMOD, TUN +from mininet.moduledeps import moduleDeps, pathCheck, OVS_KMOD, OF_KMOD, TUN SWITCH_PORT_BASE = 1 # For OF > 0.9, switch ports start at 1 rather than zero @@ -455,11 +455,12 @@ class UserSwitch( Switch ): """Init. name: name for the switch""" Switch.__init__( self, name, **kwargs ) + pathCheck( 'ofdatapath', 'ofprotocol' ) @staticmethod def setup(): "Ensure any dependencies are loaded; if not, try to load them." - moduleDeps( add = TUN ) + moduleDeps( add=TUN ) def start( self, controllers ): """Start OpenFlow reference user datapath. @@ -511,6 +512,7 @@ class KernelSwitch( Switch ): def setup(): "Ensure any dependencies are loaded; if not, try to load them." moduleDeps( subtract = OVS_KMOD, add = OF_KMOD ) + pathCheck( 'ofprotocol' ) def start( self, controllers ): "Start up reference kernel datapath." @@ -523,7 +525,7 @@ class KernelSwitch( Switch ): if self.defaultMAC: self.cmd( 'ifconfig', self.intf, 'hw', 'ether', self.defaultMAC ) ports = sorted( self.ports.values() ) - if len( ports ) != ports[ -1 ] + 1: + if len( ports ) != ports[ -1 ] + 1 - self.portBase: raise Exception( 'only contiguous, zero-indexed port ranges' 'supported: %s' % ports ) intfs = [ self.intfs[ port ] for port in ports ] @@ -564,6 +566,7 @@ class OVSKernelSwitch( Switch ): def setup(): "Ensure any dependencies are loaded; if not, try to load them." moduleDeps( subtract = OF_KMOD, add = OVS_KMOD ) + pathCheck( 'ovs-dpctl', 'ovs-openflowd' ) def start( self, controllers ): "Start up kernel datapath." @@ -580,7 +583,7 @@ class OVSKernelSwitch( Switch ): mac_str = ' --datapath-id=0000' + \ ''.join( self.defaultMAC.split( ':' ) ) + ' ' ports = sorted( self.ports.values() ) - if len( ports ) != ports[ -1 ]: + if len( ports ) != ports[ -1 ] + 1 - self.portBase: raise Exception( 'only contiguous, one-indexed port ranges ' 'supported: %s' % self.intfs ) intfs = [ self.intfs[ port ] for port in ports ] @@ -617,6 +620,7 @@ class Controller( Node ): def start( self ): """Start on controller. Log to /tmp/cN.log""" + pathCheck( self.controller ) cout = '/tmp/' + self.name + '.log' if self.cdir is not None: self.cmd( 'cd ' + self.cdir ) From b13a2c17c5cf5a80484914d744ed28a58b67b5dd Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 16 Aug 2010 23:02:04 -0700 Subject: [PATCH 23/72] Removed test for reference kernel implementation, for now at least. ;-( --- mininet/test/test_nets.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mininet/test/test_nets.py b/mininet/test/test_nets.py index 3ace2ed..dbadf1e 100755 --- a/mininet/test/test_nets.py +++ b/mininet/test/test_nets.py @@ -6,14 +6,15 @@ import unittest from mininet.net import init, Mininet -from mininet.node import KernelSwitch, Host, Controller, ControllerParams +from mininet.node import Host, Controller, ControllerParams +# from mininet.node import KernelSwitch from mininet.node import UserSwitch, OVSKernelSwitch from mininet.topo import SingleSwitchTopo, LinearTopo -# temporary, until user-space side is tested -SWITCHES = { 'kernel': KernelSwitch, - 'user': UserSwitch, - 'ovsk': OVSKernelSwitch } +SWITCHES = { 'user': UserSwitch, + 'ovsk': OVSKernelSwitch, + # 'kernel': KernelSwitch +} class testSingleSwitch( unittest.TestCase ): From 0533e1cc1ec8f89baffd48c059f3be809da40bdb Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 00:30:25 -0700 Subject: [PATCH 24/72] Remove hard-wired /home/mininet directory. --- util/install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/install.sh b/util/install.sh index dd84f84..020ac7d 100755 --- a/util/install.sh +++ b/util/install.sh @@ -69,7 +69,7 @@ function mn_deps { sudo apt-get install -y screen psmisc xterm ssh iperf iproute python-setuptools #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: sudo sysctl -p @@ -194,7 +194,7 @@ function cbench { git clone git://www.openflow.org/oflops.git cd oflops sh boot.sh - ./configure --with-openflow-src-dir=/home/mininet/openflow + ./configure --with-openflow-src-dir=$HOME/openflow make sudo make install || true # make install fails; force past this } From 455194a3b80b8a9f29e5d871c3207fe62284b534 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 03:04:12 -0700 Subject: [PATCH 25/72] Delete spaces around =. --- mininet/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index ad94ad6..6380fee 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -511,7 +511,7 @@ class KernelSwitch( Switch ): @staticmethod def setup(): "Ensure any dependencies are loaded; if not, try to load them." - moduleDeps( subtract = OVS_KMOD, add = OF_KMOD ) + moduleDeps( subtract=OVS_KMOD, add=OF_KMOD ) pathCheck( 'ofprotocol' ) def start( self, controllers ): From 5d4d6305800cc9c27b2028cb9e01d4762bc00e66 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 03:04:30 -0700 Subject: [PATCH 26/72] Getting close to Ubuntu install. --- util/install.sh | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/util/install.sh b/util/install.sh index 020ac7d..c5eaa1b 100755 --- a/util/install.sh +++ b/util/install.sh @@ -4,7 +4,7 @@ # Fail on error set -e - + # Fail on unset var usage set -o nounset @@ -17,6 +17,7 @@ KERNEL_NAME=2.6.33.1-mininet #KERNEL_NAME=`uname -r` 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 +DIST=UBUNTU # Assume Ubuntu, not debian Lenny # Kernel Deb pkg to be removed: KERNEL_IMAGE_OLD=linux-image-2.6.26-2-686 @@ -33,8 +34,8 @@ function kernel { sudo apt-get update # The easy approach: download pre-built linux-image and linux-headers packages: - wget $KERNEL_LOC/$KERNEL_HEADERS - wget $KERNEL_LOC/$KERNEL_IMAGE + wget -c $KERNEL_LOC/$KERNEL_HEADERS + wget -c $KERNEL_LOC/$KERNEL_IMAGE #Install custom linux headers and image: sudo dpkg -i $KERNEL_IMAGE $KERNEL_HEADERS @@ -109,7 +110,7 @@ function of { sudo apt-get remove -y avahi-daemon # Disable IPv6. Add to /etc/modprobe.d/blacklist: - sudo sh -c "echo -e 'blacklist net-pf-10\nblacklist ipv6' >> /etc/modprobe.d/blacklist" + sudo sh -c "echo 'blacklist net-pf-10\nblacklist ipv6' >> /etc/modprobe.d/blacklist" } # Install OpenVSwitch @@ -117,12 +118,14 @@ function of { function ovs { echo "Installing OpenVSwitch..." + if [ "$DIST" = "LENNY" ]; then #Install Autoconf 2.63+ backport from Debian Backports repo: #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 apt-get update sudo apt-get -y --force-yes install debian-backports-keyring sudo apt-get -y --force-yes -t lenny-backports install autoconf + fi #Install OVS from release cd ~/ @@ -132,7 +135,10 @@ function ovs { git clone git://openvswitch.org/openvswitch cd $OVS_RELEASE ./boot.sh - ./configure --with-l26=/lib/modules/${KERNEL_NAME}/build + BUILDDIR=/lib/modules/${KERNEL_NAME}/build + mkdir -p $BUILDDIR + opts="--with-l26=$BUILDDIR" + ./configure $opts make sudo make install } @@ -142,8 +148,12 @@ function nox { echo "Installing NOX w/tutorial files..." #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" == "LENNY" ]; then + sudo apt-get -y install libboost1.35-dev + else + sudo apt-get -y install libboost1.40-dev + fi #Install NOX optional deps: sudo apt-get install -y libsqlite3-dev python-simplejson @@ -288,14 +298,20 @@ function usage { exit 2 } +function lenny { + echo "Installing for Lenny" + DIST=LENNY +} + if [ $# -eq 0 ] then all else - while getopts 'acdfhkmntvx' OPTION + while getopts 'lacdfhkmntvx' OPTION do case $OPTION in - a) all;; + l) lenny;; + a) all;; c) kernel_clean;; d) vm_clean;; f) of;; From 52c700ff0cb30638b0e7cb73da80c825aae2ec5d Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 16:06:34 -0700 Subject: [PATCH 27/72] Updated for 1.0 and to reflect install.sh. --- INSTALL | 110 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 28 deletions(-) diff --git a/INSTALL b/INSTALL index dd735cd..a4571be 100644 --- a/INSTALL +++ b/INSTALL @@ -1,13 +1,14 @@ Preliminary Mininet Installation/Configuration Notes -Alpha release, March 2010 +Pre-Beta release, 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 easiest way to get Mininet running is to start with one of our pre-built +virtual machine images from: http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetGettingStarted @@ -36,22 +37,37 @@ compile kernels, apply patches, configure networks, write code, etc.. If this is unfamiliar territory, or if you run into trouble, we recommend 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://www.openflowswitch.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://yuba.stanford.edu/mininet.git + 1. Core Mininet installation 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: - + + # cd mininet # 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 script (mn) as well as its helper utility (mnexec.) -2. Script-based kernel and OpenFlow installation for Debian +2. Script-based kernel and OpenFlow installation for Ubuntu/Debian Lenny - If you are running debian-stable, you may be able to use the + 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 other software including the OpenFlow reference implementation, the Open vSwitch switch implementation, and the NOX OpenFlow controller. Assuming @@ -63,20 +79,33 @@ using one of our pre-built virtual machine images (see above.) % sudo reboot # to load new kernel % ~/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 (20 + minutes or more, depending on your network connection, computer, etc..) + + If install.sh cannot be used for some reason, or if you don't want to + install all of these components (they're useful!), the kernel and OpenFlow software requirements are descibed in steps [3] and [4], 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 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. + + For Ubuntu and Debian, we provide a 2.6.33 kernel package which you may be + able to install using "util/install.sh -x". Note our kernel package + 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 doesn't support it, 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. + 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 mininet/util/kbuild. You may wish to read it, as it applies patches @@ -102,23 +131,19 @@ using one of our pre-built virtual machine images (see above.) Mininet requires either the reference OpenFlow switch implementation (from openflowswitch.org) or Open vSwitch (openvswitch.org) to be - installed. "make test" requires the reference user and kernel space - implementations as well as Open vSwitch. Note the kernel implementation - is not currently included in OpenFlow 1.0. - - 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 + installed. "make test" requires the reference user space + implementations as well as Open vSwitch. Note the reference kernel + implementation is not currently included in OpenFlow 1.0. - A patch to enable datapath.c to compile with recent kernels - is included in util/openflow-patches/datapath.patch. + On Ubuntu and Debian, the install.sh script may be used with the '-f' + option to install the OpenFlow reference implementation, the '-v' option + 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!) Mininet will automatically load and remove kernel module dependencies for supported switch types, using modprobe and rmmod - but these - modules must be in a location where modprobe can find them (i.e. - /lib/modules/...) + modules must be in a location where modprobe can find them (e.g. + something like /lib/modules/`uname -r`/kernel/drivers/net/) The reference OpenFlow controller (controller(8)) only supports 16 switches by default! If you wish to run a network with more than 16 @@ -128,6 +153,9 @@ using one of our pre-built virtual machine images (see above.) 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: sudo aptitude/yum install iperf @@ -141,6 +169,9 @@ using one of our pre-built virtual machine images (see above.) Some examples may have additional requirements - consult the specific 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 Mininet should be run either on a machine with @@ -151,3 +182,26 @@ using one of our pre-built virtual machine images (see above.) 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. + + + + + From 85b69adbf8e443f988ed28f4c198b21209d7dd8e Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 16:07:07 -0700 Subject: [PATCH 28/72] Version that hopefully will work on Ubuntu with an ext3 root FS. --- util/install.sh | 67 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/util/install.sh b/util/install.sh index c5eaa1b..1a4afbd 100755 --- a/util/install.sh +++ b/util/install.sh @@ -17,12 +17,12 @@ KERNEL_NAME=2.6.33.1-mininet #KERNEL_NAME=`uname -r` 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 -DIST=UBUNTU # Assume Ubuntu, not debian Lenny +DIST=`lsb_release -is` # Kernel Deb pkg to be removed: 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 # release 1.0.1 doesn't work with veth pairs. @@ -33,6 +33,13 @@ function kernel { echo "Install new kernel..." sudo apt-get update + # Until we build ext4 into our kernel image + ext2=`mount | head -1 | egrep 'ext2|ext3'` + if [ "$ext2" == "" ]; then + echo "Kernel package requires ext2 or ext3 root filesystem" + exit 1 + fi + # The easy approach: download pre-built linux-image and linux-headers packages: wget -c $KERNEL_LOC/$KERNEL_HEADERS wget -c $KERNEL_LOC/$KERNEL_IMAGE @@ -118,13 +125,13 @@ function of { function ovs { echo "Installing OpenVSwitch..." - if [ "$DIST" = "LENNY" ]; then - #Install Autoconf 2.63+ backport from Debian Backports repo: - #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 apt-get update - sudo apt-get -y --force-yes install debian-backports-keyring - sudo apt-get -y --force-yes -t lenny-backports install autoconf + if [ "$DIST" = "Debian" ]; then + #Install Autoconf 2.63+ backport from Debian Backports repo: + #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 apt-get update + sudo apt-get -y --force-yes install debian-backports-keyring + sudo apt-get -y --force-yes -t lenny-backports install autoconf fi #Install OVS from release @@ -149,10 +156,12 @@ function nox { #Install NOX deps: sudo apt-get -y install autoconf automake g++ libtool python python-twisted swig libxerces-c2-dev libssl-dev make - if [ "$DIST" == "LENNY" ]; then + if [ "$DIST" == "Debian" ]; then sudo apt-get -y install libboost1.35-dev - else - sudo apt-get -y install libboost1.40-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: sudo apt-get install -y libsqlite3-dev python-simplejson @@ -164,12 +173,14 @@ function nox { # With later autoconf versions this doesn't quite work: ./boot.sh --apps-core || true - # So use this instead: - autoreconf --install --force + if [ "$DIST" == "Debian" ]; then + # So use this instead: + autoreconf --install --force + fi mkdir build cd build ../configure --with-python=yes - make + make #make check # Add NOX_CORE_DIR env var: @@ -275,7 +286,7 @@ function vm_clean { # Remove sensistive files history -c - rm ~/.bash_history # history -c doesn't seem to work for some reason + rm ~/.bash_history # need to clear in memory and remove on disk rm -f ~/.ssh/id_rsa* ~/.ssh/known_hosts sudo rm ~/.ssh/authorized_keys2 @@ -295,6 +306,27 @@ function vm_clean { function usage { printf "Usage: %s: [-acdfhkmntvxy] args\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" >&2 + + printf "\noptions:\n" >&2 + printf "-a: 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\nn" >&2 + printf "-t: install o(T)her stuff\n" >&2 + printf "-v: install open (V)switch\n" >&2 + printf "-x: install NOX(X) OpenFlow contoller\n" >&2 + printf "-y: install (A)ll packages\n" >&2 + exit 2 } @@ -307,10 +339,9 @@ if [ $# -eq 0 ] then all else - while getopts 'lacdfhkmntvx' OPTION + while getopts 'acdfhkmntvx' OPTION do case $OPTION in - l) lenny;; a) all;; c) kernel_clean;; d) vm_clean;; From 01eea3503b20ac00435d14724dab9ec58fbd72a1 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 16:36:42 -0700 Subject: [PATCH 29/72] Updated other install and help message. --- util/install.sh | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/util/install.sh b/util/install.sh index 1a4afbd..caa5c7e 100755 --- a/util/install.sh +++ b/util/install.sh @@ -242,7 +242,9 @@ function other { git config --global color.branch auto #Reduce boot screen opt-out delay. Modify timeout in /boot/grub/menu.lst to 1: - sudo sed -i -e 's/^timeout.*$/timeout 1/' /boot/grub/menu.lst + 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-* @@ -285,8 +287,8 @@ function vm_clean { sudo rm -rf openvswitch*.tar.gz # Remove sensistive files - history -c - rm ~/.bash_history # need to clear in memory and remove on disk + history -c # note this won't work if you have multiple bash sessions + rm ~/.bash_history # need to clear in memory and remove on disk rm -f ~/.ssh/id_rsa* ~/.ssh/known_hosts sudo rm ~/.ssh/authorized_keys2 @@ -305,27 +307,27 @@ function vm_clean { } 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" >&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 "\noptions:\n" >&2 - printf "-a: 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\nn" >&2 - printf "-t: install o(T)her stuff\n" >&2 - printf "-v: install open (V)switch\n" >&2 - printf "-x: install NOX(X) OpenFlow contoller\n" >&2 - printf "-y: install (A)ll packages\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\n' >&2 + printf -- ' -t: install o(T)her stuff\n' >&2 + printf -- ' -v: install open (V)switch\n' >&2 + printf -- ' -x: install NOX(X) OpenFlow contoller\n' >&2 + printf -- ' -y: install (A)ll packages\n' >&2 exit 2 } From 57a0bb2f95c67d9c5bff6815f7320566bb243b31 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 16:49:45 -0700 Subject: [PATCH 30/72] Removed unneeded lenny function. --- util/install.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/util/install.sh b/util/install.sh index caa5c7e..e1d8232 100755 --- a/util/install.sh +++ b/util/install.sh @@ -332,11 +332,6 @@ function usage { exit 2 } -function lenny { - echo "Installing for Lenny" - DIST=LENNY -} - if [ $# -eq 0 ] then all From 25f64a39a033ada56dc26d3dc037112f20840eb4 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 17:04:57 -0700 Subject: [PATCH 31/72] Changed to not install kernel on ubuntu. --- util/install.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/install.sh b/util/install.sh index e1d8232..141e0ad 100755 --- a/util/install.sh +++ b/util/install.sh @@ -266,7 +266,10 @@ function modprobe { function all { echo "Running all commands..." - kernel + if [ "$DIST" != "Ubuntu" ]; then + # Ubuntu ships with Mininet-compatible kernel + kernel + fi mn_deps of ovs From cf9c968756bbd3f6c235a06f78f60855495e8d2e Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 17:31:02 -0700 Subject: [PATCH 32/72] Change to not try to install kernel on ubuntu. --- util/install.sh | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/util/install.sh b/util/install.sh index 141e0ad..706c6d2 100755 --- a/util/install.sh +++ b/util/install.sh @@ -11,13 +11,21 @@ set -o nounset # Location of CONFIG_NET_NS-enabled kernel(s) KERNEL_LOC=http://www.stanford.edu/~brandonh +DIST=`lsb_release -is` + # Kernel params # These kernels have been tried: -KERNEL_NAME=2.6.33.1-mininet -#KERNEL_NAME=`uname -r` -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 -DIST=`lsb_release -is` +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 # Kernel Deb pkg to be removed: KERNEL_IMAGE_OLD=linux-image-2.6.26-2-686 @@ -30,15 +38,10 @@ OVS_DIR=~/$OVS_RELEASE OVS_KMOD=openvswitch_mod.ko function kernel { - echo "Install new kernel..." + echo "Install Mininet-compatible kernel" sudo apt-get update - - # Until we build ext4 into our kernel image - ext2=`mount | head -1 | egrep 'ext2|ext3'` - if [ "$ext2" == "" ]; then - echo "Kernel package requires ext2 or ext3 root filesystem" - exit 1 - fi + + if [ "$DIST" = "Debian" ]; then # The easy approach: download pre-built linux-image and linux-headers packages: wget -c $KERNEL_LOC/$KERNEL_HEADERS @@ -59,6 +62,8 @@ function kernel { 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. + fi + } function kernel_clean { @@ -134,6 +139,10 @@ function ovs { sudo apt-get -y --force-yes -t lenny-backports install autoconf fi + if [ "$DIST" == "Ubuntu" ]; then + sudo apt-get -y install $KERNEL_HEADERS + fi + #Install OVS from release cd ~/ #wget http://openvswitch.org/releases/${OVS_RELEASE}.tar.gz From a0ca68b6b827b9e1e6ce59998fb89de1856bc393 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 17:41:01 -0700 Subject: [PATCH 33/72] Install mininet along with its dependencies. --- util/install.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/util/install.sh b/util/install.sh index 706c6d2..6c1884a 100755 --- a/util/install.sh +++ b/util/install.sh @@ -78,7 +78,7 @@ function kernel_clean { # Install Mininet deps function mn_deps { - #Install dependencies: + echo "Installing Mininet dependencies" sudo apt-get install -y screen psmisc xterm ssh iperf iproute python-setuptools #Add sysctl parameters as noted in the INSTALL file to increase kernel limits to support larger setups: @@ -86,6 +86,11 @@ function mn_deps { #Load new sysctl settings: sudo sysctl -p + + echo "Installing Mininet core" + pushd ~/mininet + sudo make install + popd } # The following will cause a full OF install, covering: @@ -335,7 +340,7 @@ function usage { 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\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 NOX(X) OpenFlow contoller\n' >&2 From 7268f6943c4ed3cbc53ab337c218647f1b1b0439 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 19:33:24 -0700 Subject: [PATCH 34/72] Add gcc to mininet dependencies. --- util/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/install.sh b/util/install.sh index 6c1884a..e01d8f5 100755 --- a/util/install.sh +++ b/util/install.sh @@ -79,7 +79,7 @@ function kernel_clean { # Install Mininet deps function mn_deps { echo "Installing Mininet dependencies" - sudo apt-get install -y screen psmisc xterm ssh iperf iproute python-setuptools + sudo apt-get install -y gcc screen psmisc xterm ssh iperf iproute python-setuptools #Add sysctl parameters as noted in the INSTALL file to increase kernel limits to support larger setups: sudo su -c "cat $HOME/mininet/util/sysctl_addon >> /etc/sysctl.conf" From dd2a2442c47c8b71b8a00b19f97315f99fb02689 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 20:40:53 -0700 Subject: [PATCH 35/72] Hack: run depmod twice so it works (hopefully) on Ubuntu. --- util/install.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/install.sh b/util/install.sh index e01d8f5..aa98e7d 100755 --- a/util/install.sh +++ b/util/install.sh @@ -287,11 +287,14 @@ function all { mn_deps of ovs - modprobe + modprobe nox oftest cbench other + # BL Hack: for some annoying reason, the first depmod doesn't + # seem to take on Ubuntu, so do it once again for good measure! + modprobe echo "Please reboot, then run ./mininet/util/install.sh -c to remove unneeded packages." echo "Enjoy Mininet!" } From 59d326295f0e3b616ed22d47369cb272641abbba Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 22:32:22 -0700 Subject: [PATCH 36/72] Fixed module installation error, for real. --- mininet/moduledeps.py | 7 +++---- util/install.sh | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/mininet/moduledeps.py b/mininet/moduledeps.py index f954e03..6f185a0 100644 --- a/mininet/moduledeps.py +++ b/mininet/moduledeps.py @@ -37,7 +37,7 @@ def moduleDeps( subtract=None, add=None ): info( '*** Removing ' + mod + '\n' ) rmmodOutput = rmmod( mod ) if rmmodOutput: - error( 'Error removing ' + mod + '\n%s' % rmmodOutput ) + error( 'Error removing ' + mod + ': %s\n' % rmmodOutput ) exit( 1 ) if mod in lsmod(): error( 'Failed to remove ' + mod + '; still there!\n' ) @@ -47,9 +47,8 @@ def moduleDeps( subtract=None, add=None ): info( '*** Loading ' + mod + '\n' ) modprobeOutput = modprobe( mod ) if modprobeOutput: - error( 'Error inserting ' + mod + ';\n See INSTALL.\n%s' % - modprobeOutput ) - exit( 1 ) + error( 'Error inserting ' + mod + '- is it installed?\n' + + 'Error was: %s\n' % modprobeOutput ) if mod not in lsmod(): error( 'Failed to insert ' + mod + '\n' ) exit( 1 ) diff --git a/util/install.sh b/util/install.sh index aa98e7d..c5ad00e 100755 --- a/util/install.sh +++ b/util/install.sh @@ -127,7 +127,12 @@ function of { sudo apt-get remove -y avahi-daemon # Disable IPv6. Add to /etc/modprobe.d/blacklist: - sudo sh -c "echo '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 @@ -144,7 +149,7 @@ function ovs { sudo apt-get -y --force-yes -t lenny-backports install autoconf fi - if [ "$DIST" == "Ubuntu" ]; then + if [ "$DIST" = "Ubuntu" ]; then sudo apt-get -y install $KERNEL_HEADERS fi @@ -170,9 +175,9 @@ function nox { #Install NOX deps: sudo apt-get -y install autoconf automake g++ libtool python python-twisted swig libxerces-c2-dev libssl-dev make - if [ "$DIST" == "Debian" ]; then + if [ "$DIST" = "Debian" ]; then sudo apt-get -y install libboost1.35-dev - elif [ "$DIST" == "Ubuntu" ]; then + 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 @@ -187,7 +192,7 @@ function nox { # With later autoconf versions this doesn't quite work: ./boot.sh --apps-core || true - if [ "$DIST" == "Debian" ]; then + if [ "$DIST" = "Debian" ]; then # So use this instead: autoreconf --install --force fi @@ -292,9 +297,6 @@ function all { oftest cbench other - # BL Hack: for some annoying reason, the first depmod doesn't - # seem to take on Ubuntu, so do it once again for good measure! - modprobe echo "Please reboot, then run ./mininet/util/install.sh -c to remove unneeded packages." echo "Enjoy Mininet!" } From 8e5892e2fd5d3560ed4ffe3e8f11cfdb393865bf Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 22:35:24 -0700 Subject: [PATCH 37/72] Make it easier to see what the error was on failed module load. --- mininet/moduledeps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mininet/moduledeps.py b/mininet/moduledeps.py index 6f185a0..f57c462 100644 --- a/mininet/moduledeps.py +++ b/mininet/moduledeps.py @@ -37,7 +37,7 @@ def moduleDeps( subtract=None, add=None ): info( '*** Removing ' + mod + '\n' ) rmmodOutput = rmmod( mod ) if rmmodOutput: - error( 'Error removing ' + mod + ': %s\n' % rmmodOutput ) + error( 'Error removing ' + mod + ': <%s>\n' % rmmodOutput ) exit( 1 ) if mod in lsmod(): error( 'Failed to remove ' + mod + '; still there!\n' ) @@ -48,7 +48,7 @@ def moduleDeps( subtract=None, add=None ): modprobeOutput = modprobe( mod ) if modprobeOutput: error( 'Error inserting ' + mod + '- is it installed?\n' + - 'Error was: %s\n' % modprobeOutput ) + 'Error was: <%s>\n' % modprobeOutput ) if mod not in lsmod(): error( 'Failed to insert ' + mod + '\n' ) exit( 1 ) From 4c85d6d3ecdb860103cea4e9fce068c85ad62254 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 22:36:40 -0700 Subject: [PATCH 38/72] Quotes are better. --- mininet/moduledeps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mininet/moduledeps.py b/mininet/moduledeps.py index f57c462..9592928 100644 --- a/mininet/moduledeps.py +++ b/mininet/moduledeps.py @@ -37,7 +37,7 @@ def moduleDeps( subtract=None, add=None ): info( '*** Removing ' + mod + '\n' ) rmmodOutput = rmmod( mod ) if rmmodOutput: - error( 'Error removing ' + mod + ': <%s>\n' % rmmodOutput ) + error( 'Error removing ' + mod + ': "%s">\n' % rmmodOutput ) exit( 1 ) if mod in lsmod(): error( 'Failed to remove ' + mod + '; still there!\n' ) @@ -48,7 +48,7 @@ def moduleDeps( subtract=None, add=None ): modprobeOutput = modprobe( mod ) if modprobeOutput: error( 'Error inserting ' + mod + '- is it installed?\n' + - 'Error was: <%s>\n' % modprobeOutput ) + 'Error was: "%s"\n' % modprobeOutput ) if mod not in lsmod(): error( 'Failed to insert ' + mod + '\n' ) exit( 1 ) From 6555c9294bf3c76f8733e7d8daab0d9ca9014a89 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 22:54:44 -0700 Subject: [PATCH 39/72] Added more hopefully useful information. We may want to start cutting things at some point - it looks more complicated than it really is! --- INSTALL | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index a4571be..95a25e8 100644 --- a/INSTALL +++ b/INSTALL @@ -64,6 +64,9 @@ http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes This places the mininet package in /usr/lib/python-*/site-packages/, so that 'import mininet' will work, and installs the primary mn script (mn) as well as its helper utility (mnexec.) + + On Ubuntu and Debian, Mininet's dependencies and core files may be + installed using mininet/util/install.sh -n 2. Script-based kernel and OpenFlow installation for Ubuntu/Debian Lenny @@ -86,7 +89,18 @@ http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes install all of these components (they're useful!), the kernel and OpenFlow software requirements are descibed in steps [3] and [4], which follow. - + + Many different installation options are possible; 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, for example: + + % 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 you successfully used install.sh, congratulations! You're basically done. Proceed to step [6] for additional advice. @@ -174,6 +188,9 @@ http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes 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 no other important processes, or on a virtual machine (recommended!) From f6149e4d189180cfa8938a166d3bcce53c890927 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 23:01:12 -0700 Subject: [PATCH 40/72] More edits. --- INSTALL | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/INSTALL b/INSTALL index 95a25e8..dc5e126 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Preliminary Mininet Installation/Configuration Notes -Pre-Beta release, August 2010 +Pre-Beta version, August 2010 --- @@ -73,34 +73,38 @@ http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes 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 other software including the OpenFlow reference implementation, the Open - vSwitch switch implementation, and the NOX OpenFlow controller. Assuming - the mininet source tree is installed in ~/mininet, the steps to run - install.sh are as follows: + vSwitch switch implementation, and the NOX OpenFlow controller. + 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 - % time ~/mininet/util/install.sh + % time ~/mininet/util/install.sh # installs tons of stuff % sudo reboot # to load new kernel % ~/mininet/util/install.sh -c # to clean out unneeded kernel stuff This installs a lot of useful software, but it will take a while (20 minutes or more, depending on your network connection, computer, etc..) - - If install.sh cannot be used for some reason, or if you don't want to - install all of these components (they're useful!), the kernel and - OpenFlow software requirements are descibed in steps [3] and [4], - which follow. - Many different installation options are possible; 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, for example: + 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, 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. + If you successfully used install.sh, congratulations! You're basically done. Proceed to step [6] for additional advice. @@ -113,7 +117,7 @@ http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes tearing down virtual ethernet pairs. For Ubuntu and Debian, we provide a 2.6.33 kernel package which you may be - able to install using "util/install.sh -x". Note our kernel package + able to install using "util/install.sh -k". Note our kernel package requires an ext2 or ext3 root file system, so it won't work if you have a default Ubuntu install, which uses ext4. From 2d48b4633c4f0dbd3602361682f5a205f9510462 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Tue, 17 Aug 2010 23:11:10 -0700 Subject: [PATCH 41/72] More installation edits. --- INSTALL | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/INSTALL b/INSTALL index dc5e126..e890d35 100644 --- a/INSTALL +++ b/INSTALL @@ -65,10 +65,10 @@ http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes so that 'import mininet' will work, and installs the primary mn script (mn) as well as its helper utility (mnexec.) - On Ubuntu and Debian, Mininet's dependencies and core files may be + On Ubuntu and Debian, Mininet's dependencies and core files may also be installed using mininet/util/install.sh -n -2. Script-based kernel and OpenFlow installation for Ubuntu/Debian Lenny +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 @@ -79,14 +79,14 @@ http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes 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: + install.sh to install EVERYTHING we use for OpenFlow tutorials are: % cd % time ~/mininet/util/install.sh # installs tons of stuff % sudo reboot # to load new kernel % ~/mininet/util/install.sh -c # to clean out unneeded kernel stuff - This installs a lot of useful software, but it will take a while (20 + This installs a lot of useful software, but it will take a while (30 minutes or more, depending on your network connection, computer, etc..) Probably the minimal semi-useful configuration would be to install @@ -100,7 +100,8 @@ http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes 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, or if you don't want to + 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. From ccca871ae65fee89b150fdff3ebad66677e93469 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Wed, 18 Aug 2010 00:18:09 -0700 Subject: [PATCH 42/72] Add passive listening port --- bin/mn | 6 +++++- mininet/net.py | 19 +++++++++++++------ mininet/node.py | 5 ++++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/bin/mn b/bin/mn index 9e50cbf..510af1a 100755 --- a/bin/mn +++ b/bin/mn @@ -176,6 +176,9 @@ class MininetRunner( object ): ' controller]' ) opts.add_option( '--innamespace', action='store_true', default=False, help='sw and ctrl in namespace?' ) + opts.add_option( '--listenport', type='int', default=6634, + help='[base port for passive switch listening' + ' controller]' ) opts.add_option( '--pre', type='string', default=None, help='[CLI script to run before tests]' ) opts.add_option( '--post', type='string', default=None, @@ -222,10 +225,11 @@ class MininetRunner( object ): xterms = self.options.xterms mac = self.options.mac arp = self.options.arp + listenPort = self.options.listenport mn = Mininet( topo, switch, host, controller, controllerParams, inNamespace=inNamespace, xterms=xterms, autoSetMacs=mac, - autoStaticArp=arp ) + autoStaticArp=arp, listenPort=listenPort ) if self.options.pre: CLI( mn, script=self.options.pre ) diff --git a/mininet/net.py b/mininet/net.py index 5f1bb44..d343207 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -108,7 +108,7 @@ class Mininet( object ): cparams=ControllerParams( '10.0.0.0', 8 ), build=True, xterms=False, cleanup=False, inNamespace=False, - autoSetMacs=False, autoStaticArp=False ): + autoSetMacs=False, autoStaticArp=False, listenPort=None ): """Create Mininet object. topo: Topo (topology) object or None switch: Switch class @@ -120,7 +120,9 @@ class Mininet( object ): cleanup: if build now, cleanup before creating? inNamespace: spawn switches and controller in net namespaces? 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.host = host self.controller = controller @@ -131,6 +133,7 @@ class Mininet( object ): self.cleanup = cleanup self.autoSetMacs = autoSetMacs self.autoStaticArp = autoStaticArp + self.listenPort = listenPort self.hosts = [] self.switches = [] @@ -162,13 +165,17 @@ class Mininet( object ): """Add switch. name: name of switch to add 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: - sw = self.switch( name, defaultMAC=mac, defaultIP=ip, - inNamespace=self.inNamespace ) + sw = self.switch( name, listenPort=self.listenPort, + defaultMAC=mac, defaultIP=ip, inNamespace=self.inNamespace ) 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 ) + if not self.inNamespace: + self.listenPort += 1 self.dps += 1 self.switches.append( sw ) self.nameToNode[ name ] = sw diff --git a/mininet/node.py b/mininet/node.py index 6380fee..6da4d70 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -434,9 +434,12 @@ class Switch( Node ): 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 ) self.opts = opts + self.listenPort = listenPort + if self.listenPort: + self.opts += ' --listen=ptcp:%i ' % self.listenPort def sendCmd( self, *cmd, **kwargs ): """Send command to Node. From b480b6ef7769331c0594b45679a4df45963579c4 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Wed, 18 Aug 2010 00:18:52 -0700 Subject: [PATCH 43/72] Add newline --- mininet/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index 6da4d70..748cde0 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -562,7 +562,7 @@ class OVSKernelSwitch( Switch ): self.intf = self.dp if self.inNamespace: error( "OVSKernelSwitch currently only works" - " in the root namespace." ) + " in the root namespace.\n" ) exit( 1 ) @staticmethod From 0a9358c9fc314725f8ce62a86f4d9c509d056b44 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Wed, 18 Aug 2010 00:29:15 -0700 Subject: [PATCH 44/72] Add option to turn off passive listening port --- bin/mn | 6 +++++- mininet/net.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bin/mn b/bin/mn index 510af1a..e1bd175 100755 --- a/bin/mn +++ b/bin/mn @@ -179,6 +179,8 @@ class MininetRunner( object ): 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") opts.add_option( '--pre', type='string', default=None, help='[CLI script to run before tests]' ) opts.add_option( '--post', type='string', default=None, @@ -225,7 +227,9 @@ class MininetRunner( object ): xterms = self.options.xterms mac = self.options.mac arp = self.options.arp - listenPort = self.options.listenport + listenPort = None + if not self.options.nolistenport: + listenPort = self.options.listenport mn = Mininet( topo, switch, host, controller, controllerParams, inNamespace=inNamespace, xterms=xterms, autoSetMacs=mac, diff --git a/mininet/net.py b/mininet/net.py index d343207..25623dc 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -174,7 +174,7 @@ class Mininet( object ): sw = self.switch( name, listenPort=self.listenPort, defaultMAC=mac, defaultIP=ip, dp=self.dps, inNamespace=self.inNamespace ) - if not self.inNamespace: + if not self.inNamespace and self.listenPort: self.listenPort += 1 self.dps += 1 self.switches.append( sw ) From 9da63d4e85d44bcda3ac9be0aa7bc42e031150c9 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Wed, 18 Aug 2010 01:45:36 -0700 Subject: [PATCH 45/72] Add dpctl command, which runs on all switches --- mininet/cli.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mininet/cli.py b/mininet/cli.py index a884316..a01f641 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -272,6 +272,20 @@ class CLI( Cmd ): error( 'error reading file %s\n' % args[ 0 ] ) 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 ): """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. From 4d1c17e17e80d3b23017b3e59697ea94460b39de Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Wed, 18 Aug 2010 02:30:18 -0700 Subject: [PATCH 46/72] Move kernel downloads to OpenFlow web page --- util/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/install.sh b/util/install.sh index c5ad00e..12ad1ff 100755 --- a/util/install.sh +++ b/util/install.sh @@ -9,7 +9,7 @@ set -e set -o nounset # Location of CONFIG_NET_NS-enabled kernel(s) -KERNEL_LOC=http://www.stanford.edu/~brandonh +KERNEL_LOC=http://www.openflow.org/downloads/mininet DIST=`lsb_release -is` From 9802686b3277322a7d10bf8ae6bebe08ddd25a4d Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 18 Aug 2010 10:04:42 -0700 Subject: [PATCH 47/72] Switches use high default intf; disable slicing for user switch. ;-( This should fix --switch user --innamespace. --- mininet/node.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index 748cde0..e41d83f 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -441,6 +441,14 @@ class Switch( Node ): 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 ) ] + print "RETURNING", intf + return intf + def sendCmd( self, *cmd, **kwargs ): """Send command to Node. cmd: string""" @@ -481,7 +489,7 @@ class UserSwitch( Switch ): if self.inNamespace: intfs = intfs[ :-1 ] self.cmd( 'ofdatapath -i ' + ','.join( intfs ) + - ' punix:/tmp/' + self.name + mac_str + + ' punix:/tmp/' + self.name + mac_str + ' --no-slicing ' + ' 1> ' + ofdlog + ' 2> ' + ofdlog + ' &' ) self.cmd( 'ofprotocol unix:/tmp/' + self.name + ' tcp:%s:%d' % ( controller.IP(), controller.port ) + From bd507eecfa14032066323c8fd0e5addf17f81d32 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 18 Aug 2010 10:07:57 -0700 Subject: [PATCH 48/72] Oops, get rid of debug print. --- mininet/node.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index e41d83f..10111b1 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -446,7 +446,6 @@ class Switch( Node ): ports = self.intfs.keys() if ports: intf = self.intfs[ max( ports ) ] - print "RETURNING", intf return intf def sendCmd( self, *cmd, **kwargs ): From a77e7a029ea23ebf3022ee68bd0a50a497723a60 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 18 Aug 2010 10:23:14 -0700 Subject: [PATCH 49/72] Update for openflow.org URLs. --- INSTALL | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/INSTALL b/INSTALL index e890d35..d74a02e 100644 --- a/INSTALL +++ b/INSTALL @@ -10,12 +10,12 @@ Pre-Beta version, August 2010 The easiest way to get Mininet running is to start with one of our pre-built virtual machine images from: -http://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetGettingStarted +http://openflow.org/foswiki/bin/view/OpenFlow/MininetGettingStarted Once you have booted up the VM image, all you need to do to install Mininet into it is: - git clone git://yuba.stanford.edu/mininet.git + git clone git://openflow.org/mininet.git cd mininet sudo make install @@ -40,14 +40,14 @@ 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://www.openflowswitch.org/foswiki/bin/view/OpenFlow/MininetVMCreationNotes +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://yuba.stanford.edu/mininet.git + git clone git://openflow.org/mininet.git 1. Core Mininet installation From f9654e5654e59a6b9f61535243aa62573e47a673 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 18 Aug 2010 10:58:24 -0700 Subject: [PATCH 50/72] Better error messages when switch setup() fails. --- mininet/moduledeps.py | 16 +++++++++------- mininet/node.py | 12 ++++++++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/mininet/moduledeps.py b/mininet/moduledeps.py index 9592928..b72bac3 100644 --- a/mininet/moduledeps.py +++ b/mininet/moduledeps.py @@ -47,19 +47,21 @@ def moduleDeps( subtract=None, add=None ): info( '*** Loading ' + mod + '\n' ) modprobeOutput = modprobe( mod ) if modprobeOutput: - error( 'Error inserting ' + mod + '- is it installed?\n' + - 'Error was: "%s"\n' % modprobeOutput ) + error( 'Error inserting ' + mod + + ' - is it installed and available via modprobe?\n' + + 'Error was: "%s"\n' % modprobeOutput ) if mod not in lsmod(): - error( 'Failed to insert ' + mod + '\n' ) + error( 'Failed to insert ' + mod + ' - quitting.\n' ) exit( 1 ) else: debug( '*** ' + mod + ' already loaded\n' ) -def pathCheck( *args ): +def pathCheck( *args, **kwargs ): "Make sure each program in *args can be found in $PATH." + moduleName = kwargs.get( 'moduleName', 'it' ) for arg in args: if not quietRun( 'which ' + arg ): - error( 'Cannot find required executable %s -' - ' is it installed somewhere in your $PATH?\n(%s)\n' % - ( arg, environ[ 'PATH' ] ) ) + error( 'Cannot find required executable %s.\n' % arg + + 'Please make sure that %s is installed ' % moduleName + + 'and available in your $PATH:\n(%s)\n' % environ[ 'PATH' ] ) exit( 1 ) diff --git a/mininet/node.py b/mininet/node.py index 10111b1..3c2521c 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -465,7 +465,8 @@ class UserSwitch( Switch ): """Init. name: name for the switch""" Switch.__init__( self, name, **kwargs ) - pathCheck( 'ofdatapath', 'ofprotocol' ) + pathCheck( 'ofdatapath', 'ofprotocol', + moduleName='the OpenFlow reference user switch (openflow.org)' ) @staticmethod def setup(): @@ -521,8 +522,10 @@ class KernelSwitch( Switch ): @staticmethod def setup(): "Ensure any dependencies are loaded; if not, try to load them." + pathCheck( 'ofprotocol', + moduleName='the OpenFlow reference kernel switch' + ' (openflow.org) (NOTE: not available in OpenFlow 1.0!)' ) moduleDeps( subtract=OVS_KMOD, add=OF_KMOD ) - pathCheck( 'ofprotocol' ) def start( self, controllers ): "Start up reference kernel datapath." @@ -575,8 +578,9 @@ class OVSKernelSwitch( Switch ): @staticmethod def setup(): "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 ): "Start up kernel datapath." From 4800435d1a9acf54d1d2efec1ce51085ef21e9b5 Mon Sep 17 00:00:00 2001 From: Brandon Heller Date: Wed, 18 Aug 2010 04:43:39 -0700 Subject: [PATCH 51/72] vm: Don't exit if some files aren't there --- util/install.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/util/install.sh b/util/install.sh index 12ad1ff..89f8639 100755 --- a/util/install.sh +++ b/util/install.sh @@ -310,22 +310,23 @@ function vm_clean { # Remove sensistive files history -c # note this won't work if you have multiple bash sessions - rm ~/.bash_history # need to clear in memory and remove on disk + rm -f ~/.bash_history # need to clear in memory and remove on disk rm -f ~/.ssh/id_rsa* ~/.ssh/known_hosts - sudo rm ~/.ssh/authorized_keys2 + sudo rm -f ~/.ssh/authorized_keys2 # Remove Mininet files #sudo rm -f /lib/modules/python2.5/site-packages/mininet* #sudo rm -f /usr/bin/mnexec # Clear optional dev script for SSH keychain load on boot - rm ~/.bash_profile + rm -f ~/.bash_profile # Clear git changes git config --global user.name "None" git config --global user.email "None" - #sudo rm -rf ~/mininet + # Remove mininet install script + rm -f install-mininet.sh } function usage { From cc16d2ce29621fd777dfc0cd3cedad48966512c5 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 18 Aug 2010 23:33:05 -0700 Subject: [PATCH 52/72] Attempt to fix OS detection for Debian. --- util/install.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/install.sh b/util/install.sh index 89f8639..0cb4414 100755 --- a/util/install.sh +++ b/util/install.sh @@ -11,7 +11,8 @@ set -o nounset # Location of CONFIG_NET_NS-enabled kernel(s) KERNEL_LOC=http://www.openflow.org/downloads/mininet -DIST=`lsb_release -is` +test -e /etc/debian_version && DIST="Debian" +grep Ubuntu /etc/lsb-release &> /dev/null && DIST="Ubuntu" # Kernel params # These kernels have been tried: @@ -27,6 +28,8 @@ else exit 1 fi +echo "Detected Linux distribution: $DIST" + # Kernel Deb pkg to be removed: KERNEL_IMAGE_OLD=linux-image-2.6.26-2-686 From 05c2d669a92afa214b6f98a05c28084d2c4083a3 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 18 Aug 2010 23:39:07 -0700 Subject: [PATCH 53/72] Add make to mininet deps. --- util/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/install.sh b/util/install.sh index 0cb4414..17d22ff 100755 --- a/util/install.sh +++ b/util/install.sh @@ -82,7 +82,7 @@ function kernel_clean { # Install Mininet deps function mn_deps { echo "Installing Mininet dependencies" - sudo apt-get install -y gcc screen psmisc xterm ssh iperf iproute python-setuptools + sudo apt-get install -y gcc make screen psmisc xterm ssh iperf iproute python-setuptools #Add sysctl parameters as noted in the INSTALL file to increase kernel limits to support larger setups: sudo su -c "cat $HOME/mininet/util/sysctl_addon >> /etc/sysctl.conf" From e900a16caf0c1c9342890cdefa75d8bc9e56822d Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Thu, 19 Aug 2010 14:42:33 -0700 Subject: [PATCH 54/72] Don't try to modprobe tun if it's built-in (e.g. Ubuntu.) --- mininet/node.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index 3c2521c..1f4f51d 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -471,7 +471,8 @@ class UserSwitch( Switch ): @staticmethod def setup(): "Ensure any dependencies are loaded; if not, try to load them." - moduleDeps( add=TUN ) + if not os.path.exists( '/dev/net/tun' ): + moduleDeps( add=TUN ) def start( self, controllers ): """Start OpenFlow reference user datapath. From 40beaabc14745c03feb7e6a66c79caee0c34990e Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Thu, 19 Aug 2010 16:45:11 -0700 Subject: [PATCH 55/72] More edits for pre-beta. --- INSTALL | 62 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/INSTALL b/INSTALL index d74a02e..562c2cd 100644 --- a/INSTALL +++ b/INSTALL @@ -2,31 +2,67 @@ Preliminary Mininet Installation/Configuration Notes Pre-Beta version, August 2010 - --- (Disclaimer: we're still pre-beta - things may be broken!) +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!) + +1. Easiest "install" - use our pre-built VM image! + The easiest way to get Mininet running is to start with one of our pre-built virtual machine images from: -http://openflow.org/foswiki/bin/view/OpenFlow/MininetGettingStarted + http://openflow.org/foswiki/bin/view/OpenFlow/MininetGettingStarted -Once you have booted up the VM image, all you need to do to install -Mininet into it is: +Boot up the VM image, log in, and follow the instructions on the wiki page. - git clone git://openflow.org/mininet.git - cd mininet - sudo make install +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. -At this point, it should be possible to run a simple Mininet configuration -from the command line: +2. Native installation for Ubuntu and Debian 5 (NEW for pre-beta!) - sudo mn +If you are running Ubuntu or Debian 5, you may be able to use our handy +install.sh script, which is in mininet/util. -As an alternative, if you are Linux-savvy, do not wish to use the VM -image, and wish to take on the challenge of installing Mininet and its -dependencies from scratch, the requirements are described below. +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 OpenFlow 1.0 and associated useful software + $ mininet/util/install.sh -f + +c) Install Open vSwitch + $ mininet/util/install.sh -f + +d) 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. --- From ee7ee4065c7d42241e61a60abbc56f2c2e593699 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Thu, 19 Aug 2010 16:48:02 -0700 Subject: [PATCH 56/72] Get the options right... --- INSTALL | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/INSTALL b/INSTALL index 562c2cd..34b9e10 100644 --- a/INSTALL +++ b/INSTALL @@ -51,12 +51,15 @@ a) On Debian 5, first install a Mininet-compatible kernel: b) Install OpenFlow 1.0 and associated useful software $ mininet/util/install.sh -f -c) Install Open vSwitch - $ mininet/util/install.sh -f +c) Install Open vSwitch and its kernel module + $ mininet/util/install.sh -vm d) If you wish to install the version of NOX we use in the tutorial: $ mininet/util/install.sh -x +e) Install mininet and its dependencies: + $ mininet/util/install.sh -n + 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. From ec226c9b83c5049a33edd08b824045c9fde30166 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Thu, 19 Aug 2010 16:49:06 -0700 Subject: [PATCH 57/72] Better order - kernel first, then mininet, then everything else. --- INSTALL | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/INSTALL b/INSTALL index 34b9e10..57046f2 100644 --- a/INSTALL +++ b/INSTALL @@ -47,19 +47,19 @@ 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 OpenFlow 1.0 and associated useful software + +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 -c) Install Open vSwitch and its kernel module +d) Install Open vSwitch and its kernel module $ mininet/util/install.sh -vm -d) If you wish to install the version of NOX we use in the tutorial: +e) If you wish to install the version of NOX we use in the tutorial: $ mininet/util/install.sh -x -e) Install mininet and its dependencies: - $ mininet/util/install.sh -n - 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. From cc960215fc44ecc782e645e872b5b30598662924 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Thu, 19 Aug 2010 20:53:40 -0700 Subject: [PATCH 58/72] Added --prefixlen option - this may help with router tutorial. --- bin/mn | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/mn b/bin/mn index e1bd175..903e186 100755 --- a/bin/mn +++ b/bin/mn @@ -55,7 +55,7 @@ TESTS = [ 'cli', 'build', 'pingall', 'pingpair', 'iperf', 'all', 'iperfudp', 'none' ] ALTSPELLING = { 'pingall': 'pingAll', 'pingpair': 'pingPair', - 'iperfudp': 'iperfUdp', 'iperfUDP': 'iperfUdp' } + 'iperfudp': 'iperfUdp', 'iperfUDP': 'iperfUdp', 'prefixlen': 'prefixLen' } def buildTopo( topo ): "Create topology from string with format (object, arg1, arg2,...)." @@ -185,7 +185,8 @@ class MininetRunner( object ): help='[CLI script to run before tests]' ) opts.add_option( '--post', type='string', default=None, help='[CLI script to run after tests]' ) - + opts.add_option( '--prefixlen', type='int', default=8, + help='[prefix length (e.g. /8) for automatic network configuration]' ) self.options, self.args = opts.parse_args() def setup( self ): @@ -222,7 +223,12 @@ class MininetRunner( object ): if self.validate: self.validate( self.options ) - 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) + inNamespace = self.options.innamespace xterms = self.options.xterms mac = self.options.mac From 5c24e18639876428ae74379b0fb22f6005bdb3ac Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Fri, 20 Aug 2010 08:48:10 -0700 Subject: [PATCH 59/72] Disable (broken) scripting for interactive commands. --- mininet/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mininet/cli.py b/mininet/cli.py index a01f641..3fbedd1 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -328,7 +328,8 @@ class CLI( Cmd ): while True: try: 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 ) if key is not '': node.write(key) From fe769afa224d762d060277595e43a32bf248eac3 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 19:46:48 -0700 Subject: [PATCH 60/72] Added port to controller args; changed NOX to new arg format. --- mininet/node.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index 1f4f51d..3673c11 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -200,7 +200,6 @@ class Node( object ): """Monitor and return the output of a command. Set self.waiting to False if command has completed. timeoutms: timeout in ms or None to wait indefinitely.""" - assert self.waiting self.waitReadable( timeoutms ) data = self.read( 1024 ) # Look for PID @@ -623,7 +622,7 @@ class Controller( Node ): OpenFlow controller.""" def __init__( self, name, inNamespace=False, controller='controller', - cargs='-v ptcp:', cdir=None, defaultIP="127.0.0.1", + cargs='-v ptcp:%d', cdir=None, defaultIP="127.0.0.1", port=6633 ): self.controller = controller self.cargs = cargs @@ -639,7 +638,7 @@ class Controller( Node ): cout = '/tmp/' + self.name + '.log' if self.cdir is not None: self.cmd( 'cd ' + self.cdir ) - self.cmd( self.controller + ' ' + self.cargs + + self.cmd( self.controller + ' ' + self.cargs % self.port + ' 1>' + cout + ' 2>' + cout + '&' ) self.execed = False @@ -684,7 +683,7 @@ class NOX( Controller ): Controller.__init__( self, name, controller=noxCoreDir + '/nox_core', - cargs='--libdir=/usr/local/lib -v -i ptcp: ' + + cargs='--libdir=/usr/local/lib -v -i ptcp::%s ' % self.port + ' '.join( noxArgs ), cdir=noxCoreDir, **kwargs ) From 2a75022403be210e430464d7eef671b0dad1ee28 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 19:50:00 -0700 Subject: [PATCH 61/72] Fixed args for nox. --- mininet/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mininet/node.py b/mininet/node.py index 3673c11..1b7da65 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -683,7 +683,7 @@ class NOX( Controller ): Controller.__init__( self, name, controller=noxCoreDir + '/nox_core', - cargs='--libdir=/usr/local/lib -v -i ptcp::%s ' % self.port + + cargs='--libdir=/usr/local/lib -v -i ptcp:%s ' % self.port + ' '.join( noxArgs ), cdir=noxCoreDir, **kwargs ) From eaf5888ae048e0f2e02b0751a2786da4b802e534 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 19:50:30 -0700 Subject: [PATCH 62/72] Added controller class arg to addController(). --- mininet/net.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mininet/net.py b/mininet/net.py index 25623dc..13a01dd 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -94,7 +94,7 @@ from time import sleep from mininet.cli import CLI 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.util import quietRun, fixLimits from mininet.util import createLink, macColonHex, ipStr, ipParse @@ -103,7 +103,7 @@ from mininet.term import cleanUpScreens, makeTerms class Mininet( object ): "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, cparams=ControllerParams( '10.0.0.0', 8 ), build=True, xterms=False, cleanup=False, @@ -181,13 +181,16 @@ class Mininet( object ): self.nameToNode[ name ] = sw return sw - def addController( self, name='c0', **kwargs ): + def addController( self, name='c0', Controller=None, **kwargs ): """Add controller. - controller: Controller class""" - controller_new = self.controller( name, **kwargs ) + Controller: Controller class""" + if not Controller: + Controller = self.controller + controller_new = Controller( name, **kwargs ) if controller_new: # allow controller-less setups self.controllers.append( controller_new ) self.nameToNode[ name ] = controller_new + return controller_new # Control network support: # From 73a098a499a76f4ae5c54c948fb4bfd5a32191f2 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 19:51:09 -0700 Subject: [PATCH 63/72] Use __dict__.update to update an object's fields. --- examples/consoles.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/consoles.py b/examples/consoles.py index 54fb32c..607163d 100755 --- a/examples/consoles.py +++ b/examples/consoles.py @@ -448,8 +448,7 @@ class ConsoleApp( Frame ): def assign( obj, **kwargs ): "Set a bunch of fields in an object." - for name, value in kwargs.items(): - setattr( obj, name, value ) + obj.__dict__.update( kwargs ) class Object( object ): "Generic object you can stuff junk into." From cde0c25bfe2da8efef27d0d70cad9dab1d624a88 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 19:51:54 -0700 Subject: [PATCH 64/72] Fix for new networkx. --- mininet/topo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mininet/topo.py b/mininet/topo.py index 07f74ef..d89b988 100644 --- a/mininet/topo.py +++ b/mininet/topo.py @@ -11,7 +11,7 @@ A Topo object can be a topology database for NOX, can represent a physical setup for testing, and can even be emulated with the Mininet package. ''' -from networkx.classes.graph import Graph +from networkx import Graph from mininet.node import SWITCH_PORT_BASE class NodeID(object): From 276bdaf0d399ee89deba533b8b863ec4c341c707 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 19:52:30 -0700 Subject: [PATCH 65/72] Added more dependencies for some installs and for Debian. --- util/install.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/util/install.sh b/util/install.sh index 17d22ff..d9eba1a 100755 --- a/util/install.sh +++ b/util/install.sh @@ -82,7 +82,8 @@ function kernel_clean { # Install Mininet deps function mn_deps { echo "Installing Mininet dependencies" - sudo apt-get install -y gcc make 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: sudo su -c "cat $HOME/mininet/util/sysctl_addon >> /etc/sysctl.conf" @@ -144,6 +145,7 @@ function ovs { 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: #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" @@ -165,7 +167,10 @@ function ovs { cd $OVS_RELEASE ./boot.sh BUILDDIR=/lib/modules/${KERNEL_NAME}/build - mkdir -p $BUILDDIR + if [ ! -e $BUILDDIR ]; then + echo "Creating build directory $BUILDDIR" + sudo mkdir -p $BUILDDIR + fi opts="--with-l26=$BUILDDIR" ./configure $opts make @@ -352,7 +357,7 @@ function usage { 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 NOX(X) OpenFlow contoller\n' >&2 + printf -- ' -x: install NO(X) OpenFlow controller\n' >&2 printf -- ' -y: install (A)ll packages\n' >&2 exit 2 From e0e69bbeec118e8ccd43f2ce9b6f6fed0c5903f5 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 19:53:09 -0700 Subject: [PATCH 66/72] Added new example of multiple controllers. --- examples/controllers.py | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100755 examples/controllers.py diff --git a/examples/controllers.py b/examples/controllers.py new file mode 100755 index 0000000..340089d --- /dev/null +++ b/examples/controllers.py @@ -0,0 +1,60 @@ +#!/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(): + + 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" + [ s1.linkTo( h ) for h in hosts1 ] + [ s2.linkTo( h ) for h in hosts2 ] + s1.linkTo( s2 ) + + print "*** Starting network" + net.build() + [ controller.start() for controller in c1, c2 ] + 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() From 300efb2b803efe234c24d81cc7f835a05f1ed6c4 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 19:54:10 -0700 Subject: [PATCH 67/72] Added simple example of using API just to create a namespace. --- examples/baresshd.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100755 examples/baresshd.py diff --git a/examples/baresshd.py b/examples/baresshd.py new file mode 100755 index 0000000..841454a --- /dev/null +++ b/examples/baresshd.py @@ -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() From 444f9d8d7660bddf03d0a01c58cb1c77fcbe01cf Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 20:50:28 -0700 Subject: [PATCH 68/72] Pass code check. --- bin/mn | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bin/mn b/bin/mn index 903e186..5b5547d 100755 --- a/bin/mn +++ b/bin/mn @@ -186,7 +186,8 @@ class MininetRunner( object ): opts.add_option( '--post', type='string', default=None, help='[CLI script to run after tests]' ) opts.add_option( '--prefixlen', type='int', default=8, - help='[prefix length (e.g. /8) for automatic network configuration]' ) + help='[prefix length (e.g. /8) for automatic ' + 'network configuration]' ) self.options, self.args = opts.parse_args() def setup( self ): @@ -226,7 +227,7 @@ class MininetRunner( object ): # 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', + controllerParams = ControllerParams( '10.0.0.0', self.options.prefixlen) inNamespace = self.options.innamespace From 74a56e2bae7f2cc87795d2a79daeaef28c4bac0d Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 20:50:42 -0700 Subject: [PATCH 69/72] Pass code check. --- examples/controllers.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/controllers.py b/examples/controllers.py index 340089d..6eeef0e 100755 --- a/examples/controllers.py +++ b/examples/controllers.py @@ -20,6 +20,7 @@ def addHost( net, N ): return net.addHost( name, ip=ip ) def multiControllerNet(): + "Create a network with multiple controllers." net = Mininet( controller=Controller, switch=Switch) @@ -36,13 +37,16 @@ def multiControllerNet(): hosts2 = [ addHost( net, n ) for n in 5, 6 ] print "*** Creating links" - [ s1.linkTo( h ) for h in hosts1 ] - [ s2.linkTo( h ) for h in hosts2 ] + for h in hosts1: + s1.linkTo( h ) + for h in hosts2: + s2.linkTo( h ) s1.linkTo( s2 ) print "*** Starting network" net.build() - [ controller.start() for controller in c1, c2 ] + c1.start() + c2.start() s1.start( [ c1 ] ) s2.start( [ c2 ] ) From 55ca2d0c96fdf0dbf7237959d1d4f49512862c98 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 20:51:27 -0700 Subject: [PATCH 70/72] Pass code check. --- mininet/moduledeps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mininet/moduledeps.py b/mininet/moduledeps.py index b72bac3..2e154b1 100644 --- a/mininet/moduledeps.py +++ b/mininet/moduledeps.py @@ -47,7 +47,7 @@ def moduleDeps( subtract=None, add=None ): info( '*** Loading ' + mod + '\n' ) modprobeOutput = modprobe( mod ) if modprobeOutput: - error( 'Error inserting ' + mod + + error( 'Error inserting ' + mod + ' - is it installed and available via modprobe?\n' + 'Error was: "%s"\n' % modprobeOutput ) if mod not in lsmod(): @@ -62,6 +62,6 @@ def pathCheck( *args, **kwargs ): for arg in args: if not quietRun( 'which ' + arg ): error( 'Cannot find required executable %s.\n' % arg + - 'Please make sure that %s is installed ' % moduleName + + 'Please make sure that %s is installed ' % moduleName + 'and available in your $PATH:\n(%s)\n' % environ[ 'PATH' ] ) exit( 1 ) From e30f2c99c235cdafb344dd473bade22d409ee3b7 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 20:51:40 -0700 Subject: [PATCH 71/72] Rename Controller.controller to .command --- mininet/net.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mininet/net.py b/mininet/net.py index 13a01dd..bf25330 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -181,12 +181,12 @@ class Mininet( object ): self.nameToNode[ name ] = sw return sw - def addController( self, name='c0', Controller=None, **kwargs ): + def addController( self, name='c0', controller=None, **kwargs ): """Add controller. - Controller: Controller class""" - if not Controller: - Controller = self.controller - controller_new = Controller( name, **kwargs ) + controller: Controller class""" + if not controller: + controller = self.controller + controller_new = controller( name, **kwargs ) if controller_new: # allow controller-less setups self.controllers.append( controller_new ) self.nameToNode[ name ] = controller_new From 57fd19efaa164b78f9e531294db7c5f4a4cdb398 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Wed, 1 Sep 2010 20:52:29 -0700 Subject: [PATCH 72/72] Rename Controller.controller to .command --- mininet/node.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index 1b7da65..da1f204 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -464,7 +464,7 @@ class UserSwitch( Switch ): """Init. name: name for the switch""" Switch.__init__( self, name, **kwargs ) - pathCheck( 'ofdatapath', 'ofprotocol', + pathCheck( 'ofdatapath', 'ofprotocol', moduleName='the OpenFlow reference user switch (openflow.org)' ) @staticmethod @@ -621,10 +621,10 @@ class Controller( Node ): """A Controller is a Node that is running (or has execed?) an OpenFlow controller.""" - def __init__( self, name, inNamespace=False, controller='controller', + def __init__( self, name, inNamespace=False, command='controller', cargs='-v ptcp:%d', cdir=None, defaultIP="127.0.0.1", port=6633 ): - self.controller = controller + self.command = command self.cargs = cargs self.cdir = cdir self.port = port @@ -634,17 +634,17 @@ class Controller( Node ): def start( self ): """Start on controller. Log to /tmp/cN.log""" - pathCheck( self.controller ) + pathCheck( self.command ) cout = '/tmp/' + self.name + '.log' if self.cdir is not None: self.cmd( 'cd ' + self.cdir ) - self.cmd( self.controller + ' ' + self.cargs % self.port + + self.cmd( self.command + ' ' + self.cargs % self.port + ' 1>' + cout + ' 2>' + cout + '&' ) self.execed = False def stop( self ): "Stop controller." - self.cmd( 'kill %' + self.controller ) + self.cmd( 'kill %' + self.command ) self.terminate() def IP( self, intf=None ): @@ -682,7 +682,7 @@ class NOX( Controller ): noxCoreDir = os.environ[ 'NOX_CORE_DIR' ] Controller.__init__( self, name, - controller=noxCoreDir + '/nox_core', + command=noxCoreDir + '/nox_core', cargs='--libdir=/usr/local/lib -v -i ptcp:%s ' % self.port + ' '.join( noxArgs ), cdir=noxCoreDir, **kwargs )