Merge branch 'ivs' of https://github.com/rlane/mininet into rlane-ivs

Conflicts:
	util/install.sh

fixes #159
This commit is contained in:
Bob Lantz
2013-07-31 18:20:18 -07:00
6 changed files with 169 additions and 52 deletions
+3 -2
View File
@@ -26,7 +26,7 @@ from mininet.log import lg, LEVELS, info, debug, error
from mininet.net import Mininet, MininetWithControlNet, VERSION from mininet.net import Mininet, MininetWithControlNet, VERSION
from mininet.node import ( Host, CPULimitedHost, Controller, OVSController, from mininet.node import ( Host, CPULimitedHost, Controller, OVSController,
NOX, RemoteController, UserSwitch, OVSKernelSwitch, NOX, RemoteController, UserSwitch, OVSKernelSwitch,
OVSLegacyKernelSwitch ) OVSLegacyKernelSwitch, IVSSwitch )
from mininet.link import Link, TCLink from mininet.link import Link, TCLink
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
from mininet.topolib import TreeTopo from mininet.topolib import TreeTopo
@@ -45,7 +45,8 @@ TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
SWITCHDEF = 'ovsk' SWITCHDEF = 'ovsk'
SWITCHES = { 'user': UserSwitch, SWITCHES = { 'user': UserSwitch,
'ovsk': OVSKernelSwitch, 'ovsk': OVSKernelSwitch,
'ovsl': OVSLegacyKernelSwitch } 'ovsl': OVSLegacyKernelSwitch,
'ivs': IVSSwitch }
HOSTDEF = 'proc' HOSTDEF = 'proc'
HOSTS = { 'proc': Host, HOSTS = { 'proc': Host,
+6 -2
View File
@@ -11,6 +11,7 @@ nothing irreplaceable!
""" """
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
import time
from mininet.log import info from mininet.log import info
from mininet.term import cleanUpScreens from mininet.term import cleanUpScreens
@@ -27,10 +28,13 @@ def cleanup():
info("*** Removing excess controllers/ofprotocols/ofdatapaths/pings/noxes" info("*** Removing excess controllers/ofprotocols/ofdatapaths/pings/noxes"
"\n") "\n")
zombies = 'controller ofprotocol ofdatapath ping nox_core lt-nox_core ' zombies = 'controller ofprotocol ofdatapath ping nox_core lt-nox_core '
zombies += 'ovs-openflowd ovs-controller udpbwtest mnexec' zombies += 'ovs-openflowd ovs-controller udpbwtest mnexec ivs'
# Note: real zombie processes can't actually be killed, since they # Note: real zombie processes can't actually be killed, since they
# are already (un)dead. Then again, # are already (un)dead. Then again,
# you can't connect to them either, so they're mostly harmless. # you can't connect to them either, so they're mostly harmless.
# Send SIGTERM first to give processes a chance to shutdown cleanly.
sh( 'killall ' + zombies + ' 2> /dev/null' )
time.sleep(1)
sh( 'killall -9 ' + zombies + ' 2> /dev/null' ) sh( 'killall -9 ' + zombies + ' 2> /dev/null' )
# And kill off sudo mnexec # And kill off sudo mnexec
@@ -49,7 +53,7 @@ def cleanup():
sh( 'dpctl deldp ' + dp ) sh( 'dpctl deldp ' + dp )
info( "*** Removing OVS datapaths" ) info( "*** Removing OVS datapaths" )
dps = sh("ovs-vsctl list-br").split( '\n' ) dps = sh("ovs-vsctl --timeout=1 list-br").split( '\n' )
for dp in dps: for dp in dps:
if dp: if dp:
sh( 'ovs-vsctl del-br ' + dp ) sh( 'ovs-vsctl del-br ' + dp )
+58
View File
@@ -1026,6 +1026,64 @@ class OVSSwitch( Switch ):
OVSKernelSwitch = OVSSwitch OVSKernelSwitch = OVSSwitch
class IVSSwitch(Switch):
"""IVS virtual switch"""
def __init__( self, name, **kwargs ):
Switch.__init__( self, name, **kwargs )
@classmethod
def setup( cls ):
"Make sure IVS is installed"
pathCheck( 'ivs-ctl', 'ivs',
moduleName="Indigo Virtual Switch (projectfloodlight.org)" )
out, err, exitcode = errRun( 'ivs-ctl show' )
if exitcode:
error( out + err +
'ivs-ctl exited with code %d\n' % exitcode +
'*** The openvswitch kernel module might '
'not be loaded. Try modprobe openvswitch.\n' )
exit( 1 )
def start( self, controllers ):
"Start up a new IVS switch"
args = ['ivs']
args.extend( ['--name', self.name] )
args.extend( ['--dpid', self.dpid] )
args.extend( ['--verbose'] )
for intf in self.intfs.values():
if not intf.IP():
args.extend( ['-i', intf.name] )
for c in controllers:
args.extend( ['-c', '%s:%d' % (c.IP(), c.port)] )
if self.listenPort:
args.extend( ['--listen', '127.0.0.1:%i' % self.listenPort] )
logfile = '/tmp/ivs.%s.log' % self.name
self.cmd( ' '.join(args) + ' >' + logfile + ' 2>&1 </dev/null &' )
def stop( self ):
"Terminate IVS switch."
self.cmd( 'kill %ivs' )
self.deleteIntfs()
def attach( self, intf ):
"Connect a data port"
self.cmd( 'ivs-ctl', 'add-port', '--datapath', self.name, intf )
def detach( self, intf ):
"Disconnect a data port"
self.cmd( 'ivs-ctl', 'del-port', '--datapath', self.name, intf )
def dpctl( self, *args ):
"Run dpctl command"
if not self.listenPort:
return "can't run dpctl without passive listening port"
return self.cmd( 'ovs-ofctl ' + ' '.join( args ) +
' tcp:127.0.0.1:%i' % self.listenPort )
class Controller( Node ): class Controller( Node ):
"""A Controller is a Node that is running (or has execed?) an """A Controller is a Node that is running (or has execed?) an
OpenFlow controller.""" OpenFlow controller."""
+21 -10
View File
@@ -6,14 +6,12 @@
import unittest import unittest
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import OVSKernelSwitch from mininet.node import OVSKernelSwitch, UserSwitch, IVSSwitch
from mininet.node import CPULimitedHost from mininet.node import CPULimitedHost
from mininet.link import TCLink from mininet.link import TCLink
from mininet.topo import Topo from mininet.topo import Topo
from mininet.log import setLogLevel from mininet.log import setLogLevel
SWITCH = OVSKernelSwitch
# Number of hosts for each test # Number of hosts for each test
N = 2 N = 2
@@ -32,14 +30,16 @@ class SingleSwitchOptionsTopo(Topo):
self.addLink(host, switch) self.addLink(host, switch)
class testOptionsTopo( unittest.TestCase ): class testOptionsTopoCommon( object ):
"Verify ability to create networks with host and link options." "Verify ability to create networks with host and link options (common code)."
switchClass = None # overridden in subclasses
def runOptionsTopoTest( self, n, hopts=None, lopts=None ): def runOptionsTopoTest( self, n, hopts=None, lopts=None ):
"Generic topology-with-options test runner." "Generic topology-with-options test runner."
mn = Mininet( topo=SingleSwitchOptionsTopo( n=n, hopts=hopts, mn = Mininet( topo=SingleSwitchOptionsTopo( n=n, hopts=hopts,
lopts=lopts ), lopts=lopts ),
host=CPULimitedHost, link=TCLink ) host=CPULimitedHost, link=TCLink, switch=self.switchClass )
dropped = mn.run( mn.ping ) dropped = mn.run( mn.ping )
self.assertEqual( dropped, 0 ) self.assertEqual( dropped, 0 )
@@ -58,7 +58,7 @@ class testOptionsTopo( unittest.TestCase ):
#self.runOptionsTopoTest( N, hopts=hopts ) #self.runOptionsTopoTest( N, hopts=hopts )
mn = Mininet( SingleSwitchOptionsTopo( n=N, hopts=hopts ), mn = Mininet( SingleSwitchOptionsTopo( n=N, hopts=hopts ),
host=CPULimitedHost ) host=CPULimitedHost, switch=self.switchClass )
mn.start() mn.start()
results = mn.runCpuLimitTest( cpu=CPU_FRACTION ) results = mn.runCpuLimitTest( cpu=CPU_FRACTION )
mn.stop() mn.stop()
@@ -73,7 +73,7 @@ class testOptionsTopo( unittest.TestCase ):
lopts = { 'bw': BW, 'use_htb': True } lopts = { 'bw': BW, 'use_htb': True }
# Also verify correctness of limit limitng within a bound. # Also verify correctness of limit limitng within a bound.
mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ), mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ),
link=TCLink ) link=TCLink, switch=self.switchClass )
bw_strs = mn.run( mn.iperf ) bw_strs = mn.run( mn.iperf )
for bw_str in bw_strs: for bw_str in bw_strs:
bw = float( bw_str.split(' ')[0] ) bw = float( bw_str.split(' ')[0] )
@@ -85,7 +85,7 @@ class testOptionsTopo( unittest.TestCase ):
DELAY_TOLERANCE = 0.8 # Delay fraction below which test should fail DELAY_TOLERANCE = 0.8 # Delay fraction below which test should fail
lopts = { 'delay': '%sms' % DELAY_MS, 'use_htb': True } lopts = { 'delay': '%sms' % DELAY_MS, 'use_htb': True }
mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ), mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ),
link=TCLink ) link=TCLink, switch=self.switchClass )
ping_delays = mn.run( mn.pingFull ) ping_delays = mn.run( mn.pingFull )
test_outputs = ping_delays[0] test_outputs = ping_delays[0]
# Ignore unused variables below # Ignore unused variables below
@@ -105,7 +105,7 @@ class testOptionsTopo( unittest.TestCase ):
REPS = 1 REPS = 1
lopts = { 'loss': LOSS_PERCENT, 'use_htb': True } lopts = { 'loss': LOSS_PERCENT, 'use_htb': True }
mn = Mininet( topo=SingleSwitchOptionsTopo( n=N, lopts=lopts ), mn = Mininet( topo=SingleSwitchOptionsTopo( n=N, lopts=lopts ),
host=CPULimitedHost, link=TCLink ) host=CPULimitedHost, link=TCLink, switch=self.switchClass )
# Drops are probabilistic, but the chance of no dropped packets is # Drops are probabilistic, but the chance of no dropped packets is
# 1 in 100 million with 4 hops for a link w/99% loss. # 1 in 100 million with 4 hops for a link w/99% loss.
dropped_total = 0 dropped_total = 0
@@ -121,6 +121,17 @@ class testOptionsTopo( unittest.TestCase ):
hopts = { 'cpu': 0.5 / N } hopts = { 'cpu': 0.5 / N }
self.runOptionsTopoTest( N, hopts=hopts, lopts=lopts ) self.runOptionsTopoTest( N, hopts=hopts, lopts=lopts )
class testOptionsTopoOVSKernel( testOptionsTopoCommon, unittest.TestCase ):
"Verify ability to create networks with host and link options (OVS kernel switch)."
switchClass = OVSKernelSwitch
class testOptionsTopoIVS( testOptionsTopoCommon, unittest.TestCase ):
"Verify ability to create networks with host and link options (IVS switch)."
switchClass = IVSSwitch
class testOptionsTopoUserspace( testOptionsTopoCommon, unittest.TestCase ):
"Verify ability to create networks with host and link options (Userspace switch)."
switchClass = UserSwitch
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'warning' ) setLogLevel( 'warning' )
+44 -23
View File
@@ -7,42 +7,63 @@ import unittest
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import Host, Controller from mininet.node import Host, Controller
from mininet.node import UserSwitch, OVSKernelSwitch from mininet.node import UserSwitch, OVSKernelSwitch, IVSSwitch
from mininet.topo import SingleSwitchTopo, LinearTopo from mininet.topo import SingleSwitchTopo, LinearTopo
from mininet.log import setLogLevel from mininet.log import setLogLevel
SWITCHES = { 'user': UserSwitch,
'ovsk': OVSKernelSwitch,
}
class testSingleSwitchCommon( object ):
"Test ping with single switch topology (common code)."
class testSingleSwitch( unittest.TestCase ): switchClass = None # overridden in subclasses
"For each datapath type, test ping with single switch topologies."
def testMinimal( self ): def testMinimal( self ):
"Ping test with both datapaths on minimal topology" "Ping test on minimal topology"
for switch in SWITCHES.values(): mn = Mininet( SingleSwitchTopo(), self.switchClass, Host, Controller )
mn = Mininet( SingleSwitchTopo(), switch, Host, Controller ) dropped = mn.run( mn.ping )
dropped = mn.run( mn.ping ) self.assertEqual( dropped, 0 )
self.assertEqual( dropped, 0 )
def testSingle5( self ): def testSingle5( self ):
"Ping test with both datapaths on 5-host single-switch topology" "Ping test on 5-host single-switch topology"
for switch in SWITCHES.values(): mn = Mininet( SingleSwitchTopo( k=5 ), self.switchClass, Host, Controller )
mn = Mininet( SingleSwitchTopo( k=5 ), switch, Host, Controller ) dropped = mn.run( mn.ping )
dropped = mn.run( mn.ping ) self.assertEqual( dropped, 0 )
self.assertEqual( dropped, 0 )
class testSingleSwitchOVSKernel( testSingleSwitchCommon, unittest.TestCase ):
"Test ping with single switch topology (OVS kernel switch)."
switchClass = OVSKernelSwitch
class testSingleSwitchIVS( testSingleSwitchCommon, unittest.TestCase ):
"Test ping with single switch topology (IVS switch)."
switchClass = IVSSwitch
class testSingleSwitchUserspace( testSingleSwitchCommon, unittest.TestCase ):
"Test ping with single switch topology (Userspace switch)."
switchClass = UserSwitch
class testLinear( unittest.TestCase ): class testLinearCommon( object ):
"For each datapath type, test all-pairs ping with LinearNet." "Test all-pairs ping with LinearNet (common code)."
switchClass = None # overridden in subclasses
def testLinear5( self ): def testLinear5( self ):
"Ping test with both datapaths on a 5-switch topology" "Ping test on a 5-switch topology"
for switch in SWITCHES.values(): mn = Mininet( LinearTopo( k=5 ), self.switchClass, Host, Controller )
mn = Mininet( LinearTopo( k=5 ), switch, Host, Controller ) dropped = mn.run( mn.ping )
dropped = mn.run( mn.ping ) self.assertEqual( dropped, 0 )
self.assertEqual( dropped, 0 )
class testLinearOVSKernel( testLinearCommon, unittest.TestCase ):
"Test all-pairs ping with LinearNet (OVS kernel switch)."
switchClass = OVSKernelSwitch
class testLinearIVS( testLinearCommon, unittest.TestCase ):
"Test all-pairs ping with LinearNet (IVS switch)."
switchClass = IVSSwitch
class testLinearUserspace( testLinearCommon, unittest.TestCase ):
"Test all-pairs ping with LinearNet (Userspace switch)."
switchClass = UserSwitch
if __name__ == '__main__': if __name__ == '__main__':
+37 -15
View File
@@ -84,10 +84,9 @@ OVS_RELEASE=1.4.0
OVS_PACKAGE_LOC=https://github.com/downloads/mininet/mininet OVS_PACKAGE_LOC=https://github.com/downloads/mininet/mininet
OVS_BUILDSUFFIX=-ignore # was -2 OVS_BUILDSUFFIX=-ignore # was -2
OVS_PACKAGE_NAME=ovs-$OVS_RELEASE-core-$DIST_LC-$RELEASE-$ARCH$OVS_BUILDSUFFIX.tar OVS_PACKAGE_NAME=ovs-$OVS_RELEASE-core-$DIST_LC-$RELEASE-$ARCH$OVS_BUILDSUFFIX.tar
OVS_SRC=$BUILD_DIR/openvswitch
OVS_TAG=v$OVS_RELEASE OVS_TAG=v$OVS_RELEASE
OVS_BUILD=$OVS_SRC/build-$KERNEL_NAME
OVS_KMODS=($OVS_BUILD/datapath/linux/{openvswitch_mod.ko,brcompat_mod.ko}) IVS_TAG=v0.3
# Command-line versions overrides that simplify custom VM creation # Command-line versions overrides that simplify custom VM creation
# To use, pass in the vars on the cmd line before install.sh, e.g. # To use, pass in the vars on the cmd line before install.sh, e.g.
@@ -95,6 +94,7 @@ OVS_KMODS=($OVS_BUILD/datapath/linux/{openvswitch_mod.ko,brcompat_mod.ko})
WS_DISSECTOR_REV=${WS_DISSECTOR_REV:-""} WS_DISSECTOR_REV=${WS_DISSECTOR_REV:-""}
OF13_SWITCH_REV=${OF13_SWITCH_REV:-""} OF13_SWITCH_REV=${OF13_SWITCH_REV:-""}
function kernel { function kernel {
echo "Install Mininet-compatible kernel if necessary" echo "Install Mininet-compatible kernel if necessary"
sudo apt-get update sudo apt-get update
@@ -287,6 +287,10 @@ function wireshark {
function ovs { function ovs {
echo "Installing Open vSwitch..." echo "Installing Open vSwitch..."
OVS_SRC=$BUILD_DIR/openvswitch
OVS_BUILD=$OVS_SRC/build-$KERNEL_NAME
OVS_KMODS=($OVS_BUILD/datapath/linux/{openvswitch_mod.ko,brcompat_mod.ko})
# Required for module build/dkms install # Required for module build/dkms install
$install $KERNEL_HEADERS $install $KERNEL_HEADERS
@@ -399,6 +403,22 @@ function remove_ovs {
echo "Done removing OVS" echo "Done removing OVS"
} }
function ivs {
echo "Installing Indigo Virtual Switch..."
IVS_SRC=$BUILD_DIR/ivs
# Install dependencies
$install git pkg-config gcc make libnl-3-dev libnl-route-3-dev libnl-genl-3-dev
# Install IVS from source
cd $BUILD_DIR
git clone git://github.com/floodlight/ivs $IVS_SRC -b $IVS_TAG --recursive
cd $IVS_SRC
make
sudo make install
}
# Install NOX with tutorial files # Install NOX with tutorial files
function nox { function nox {
echo "Installing NOX w/tutorial files..." echo "Installing NOX w/tutorial files..."
@@ -640,7 +660,7 @@ function vm_clean {
} }
function usage { function usage {
printf '\nUsage: %s [-abcdfhkmnprtvwx03]\n\n' $(basename $0) >&2 printf '\nUsage: %s [-abcdfhikmnprtvwx03]\n\n' $(basename $0) >&2
printf 'This install script attempts to install useful packages\n' >&2 printf 'This install script attempts to install useful packages\n' >&2
printf 'for Mininet. It should (hopefully) work on Ubuntu 11.10+\n' >&2 printf 'for Mininet. It should (hopefully) work on Ubuntu 11.10+\n' >&2
@@ -653,21 +673,22 @@ function usage {
printf -- ' -b: install controller (B)enchmark (oflops)\n' >&2 printf -- ' -b: install controller (B)enchmark (oflops)\n' >&2
printf -- ' -c: (C)lean up after kernel install\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 -- ' -d: (D)elete some sensitive files from a VM image\n' >&2
printf -- ' -f: install open(F)low\n' >&2 printf -- ' -e: install Mininet d(E)veloper dependencies\n' >&2
printf -- ' -f: install Open(F)low\n' >&2
printf -- ' -h: print this (H)elp message\n' >&2 printf -- ' -h: print this (H)elp message\n' >&2
printf -- ' -i: install (I)ndigo Virtual Switch\n' >&2
printf -- ' -k: install new (K)ernel\n' >&2 printf -- ' -k: install new (K)ernel\n' >&2
printf -- ' -m: install Open vSwitch kernel (M)odule from source dir\n' >&2 printf -- ' -m: install Open vSwitch kernel (M)odule from source dir\n' >&2
printf -- ' -n: install mini(N)et dependencies + core files\n' >&2 printf -- ' -n: install Mini(N)et dependencies + core files\n' >&2
printf -- ' -e: install mininet d(E)veloper dependencies\n' >&2
printf -- ' -p: install (P)OX OpenFlow Controller\n' >&2 printf -- ' -p: install (P)OX OpenFlow Controller\n' >&2
printf -- ' -r: remove existing Open vSwitch packages\n' >&2 printf -- ' -r: remove existing Open vSwitch packages\n' >&2
printf -- ' -s <dir>: place dependency (S)ource/build trees in <dir>\n' >&2
printf -- ' -t: complete o(T)her Mininet VM setup tasks\n' >&2 printf -- ' -t: complete o(T)her Mininet VM setup tasks\n' >&2
printf -- ' -v: install open (V)switch\n' >&2 printf -- ' -v: install Open (V)switch\n' >&2
printf -- ' -w: install OpenFlow (w)ireshark dissector\n' >&2 printf -- ' -w: install OpenFlow (W)ireshark dissector\n' >&2
printf -- ' -x: install NO(X) Classic OpenFlow controller\n' >&2 printf -- ' -x: install NO(X) Classic OpenFlow controller\n' >&2
printf -- ' -0: (default) -0[fx] installs OpenFlow 1.0 versions\n' >&2 printf -- ' -0: (default) -0[fx] installs OpenFlow 1.0 versions\n' >&2
printf -- ' -3: -3[fx] installs OpenFlow 1.3 versions\n' >&2 printf -- ' -3: -3[fx] installs OpenFlow 1.3 versions\n' >&2
printf -- ' -i < directory >: sets the (I)nstallation directory for Mininet dependencies\n' >&2
exit 2 exit 2
} }
@@ -677,25 +698,29 @@ if [ $# -eq 0 ]
then then
all all
else else
while getopts 'abcdefhkmnprtvwx03i:' OPTION while getopts 'abcdefhikmnprs:tvwx03' OPTION
do do
case $OPTION in case $OPTION in
a) all;; a) all;;
b) cbench;; b) cbench;;
c) kernel_clean;; c) kernel_clean;;
d) vm_clean;; d) vm_clean;;
e) mn_dev;;
f) case $OF_VERSION in f) case $OF_VERSION in
1.0) of;; 1.0) of;;
1.3) of13;; 1.3) of13;;
*) echo "Invalid OpenFlow version $OF_VERSION";; *) echo "Invalid OpenFlow version $OF_VERSION";;
esac;; esac;;
h) usage;; h) usage;;
i) ivs;;
k) kernel;; k) kernel;;
m) modprobe;; m) modprobe;;
n) mn_deps;; n) mn_deps;;
e) mn_dev;;
p) pox;; p) pox;;
r) remove_ovs;; r) remove_ovs;;
s) mkdir -p $OPTARG; # ensure the directory is created
BUILD_DIR="$( cd -P "$OPTARG" && pwd )"; # get the full path
echo "Dependency installation directory: $BUILD_DIR";;
t) vm_other;; t) vm_other;;
v) ovs;; v) ovs;;
w) wireshark;; w) wireshark;;
@@ -706,9 +731,6 @@ else
esac;; esac;;
0) OF_VERSION=1.0;; 0) OF_VERSION=1.0;;
3) OF_VERSION=1.3;; 3) OF_VERSION=1.3;;
i) mkdir -p $OPTARG; # ensure the directory is created
BUILD_DIR="$( cd -P "$OPTARG" && pwd )"; # get the full path of the directory
echo "Dependency installation directory: $BUILD_DIR";;
?) usage;; ?) usage;;
esac esac
done done