diff --git a/INSTALL b/INSTALL index a99ea17..a434f8c 100644 --- a/INSTALL +++ b/INSTALL @@ -47,12 +47,11 @@ Preliminary Mininet Installation/Configuration Notes To compile for Linux 2.6.33, you may need to apply the patch included below. - If you want to automatically load the kernel modules required - for OpenFlow, you could add something like the following to - /etc/rc.local: +- 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. - insmod /home/openflow/openflow/datapath/linux-2.6/ofdatapath.ko - modprobe tun + See ~/mininet/util/modprobe_setup.sh for an example. - The reference OpenFlow controller (controller(8)) only supports 16 switches by default! If you wish to run a network with more than 16 diff --git a/mininet/moduledeps.py b/mininet/moduledeps.py new file mode 100644 index 0000000..7cfe8e8 --- /dev/null +++ b/mininet/moduledeps.py @@ -0,0 +1,54 @@ +"Module dependency utility functions for Mininet." + +from mininet.util import quietRun +from mininet.log import info, error, debug + +def lsmod(): + "Return output of lsmod." + return quietRun( 'lsmod' ) + +def rmmod( mod ): + """Return output of lsmod. + mod: module string""" + return quietRun( [ 'rmmod', mod ] ) + +def modprobe( mod ): + """Return output of modprobe + mod: module string""" + return quietRun( [ 'modprobe', mod ] ) + +OF_KMOD = 'ofdatapath' +OVS_KMOD = 'openvswitch_mod' +TUN = 'tun' + +def moduleDeps( subtract = [], add = [] ): + """Handle module dependencies. + subtract: string or list of module names to remove, if already loaded + add: string or list of module names to add, if not already loaded""" + if type( subtract ) is str: + subtract = [ subtract ] + if type( add ) is str: + add = [ add ] + for mod in subtract: + if mod in lsmod(): + info( '*** Removing ' + mod + '\n' ) + rmmodOutput = rmmod( mod ) + if rmmodOutput: + error( 'Error removing ' + mod + '\n%s' % rmmodOutput ) + exit( 1 ) + if mod in lsmod(): + error( 'Failed to remove ' + mod + '; still there!\n' ) + exit( 1 ) + for mod in add: + if mod not in lsmod(): + info( '*** Loading ' + mod + '\n' ) + modprobeOutput = modprobe( mod ) + if modprobeOutput: + error( 'Error inserting ' + mod + ';\n See INSTALL.\n%s' % + modprobeOutput ) + exit( 1 ) + if mod not in lsmod(): + error( 'Failed to insert ' + mod + '\n' ) + exit( 1 ) + else: + debug( '*** ' + mod + ' already loaded\n' ) \ No newline at end of file diff --git a/mininet/net.py b/mininet/net.py index 0f37133..f732c36 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -151,6 +151,8 @@ class Mininet( object ): self.dps = 0 # number of created kernel datapaths self.terms = [] # list of spawned xterm processes + switch.setup() + if build: self.build() diff --git a/mininet/node.py b/mininet/node.py index 44c5faa..a3126cf 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -50,6 +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 class Node( object ): """A virtual network node is simply a shell in a network namespace. @@ -397,6 +398,11 @@ class UserSwitch( Switch ): name: name for the switch""" Switch.__init__( self, name, **kwargs ) + @staticmethod + def setup(): + "Ensure any dependencies are loaded; if not, try to load them." + moduleDeps( add = TUN ) + def start( self, controllers ): """Start OpenFlow reference user datapath. Log to /tmp/sN-{ofd,ofp}.log. @@ -448,6 +454,11 @@ class KernelSwitch( Switch ): " in the root namespace." ) exit( 1 ) + @staticmethod + def setup(): + "Ensure any dependencies are loaded; if not, try to load them." + moduleDeps( subtract = OVS_KMOD, add = OF_KMOD ) + def start( self, controllers ): "Start up reference kernel datapath." ofplog = '/tmp/' + self.name + '-ofp.log' @@ -508,6 +519,11 @@ class OVSKernelSwitch( Switch ): " in the root namespace." ) exit( 1 ) + @staticmethod + def setup(): + "Ensure any dependencies are loaded; if not, try to load them." + moduleDeps( subtract = OF_KMOD, add = OVS_KMOD ) + def start( self, controllers ): "Start up kernel datapath." ofplog = '/tmp/' + self.name + '-ofp.log' diff --git a/mininet/test/test_nets.py b/mininet/test/test_nets.py index b5e32a3..e114e3c 100755 --- a/mininet/test/test_nets.py +++ b/mininet/test/test_nets.py @@ -7,10 +7,13 @@ import unittest from mininet.net import init, Mininet from mininet.node import KernelSwitch, Host, Controller, ControllerParams +from mininet.node import UserSwitch, OVSKernelSwitch from mininet.topo import SingleSwitchTopo, LinearTopo # temporary, until user-space side is tested -SWITCHES = { 'kernel': KernelSwitch } +SWITCHES = { 'kernel': KernelSwitch, + 'user': UserSwitch, + 'ovsk': OVSKernelSwitch } class testSingleSwitch( unittest.TestCase ): diff --git a/util/modprobe_setup.sh b/util/modprobe_setup.sh new file mode 100755 index 0000000..fec0a36 --- /dev/null +++ b/util/modprobe_setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# Script to copy built OVS and OF kernel modules to where modprobe will +# find them automatically. Removes the need to keep an environment variable +# for each, and works nicely with multiple kernel versions. +# +# The downside is that after each recompilation of OVS or OF 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. +DRIVERS_DIR=/lib/modules/`uname -r`/kernel/drivers + +OVS_DIR=~/openvswitch +OVS_KMOD=openvswitch_mod.ko +cp $OVS_DIR/datapath/linux-2.6/$OVS_KMOD $DRIVERS_DIR + +OF_DIR=~/openflow +OF_KMOD=ofdatapath.ko +cp $OF_DIR/datapath/linux-2.6/$OF_KMOD $DRIVERS_DIR + +# Update for modprobe +sudo depmod -a