Conflicts:
	mininet/node.py -- revert our change; better solution upstream
	util/install.sh -- resolved the conflict (echo statement)
This commit is contained in:
Jose Pedro Oliveira
2013-09-13 04:05:47 +01:00
52 changed files with 2130 additions and 474 deletions
+39
View File
@@ -0,0 +1,39 @@
Mininet Contributors
Mininet is an open source project and we gratefully acknowledge
the many contributions to the project! If you have contributed
code into the project and are not on this list, please let us know
or send a pull request.
Contributors include:
Mininet Core Team
Bob Lantz
Brandon Heller
Nikhil Handigol
Vimal Jeyakumar
Brian O'Connor
Additional Mininet Contributors
Gustavo Pantuza Coelho Pinto
Ryan Cox
Shaun Crampton
David Erickson
Glen Gibb
Andrew Ferguson
Eder Leao Fernandes
Vitaly Ivanov
Rich Lane
Murphy McCauley
James Page
Angad Singh
Piyush Srivastava
Ed Swierk
Isaku Yamahata
Thanks also to everyone who has submitted issues and pull
requests on github, and to our friendly mininet-discuss
mailing list!
+10 -5
View File
@@ -2,7 +2,7 @@
Mininet Installation/Configuration Notes
----------------------------------------
Mininet 2.0.0
Mininet 2.1.0
---
The supported installation methods for Mininet are 1) using a
@@ -15,7 +15,7 @@ like to contribute an installation script, we would welcome it!)
1. Easiest "installation" - 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/mininet>
pre-built virtual machine images from <http://mininet.org/>
Boot up the VM image, log in, and follow the instructions on the
Mininet web site.
@@ -42,7 +42,7 @@ like to contribute an installation script, we would welcome it!)
sudo rm /usr/local/bin/ovs*
sudo rm /usr/local/sbin/ovs*
3. Native installation from source on Ubuntu 11.10+
3. Native installation from source on Ubuntu 12.04+
If you're reading this, you've probably already done so, but the
command to download the Mininet source code is:
@@ -56,7 +56,7 @@ like to contribute an installation script, we would welcome it!)
`install.sh` is a bit intrusive and may possibly damage your OS
and/or home directory, by creating/modifying several directories
such as `mininet`, `openflow`, `oftest`, `pox`, or `noxcosre`.
such as `mininet`, `openflow`, `oftest`, `pox`, etc..
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!
@@ -81,6 +81,11 @@ like to contribute an installation script, we would welcome it!)
This takes about 4 minutes on our test system.
You can change the directory where the dependencies are installed using
the -s <directory> flag.
mininet/util/install.sh -s <directory> -a
4. Creating your own Mininet/OpenFlow tutorial VM
Creating your own Ubuntu Mininet VM for use with the OpenFlow tutorial
@@ -108,7 +113,7 @@ like to contribute an installation script, we would welcome it!)
modules (e.g. tun and ofdatapath for the reference kernel
implementation) must be loaded.
* Python, `bash`, `ping`, `iperf`, etc.`
* Python, `bash`, `ping`, `iperf`, etc.
* Root privileges (required for network device access)
+2 -2
View File
@@ -1,6 +1,6 @@
Mininet 2.0.0 License
Mininet 2.1.0 License
Copyright (c) 2012 Open Networking Laboratory
Copyright (c) 2013 Open Networking Laboratory
Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
The Leland Stanford Junior University
+1 -1
View File
@@ -1,6 +1,6 @@
MININET = mininet/*.py
TEST = mininet/test/*.py
EXAMPLES = examples/*.py
EXAMPLES = mininet/examples/*.py
MN = bin/mn
BIN = $(MN)
PYSRC = $(MININET) $(TEST) $(EXAMPLES) $(BIN)
+30 -30
View File
@@ -4,7 +4,7 @@ Mininet: Rapid Prototyping for Software Defined Networks
*The best way to emulate almost any network on your laptop!*
Version 2.0.0
Version 2.1.0
### What is Mininet?
@@ -67,32 +67,32 @@ Mininet includes:
`mn -c`
### New features in 2.0.0
### New features in 2.1.0
Mininet 2.0.0 is a major upgrade and provides
a number of enhancements and new features, including:
Mininet 2.1.0 provides a number of bug fixes as well as
several new features, including:
* "Mininet-HiFi" functionality:
* Convenient access to Mininet() as a dict of nodes
* X11 tunneling (wireshark in Mininet hosts, finally!)
* Accurate reflection of the Mininet() object in the CLI
* Automatically detecting and adjusting resource limits
* Automatic cleanup on failure of the `mn` command
* Preliminary support for running OVS in user space mode
* Preliminary support (`IVSSwitch()`) for the Indigo Virtual Switch
* support for installing the OpenFlow 1.3 versions of the reference
user switch and NOX from CPqD
* The ability to import modules from mininet.examples
* Link bandwidth limits using `tc` (`TCIntf` and `TCLink` classes)
We have provided several new examples (which can easily be
imported to provide useful functionality) including:
* CPU isolation and bandwidth limits (`CPULimitedHost` class)
* Modeling separate control and data networks
* Connecting Mininet hosts the internet (or a LAN) using NAT
* Creating per-host custom directories using bind mounts
* Support for Open vSwitch 1.4+ (including Ubuntu OVS packages)
* Debian packaging (and `apt-get install mininet` in Ubuntu 12.10)
* First-class Interface (`Intf`) and Link (`Link`) classes for easier
extensibility
* An upgraded Topology (`Topo`) class which supports node and link
customization
* Man pages for the `mn` and `mnexec` utilities.
[Since the API (most notably the topology) has changed, existing code
that runs in Mininet 1.0 will need to be changed to run with Mininet
2.0. This is the primary reason for the major version number change.]
Note that examples contain experimental features which might
"graduate" into mainline Mininet in the future, but they should
not be considered a stable part of the Mininet API!
### Installation
@@ -116,19 +116,19 @@ Mininet mailing list, `mininet-discuss` at:
### Contributing
Mininet is an open-source project and is currently hosted at
<https://github.com/mininet>. You are encouraged to download the code,
examine it, modify it, and submit bug reports, bug fixes, feature
requests, and enhancements!
Mininet is an open source project and is currently hosted
at <https://github.com/mininet>. You are encouraged to download
the code, examine it, modify it, and submit bug reports, bug fixes,
feature requests, new features and other issues and pull requests.
Thanks to everyone who has contributed to the project
(see CONTRIBUTORS for more info!)
Best wishes, and we look forward to seeing what you can do with
Mininet to change the networking world!
### Credits
The Mininet Team:
The Mininet 2.1.0 Team:
* Bob Lantz
* Brandon Heller
* Nikhil Handigol
* Vimal Jeyakumar
* Brian O'Connor
+4 -1
View File
@@ -17,10 +17,13 @@ Architecture: any
Depends:
openvswitch-switch,
telnet,
socat,
iperf,
cgroup-bin,
${misc:Depends},
${python:Depends},
${shlibs:Depends}
Recommends: iperf, openvswitch-controller, socat
Recommends: openvswitch-controller
Description: Process-based network emulator
Mininet is a network emulator which uses lightweight
virtualization to create virtual networks for rapid
+1 -1
View File
@@ -3,7 +3,7 @@ Upstream-Name: mininet
Source: https://github.com/mininet/mininet
Files: *
Copyright: 2012 Open Networking Laboratory,
Copyright: 2012-2013 Open Networking Laboratory,
2009-2012 Bob Lantz,
2009-2012 The Board of Trustees of the Leland Stanford Junior
University
+29 -30
View File
@@ -1,4 +1,3 @@
Mininet Examples
========================================================
@@ -7,114 +6,114 @@ Mininet's Python API.
========================================================
### baresshd.py:
#### baresshd.py:
This example uses Mininet's medium-level API to create an sshd
process running in a namespace. Doesn't use OpenFlow.
### consoles.py:
#### consoles.py:
This example creates a grid of console windows, one for each node,
and allows interaction with and monitoring of each console, including
graphical monitoring.
### controllers.py:
#### controllers.py:
This example creates a network with multiple controllers, by
using a custom Switch() subclass.
using a custom `Switch()` subclass.
### controllers2.py:
#### controllers2.py:
This example creates a network with multiple controllers by
creating an empty network, adding nodes to it, and manually
starting the switches.
### controlnet.py:
#### controlnet.py:
This examples shows how you can model the control network as well
as the data network, by actually creating two Mininet objects.
### cpu.py:
#### cpu.py:
This example tests iperf bandwidth for varying CPU limits.
### emptynet.py:
#### emptynet.py:
This example demonstrates creating an empty network (i.e. with no
topology object) and adding nodes to it.
### hwintf.py:
#### hwintf.py:
This example shows how to add an interface (for example a real
hardware interface) to a network after the network is created.
### limit.py:
#### limit.py:
This example shows how to use link and CPU limits.
### linearbandwidth.py:
#### linearbandwidth.py:
This example shows how to create a custom topology programatically
by subclassing Topo, and how to run a series of tests on it.
### miniedit.py:
#### miniedit.py:
This example demonstrates creating a network via a graphical editor.
### multiping.py:
#### multiping.py:
This example demonstrates one method for
monitoring output from multiple hosts, using `node.monitor()`.
### multipoll.py:
#### multipoll.py:
This example demonstrates monitoring output files from multiple hosts.
### multitest.py:
#### multitest.py:
This example creates a network and runs multiple tests on it.
### nat.py:
#### nat.py:
This example shows how to connect a Mininet network to the Internet
using NAT. It also answers the eternal question "why can't I ping
google?"
`google.com`?"
### popen.py:
#### popen.py:
This example monitors a number of hosts using `host.popen()` and
`pmonitor()`.
### popenpoll.py:
#### popenpoll.py:
This example demonstrates monitoring output from multiple hosts using
the `node.popen()` interface (which returns Popen objects) and `pmonitor()`.
the `node.popen()` interface (which returns `Popen` objects) and `pmonitor()`.
### scratchnet.py, scratchnetuser.py:
#### scratchnet.py, scratchnetuser.py:
These two examples demonstrate how to create a network by using the lowest-
level Mininet functions. Generally the higher-level API is easier to use,
but scratchnet shows what is going on behind the scenes.
### simpleperf.py:
#### simpleperf.py:
A simple example of configuring network and CPU bandwidth limits.
### sshd.py:
#### sshd.py:
This example shows how to run an sshd process in each host, allowing
you to log in via ssh. This requires connecting the Mininet data network
This example shows how to run an `sshd` process in each host, allowing
you to log in via `ssh`. This requires connecting the Mininet data network
to an interface in the root namespace (generaly the control network
already lives in the root namespace, so it does not need to be explicitly
connected.)
### tree1024.py:
#### tree1024.py:
This example attempts to create a 1024-host network, and then runs the
CLI on it. It may run into scalability limits, depending on available
memory and sysctl configuration (see `INSTALL`.)
memory and `sysctl` configuration (see `INSTALL`.)
### treeping64.py:
#### treeping64.py:
This example creates a 64-host tree network, and attempts to check full
connectivity using ping, for different switch/datapath types.
connectivity using `ping`, for different switch/datapath types.
+4
View File
@@ -0,0 +1,4 @@
"""
Mininet Examples
See README for details
"""
+6 -1
View File
@@ -2,6 +2,7 @@
"This example doesn't use OpenFlow, but attempts to run sshd in a namespace."
import sys
from mininet.node import Host
from mininet.util import ensureRoot
@@ -27,6 +28,10 @@ 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 )
cmd = '/usr/sbin/sshd -o "Banner /tmp/%s.banner"' % h1.name
# add arguments from the command line
if len( sys.argv ) > 1:
cmd += ' ' + ' '.join( sys.argv[ 1: ] )
h1.cmd( cmd )
print "*** You may now ssh into", h1.name, "at", h1.IP()
+197
View File
@@ -0,0 +1,197 @@
#!/usr/bin/python
"""
bind.py: Bind mount prototype
This creates hosts with private directories as desired.
"""
from mininet.net import Mininet
from mininet.node import Host
from mininet.cli import CLI
from mininet.util import errFail, quietRun, errRun
from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel, info, debug
from os.path import realpath
from functools import partial
# Utility functions for unmounting a tree
MNRUNDIR = realpath( '/var/run/mn' )
def mountPoints():
"Return list of mounted file systems"
mtab, _err, _ret = errFail( 'cat /proc/mounts' )
lines = mtab.split( '\n' )
mounts = []
for line in lines:
if not line:
continue
fields = line.split( ' ')
mount = fields[ 1 ]
mounts.append( mount )
return mounts
def unmountAll( rootdir=MNRUNDIR ):
"Unmount all mounts under a directory tree"
rootdir = realpath( rootdir )
# Find all mounts below rootdir
# This is subtle because /foo is not
# a parent of /foot
dirslash = rootdir + '/'
mounts = [ m for m in mountPoints()
if m == dir or m.find( dirslash ) == 0 ]
# Unmount them from bottom to top
mounts.sort( reverse=True )
for mount in mounts:
debug( 'Unmounting', mount, '\n' )
_out, err, code = errRun( 'umount', mount )
if code != 0:
info( '*** Warning: failed to umount', mount, '\n' )
info( err )
class HostWithPrivateDirs( Host ):
"Host with private directories"
mnRunDir = MNRUNDIR
def __init__(self, name, *args, **kwargs ):
"""privateDirs: list of private directories
remounts: dirs to remount
unmount: unmount dirs in cleanup? (True)
Note: if unmount is False, you must call unmountAll()
manually."""
self.privateDirs = kwargs.pop( 'privateDirs', [] )
self.remounts = kwargs.pop( 'remounts', [] )
self.unmount = kwargs.pop( 'unmount', True )
Host.__init__( self, name, *args, **kwargs )
self.rundir = '%s/%s' % ( self.mnRunDir, name )
self.root, self.private = None, None # set in createBindMounts
if self.privateDirs:
self.privateDirs = [ realpath( d ) for d in self.privateDirs ]
self.createBindMounts()
# These should run in the namespace before we chroot,
# in order to put the right entries in /etc/mtab
# Eventually this will allow a local pid space
# Now we chroot and cd to wherever we were before.
pwd = self.cmd( 'pwd' ).strip()
self.sendCmd( 'exec chroot', self.root, 'bash -ms mininet:'
+ self.name )
self.waiting = False
self.cmd( 'cd', pwd )
# In order for many utilities to work,
# we need to remount /proc and /sys
self.cmd( 'mount /proc' )
self.cmd( 'mount /sys' )
def mountPrivateDirs( self ):
"Create and bind mount private dirs"
for dir_ in self.privateDirs:
privateDir = self.private + dir_
errFail( 'mkdir -p ' + privateDir )
mountPoint = self.root + dir_
errFail( 'mount -B %s %s' %
( privateDir, mountPoint) )
def mountDirs( self, dirs ):
"Mount a list of directories"
for dir_ in dirs:
mountpoint = self.root + dir_
errFail( 'mount -B %s %s' %
( dir_, mountpoint ) )
@classmethod
def findRemounts( cls, fstypes=None ):
"""Identify mount points in /proc/mounts to remount
fstypes: file system types to match"""
if fstypes is None:
fstypes = [ 'nfs' ]
dirs = quietRun( 'cat /proc/mounts' ).strip().split( '\n' )
remounts = []
for dir_ in dirs:
line = dir_.split()
mountpoint, fstype = line[ 1 ], line[ 2 ]
# Don't re-remount directories!!!
if mountpoint.find( cls.mnRunDir ) == 0:
continue
if fstype in fstypes:
remounts.append( mountpoint )
return remounts
def createBindMounts( self ):
"""Create a chroot directory structure,
with self.privateDirs as private dirs"""
errFail( 'mkdir -p '+ self.rundir )
unmountAll( self.rundir )
# Create /root and /private directories
self.root = self.rundir + '/root'
self.private = self.rundir + '/private'
errFail( 'mkdir -p ' + self.root )
errFail( 'mkdir -p ' + self.private )
# Recursively mount / in private doort
# note we'll remount /sys and /proc later
errFail( 'mount -B / ' + self.root )
self.mountDirs( self.remounts )
self.mountPrivateDirs()
def unmountBindMounts( self ):
"Unmount all of our bind mounts"
unmountAll( self.rundir )
def popen( self, *args, **kwargs ):
"Popen with chroot support"
chroot = kwargs.pop( 'chroot', True )
mncmd = kwargs.get( 'mncmd',
[ 'mnexec', '-a', str( self.pid ) ] )
if chroot:
mncmd = [ 'chroot', self.root ] + mncmd
kwargs[ 'mncmd' ] = mncmd
return Host.popen( self, *args, **kwargs )
def cleanup( self ):
"""Clean up, then unmount bind mounts
unmount: actually unmount bind mounts?"""
# Wait for process to actually terminate
self.shell.wait()
Host.cleanup( self )
if self.unmount:
self.unmountBindMounts()
errFail( 'rmdir ' + self.root )
# Convenience aliases
findRemounts = HostWithPrivateDirs.findRemounts
# Sample usage
def testHostWithPrivateDirs():
"Test bind mounts"
topo = SingleSwitchTopo( 10 )
remounts = findRemounts( fstypes=[ 'nfs' ] )
privateDirs = [ '/var/log', '/var/run' ]
host = partial( HostWithPrivateDirs, remounts=remounts,
privateDirs=privateDirs, unmount=False )
net = Mininet( topo=topo, host=host )
net.start()
info( 'Private Directories:', privateDirs, '\n' )
CLI( net )
net.stop()
# We do this all at once to save a bit of time
info( 'Unmounting host bind mounts...\n' )
unmountAll()
if __name__ == '__main__':
unmountAll()
setLogLevel( 'info' )
testHostWithPrivateDirs()
info( 'Done.\n')
+2 -1
View File
@@ -418,7 +418,8 @@ class ConsoleApp( Frame ):
count = len( consoles )
self.setOutputHook( self.updateGraph )
for console in consoles:
#sometimes iperf -sD doesn't return, so we run it in the background instead
# Sometimes iperf -sD doesn't return,
# so we run it in the background instead
console.node.cmd( 'iperf -s &' )
i = 0
for console in consoles:
+4 -3
View File
@@ -15,8 +15,8 @@ setLogLevel( 'info' )
# Two local and one "external" controller (which is actually c0)
# Ignore the warning message that the remote isn't (yet) running
c0 = Controller( 'c0' )
c1 = Controller( 'c1' )
c0 = Controller( 'c0', port=6633 )
c1 = Controller( 'c1', port=6634 )
c2 = RemoteController( 'c2', ip='127.0.0.1' )
cmap = { 's1': c0, 's2': c1, 's3': c2 }
@@ -28,7 +28,8 @@ class MultiSwitch( OVSSwitch ):
topo = TreeTopo( depth=2, fanout=2 )
net = Mininet( topo=topo, switch=MultiSwitch, build=False )
net.controllers = [ c0, c1 ]
for c in [ c0, c1 ]:
net.addController(c)
net.build()
net.start()
CLI( net )
+87 -54
View File
@@ -10,10 +10,12 @@ control network to control the data network.
Since we're using UserSwitch on the data network,
it should correctly fail over to a backup controller.
We also hack/subclass the CLI slightly so it can talk to
both the control and data networks.
We also use a Mininet Facade to talk to both the
control and data networks from a single CLI.
"""
from functools import partial
from mininet.net import Mininet
from mininet.node import Controller, UserSwitch
from mininet.cli import CLI
@@ -30,31 +32,62 @@ class DataController( Controller ):
"Ignore spurious error"
pass
class CLI2( CLI ):
"CLI that can talk to two networks"
class MininetFacade( object ):
"""Mininet object facade that allows a single CLI to
talk to one or more networks"""
def __init__( self, *args, **kwargs ):
"cnet: second network"
self.cnet = kwargs.pop( 'cnet' )
CLI.__init__( self, *args, **kwargs )
def __init__( self, net, *args, **kwargs ):
"""Create MininetFacade object.
net: Primary Mininet object
args: unnamed networks passed as arguments
kwargs: named networks passed as arguments"""
self.net = net
self.nets = [ net ] + list( args ) + kwargs.values()
self.nameToNet = kwargs
self.nameToNet['net'] = net
def updateVars( self ):
"Update variables to include cnet"
cnet = self.cnet
nodes2 = cnet.controllers + cnet.switches + cnet.hosts
self.nodelist += nodes2
for node in nodes2:
self.nodemap[ node.name ] = node
self.locals[ 'cnet' ] = cnet
self.locals.update( self.nodemap )
def cmdloop( self, *args, **kwargs ):
"Patch to add cnet if needed"
if 'cnet' not in self.locals:
self.updateVars()
CLI.cmdloop( self, *args, **kwargs )
def __getattr__( self, name ):
"returns attribute from Primary Mininet object"
return getattr( self.net, name )
def __getitem__( self, key ):
"returns primary/named networks or node from any net"
#search kwargs for net named key
if key in self.nameToNet:
return self.nameToNet[ key ]
#search each net for node named key
for net in self.nets:
if key in net:
return net[ key ]
def __iter__( self ):
"Iterate through all nodes in all Mininet objects"
for net in self.nets:
for node in net:
yield node
def __len__( self ):
"returns aggregate number of nodes in all nets"
count = 0
for net in self.nets:
count += len(net)
return count
def __contains__( self, key ):
"returns True if node is a member of any net"
return key in self.keys()
def keys( self ):
"returns a list of all node names in all networks"
return list( self )
def values( self ):
"returns a list of all nodes in all networks"
return [ self[ key ] for key in self ]
def items( self ):
"returns (key,value) tuple list for every node in all networks"
return zip( self.keys(), self.values() )
# A real control network!
@@ -79,40 +112,40 @@ class ControlNetwork( Topo ):
# Make it Happen!!
setLogLevel( 'info' )
def run():
"Create control and data networks, and invoke the CLI"
info( '* Creating Control Network\n' )
ctopo = ControlNetwork( n=4, dataController=DataController )
cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24', controller=None )
info( '* Adding Control Network Controller\n')
cnet.addController( 'cc0', controller=Controller )
info( '* Starting Control Network\n')
cnet.start()
info( '* Creating Control Network\n' )
ctopo = ControlNetwork( n=4, dataController=DataController )
cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24', build=False )
info( '* Adding Control Network Controller\n')
cnet.addController( 'cc0' )
info( '* Starting Control Network\n')
cnet.build()
cnet.start()
dataControllers = cnet.hosts[ : -1 ] # ignore 'root' node
info( '* Creating Data Network\n' )
topo = TreeTopo( depth=2, fanout=2 )
# UserSwitch so we can easily test failover
net = Mininet( topo=topo, switch=UserSwitch, build=False )
info( '* Adding Controllers to Data Network\n' )
net.controllers = dataControllers
net.build()
info( '* Starting Data Network\n')
net.start()
CLI2( net, cnet=cnet )
info( '* Stopping Data Network\n' )
net.stop()
info( '* Stopping Control Network\n' )
# dataControllers have already been stopped
cnet.hosts = list( set( cnet.hosts ) - set( dataControllers ) )
cnet.stop()
info( '* Creating Data Network\n' )
topo = TreeTopo( depth=2, fanout=2 )
# UserSwitch so we can easily test failover
sw = partial( UserSwitch, opts='--inactivity-probe=1 --max-backoff=1' )
net = Mininet( topo=topo, switch=sw, controller=None )
info( '* Adding Controllers to Data Network\n' )
for host in cnet.hosts:
if isinstance(host, Controller):
net.addController( host )
info( '* Starting Data Network\n')
net.start()
mn = MininetFacade( net, cnet=cnet )
CLI( mn )
info( '* Stopping Data Network\n' )
net.stop()
info( '* Stopping Control Network\n' )
cnet.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
run()
+2 -2
View File
@@ -27,8 +27,8 @@ def emptyNet():
s3 = net.addSwitch( 's3' )
info( '*** Creating links\n' )
h1.linkTo( s3 )
h2.linkTo( s3 )
net.addLink( h1, s3 )
net.addLink( h2, s3 )
info( '*** Starting network\n')
net.start()
+5 -2
View File
@@ -5,7 +5,7 @@ This example shows how to add an interface (for example a real
hardware interface) to a network after the network is created.
"""
import re
import re, sys
from mininet.cli import CLI
from mininet.log import setLogLevel, info, error
@@ -28,7 +28,10 @@ def checkIntf( intf ):
if __name__ == '__main__':
setLogLevel( 'info' )
intfName = 'eth1'
# try to get hw intf from the command line; by default, use eth1
intfName = sys.argv[ 1 ] if len( sys.argv ) > 1 else 'eth1'
info( '*** Connecting to hw intf: %s' % intfName )
info( '*** Checking', intfName, '\n' )
checkIntf( intfName )
+2 -5
View File
@@ -23,13 +23,8 @@ def chunks( l, n ):
def startpings( host, targetips ):
"Tell host to repeatedly ping targets"
targetips.append( '10.0.0.200' )
targetips = ' '.join( targetips )
# BL: Not sure why loopback intf isn't up!
host.cmd( 'ifconfig lo up' )
# Simple ping loop
cmd = ( 'while true; do '
' for ip in %s; do ' % targetips +
@@ -63,6 +58,8 @@ def multiping( netsize, chunksize, seconds):
# Start pings
for subnet in subnets:
ips = [ host.IP() for host in subnet ]
#adding bogus to generate packet loss
ips.append( '10.0.0.200' )
for host in subnet:
startpings( host, ips )
+1 -1
View File
@@ -22,7 +22,7 @@ if __name__ == '__main__':
info( "*** Initializing Mininet and kernel modules\n" )
OVSKernelSwitch.setup()
info( "*** Creating network\n" )
network = Mininet( TreeTopo( depth=2, fanout=2 ), switch=OVSKernelSwitch)
network = Mininet( TreeTopo( depth=2, fanout=2 ), switch=OVSKernelSwitch )
info( "*** Starting network\n" )
network.start()
info( "*** Running ping test\n" )
+1 -1
View File
@@ -23,7 +23,7 @@ def pmonitorTest( N=3, seconds=10 ):
endTime = time() + seconds
for h, line in pmonitor( popens, timeoutms=500 ):
if h:
print '%s: %s' % ( h.name, line ),
print '<%s>: %s' % ( h.name, line ),
if time() >= endTime:
for p in popens.values():
p.send_signal( SIGINT )
+5 -1
View File
@@ -16,6 +16,8 @@ demonstrates:
- running server processes (sshd in this case) on hosts
"""
import sys
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.log import lg
@@ -68,4 +70,6 @@ def sshd( network, cmd='/usr/sbin/sshd', opts='-D' ):
if __name__ == '__main__':
lg.setLogLevel( 'info')
net = TreeNet( depth=1, fanout=4, switch=OVSKernelSwitch )
sshd( net )
# get sshd args from the command line; default: -D
opts = ' '.join( sys.argv[ 1: ] ) if len( sys.argv ) > 1 else '-D'
sshd( net, opts=opts )
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env python
"""
Run all mininet.examples tests
-v : verbose output
-quick : skip tests that take more than ~30 seconds
"""
import unittest
import os
import sys
from mininet.util import ensureRoot
from mininet.clean import cleanup
def runTests( testDir, verbosity=1 ):
"discover and run all tests in testDir"
# ensure root and cleanup before starting tests
ensureRoot()
cleanup()
# discover all tests in testDir
testSuite = unittest.defaultTestLoader.discover( testDir )
# run tests
unittest.TextTestRunner( verbosity=verbosity ).run( testSuite )
if __name__ == '__main__':
# get the directory containing example tests
testDir = os.path.dirname( os.path.realpath( __file__ ) )
verbosity = 2 if '-v' in sys.argv else 1
runTests( testDir, verbosity )
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env python
"""
Tests for baresshd.py
"""
import unittest
import pexpect
from time import sleep
from mininet.clean import cleanup, sh
class testBareSSHD( unittest.TestCase ):
opts = [ '\(yes/no\)\?', 'Welcome to h1', 'refused', pexpect.EOF, pexpect.TIMEOUT ]
def connected( self ):
"Log into ssh server, check banner, then exit"
p = pexpect.spawn( 'ssh 10.0.0.1 -i /tmp/ssh/test_rsa exit' )
while True:
index = p.expect( self.opts )
if index == 0:
p.sendline( 'yes' )
elif index == 1:
return True
else:
return False
def setUp( self ):
# verify that sshd is not running
self.assertFalse( self.connected() )
# create public key pair for testing
sh( 'rm -rf /tmp/ssh' )
sh( 'mkdir /tmp/ssh' )
sh( "ssh-keygen -t rsa -P '' -f /tmp/ssh/test_rsa" )
sh( 'cat /tmp/ssh/test_rsa.pub >> /tmp/ssh/authorized_keys' )
# run example with custom sshd args
cmd = ( 'python -m mininet.examples.baresshd '
'-o AuthorizedKeysFile=/tmp/ssh/authorized_keys '
'-o StrictModes=no' )
sh( cmd )
def testSSH( self ):
"Simple test to verify that we can ssh into h1"
result = False
# try to connect up to 3 times; sshd can take a while to start
for _ in range( 3 ):
result = self.connected()
if result:
break
else:
sleep( 1 )
self.assertTrue( result )
def tearDown( self ):
# kill the ssh process
sh( "ps aux | grep 'ssh.*Banner' | awk '{ print $2 }' | xargs kill" )
cleanup()
# remove public key pair
sh( 'rm -rf /tmp/ssh' )
if __name__ == '__main__':
unittest.main()
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python
"""
Tests for bind.py
"""
import unittest
import pexpect
class testBind( unittest.TestCase ):
prompt = 'mininet>'
def setUp( self ):
self.net = pexpect.spawn( 'python -m mininet.examples.bind' )
self.net.expect( "Private Directories: \[([\w\s,'/]+)\]" )
self.directories = []
# parse directories from mn output
for d in self.net.match.group(1).split(', '):
self.directories.append( d.strip("'") )
self.net.expect( self.prompt )
self.assertTrue( len( self.directories ) > 0 )
def testCreateFile( self ):
"Create a file, a.txt, in the first private directory and verify"
fileName = 'a.txt'
directory = self.directories[ 0 ]
path = directory + '/' + fileName
self.net.sendline( 'h1 touch %s; ls %s' % ( path, directory ) )
index = self.net.expect( [ fileName, self.prompt ] )
self.assertTrue( index == 0 )
self.net.expect( self.prompt )
self.net.sendline( 'h1 rm %s' % path )
self.net.expect( self.prompt )
def testIsolation( self ):
"Create a file in two hosts and verify that contents are different"
fileName = 'b.txt'
directory = self.directories[ 0 ]
path = directory + '/' + fileName
contents = { 'h1' : '1', 'h2' : '2' }
# Verify file doesn't exist, then write private copy of file
for host in contents:
value = contents[ host ]
self.net.sendline( '%s cat %s' % ( host, path ) )
self.net.expect( 'No such file' )
self.net.expect( self.prompt )
self.net.sendline( '%s echo %s > %s' % ( host, value, path ) )
self.net.expect( self.prompt )
# Verify file contents
for host in contents:
value = contents[ host ]
self.net.sendline( '%s cat %s' % ( host, path ) )
self.net.expect( value )
self.net.expect( self.prompt )
self.net.sendline( '%s rm %s' % ( host, path ) )
self.net.expect( self.prompt )
# TODO: need more tests
def tearDown( self ):
self.net.sendline( 'exit' )
self.net.wait()
if __name__ == '__main__':
unittest.main()
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python
"""
Tests for controllers.py and controllers2.py
"""
import unittest
import pexpect
class testControllers( unittest.TestCase ):
prompt = 'mininet>'
def connectedTest( self, name, cmap ):
"Verify that switches are connected to the controller specified by cmap"
p = pexpect.spawn( 'python -m %s' % name )
p.expect( self.prompt )
# but first a simple ping test
p.sendline( 'pingall' )
p.expect ( '(\d+)% dropped' )
percent = int( p.match.group( 1 ) ) if p.match else -1
self.assertEqual( percent, 0 )
p.expect( self.prompt )
# verify connected controller
for switch in cmap:
p.sendline( 'sh ovs-vsctl get-controller %s' % switch )
p.expect( 'tcp:([\d.:]+)')
actual = p.match.group(1)
expected = cmap[ switch ]
self.assertEqual( actual, expected )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
def testControllers( self ):
c0 = '127.0.0.1:6633'
c1 = '127.0.0.1:6634'
cmap = { 's1': c0, 's2': c1, 's3': c0 }
self.connectedTest( 'mininet.examples.controllers', cmap )
def testControllers2( self ):
c0 = '127.0.0.1:6633'
c1 = '127.0.0.1:6634'
cmap = { 's1': c0, 's2': c1 }
self.connectedTest( 'mininet.examples.controllers2', cmap )
if __name__ == '__main__':
unittest.main()
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python
"""
Test for controlnet.py
"""
import unittest
import pexpect
class testControlNet( unittest.TestCase ):
prompt = 'mininet>'
def testPingall( self ):
"Simple pingall test that verifies 0% packet drop in data network"
p = pexpect.spawn( 'python -m mininet.examples.controlnet' )
p.expect( self.prompt )
p.sendline( 'pingall' )
p.expect ( '(\d+)% dropped' )
percent = int( p.match.group( 1 ) ) if p.match else -1
self.assertEqual( percent, 0 )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
def testFailover( self ):
"Kill controllers and verity that switch, s1, fails over properly"
count = 1
p = pexpect.spawn( 'python -m mininet.examples.controlnet' )
p.expect( self.prompt )
lp = pexpect.spawn( 'tail -f /tmp/s1-ofp.log' )
lp.expect( 'tcp:\d+\.\d+\.\d+\.(\d+):\d+: connected' )
ip = int( lp.match.group( 1 ) )
self.assertEqual( count, ip )
count += 1
for c in [ 'c0', 'c1' ]:
p.sendline( '%s ifconfig %s-eth0 down' % ( c, c) )
p.expect( self.prompt )
lp.expect( 'tcp:\d+\.\d+\.\d+\.(\d+):\d+: connected' )
ip = int( lp.match.group( 1 ) )
self.assertEqual( count, ip )
count += 1
p.sendline( 'exit' )
p.wait()
if __name__ == '__main__':
unittest.main()
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python
"""
Test for cpu.py
"""
import unittest
import pexpect
import sys
class testCPU( unittest.TestCase ):
prompt = 'mininet>'
@unittest.skipIf( '-quick' in sys.argv, 'long test' )
def testCPU( self ):
"Verify that CPU utilization is monotonically decreasing for each scheduler"
p = pexpect.spawn( 'python -m mininet.examples.cpu' )
opts = [ '([a-z]+)\t([\d\.]+)%\t([\d\.]+)', pexpect.EOF ]
scheds = []
while True:
index = p.expect( opts, timeout=600 )
if index == 0:
sched = p.match.group( 1 )
cpu = float( p.match.group( 2 ) )
bw = float( p.match.group( 3 ) )
if sched not in scheds:
scheds.append( sched )
previous_bw = 10 ** 4 # 10 GB/s
self.assertTrue( bw < previous_bw )
previous_bw = bw
else:
break
self.assertTrue( len( scheds ) > 0 )
if __name__ == '__main__':
unittest.main()
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env python
"""
Test for emptynet.py
"""
import unittest
import pexpect
class testEmptyNet( unittest.TestCase ):
prompt = 'mininet>'
def testEmptyNet( self ):
"Run simple CLI tests: pingall (verify 0% drop) and iperf (sanity)"
p = pexpect.spawn( 'python -m mininet.examples.emptynet' )
p.expect( self.prompt )
# pingall test
p.sendline( 'pingall' )
p.expect ( '(\d+)% dropped' )
percent = int( p.match.group( 1 ) ) if p.match else -1
self.assertEqual( percent, 0 )
p.expect( self.prompt )
# iperf test
p.sendline( 'iperf' )
p.expect( "Results: \['[\d.]+ .bits/sec', '[\d.]+ .bits/sec'\]" )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
if __name__ == '__main__':
unittest.main()
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env python
"""
Test for hwintf.py
"""
import unittest
import pexpect
import re
from mininet.log import setLogLevel
from mininet.net import Mininet
from mininet.node import Node
from mininet.link import Link, Intf
class testHwintf( unittest.TestCase ):
prompt = 'mininet>'
def setUp( self ):
self.h3 = Node( 't0', ip='10.0.0.3/8' )
self.n0 = Node( 't1', inNamespace=False )
Link( self.h3, self.n0 )
self.h3.configDefault()
def testLocalPing( self ):
"Verify connectivity between virtual hosts using pingall"
p = pexpect.spawn( 'python -m mininet.examples.hwintf %s' % self.n0.intf() )
p.expect( self.prompt )
p.sendline( 'pingall' )
p.expect ( '(\d+)% dropped' )
percent = int( p.match.group( 1 ) ) if p.match else -1
self.assertEqual( percent, 0 )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
def testExternalPing( self ):
"Verify connnectivity between virtual host and virtual-physical 'external' host "
p = pexpect.spawn( 'python -m mininet.examples.hwintf %s' % self.n0.intf() )
p.expect( self.prompt )
# test ping external to internal
expectStr = '(\d+) packets transmitted, (\d+) received'
m = re.search( expectStr, self.h3.cmd( 'ping -v -c 1 10.0.0.1' ) )
tx = m.group( 1 )
rx = m.group( 2 )
self.assertEqual( tx, rx )
# test ping internal to external
p.sendline( 'h1 ping -c 1 10.0.0.3')
p.expect( expectStr )
tx = p.match.group( 1 )
rx = p.match.group( 2 )
self.assertEqual( tx, rx )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
def tearDown( self ):
self.h3.terminate()
self.n0.terminate()
if __name__ == '__main__':
setLogLevel( 'warning' )
unittest.main()
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env python
"""
Test for limit.py
"""
import unittest
import pexpect
import sys
class testLimit( unittest.TestCase ):
@unittest.skipIf( '-quick' in sys.argv, 'long test' )
def testLimit( self ):
"Verify that CPU limits are within a 2% tolerance of limit for each scheduler"
p = pexpect.spawn( 'python -m mininet.examples.limit' )
opts = [ '\*\*\* Testing network ([\d\.]+) Mbps',
'\*\*\* Results: \[([\d\., ]+)\]',
pexpect.EOF ]
count = 0
bw = 0
tolerance = 2
while True:
index = p.expect( opts )
if index == 0:
bw = float( p.match.group( 1 ) )
count += 1
elif index == 1:
results = p.match.group( 1 )
for x in results.split( ',' ):
result = float( x )
self.assertTrue( result < bw + tolerance )
self.assertTrue( result > bw - tolerance )
else:
break
self.assertTrue( count > 0 )
if __name__ == '__main__':
unittest.main()
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env python
"""
Test for linearbandwidth.py
"""
import unittest
import pexpect
import sys
class testLinearBandwidth( unittest.TestCase ):
@unittest.skipIf( '-quick' in sys.argv, 'long test' )
def testLinearBandwidth( self ):
"Verify that bandwidth is monotonically decreasing as # of hops increases"
p = pexpect.spawn( 'python -m mininet.examples.linearbandwidth' )
count = 0
opts = [ '\*\*\* Linear network results',
'(\d+)\s+([\d\.]+) (.bits)',
pexpect.EOF ]
while True:
index = p.expect( opts, timeout=600 )
if index == 0:
previous_bw = 10 ** 10 # 10 Gbits
count += 1
elif index == 1:
n = int( p.match.group( 1 ) )
bw = float( p.match.group( 2 ) )
unit = p.match.group( 3 )
if unit[ 0 ] == 'K':
bw *= 10 ** 3
elif unit[ 0 ] == 'M':
bw *= 10 ** 6
elif unit[ 0 ] == 'G':
bw *= 10 ** 9
self.assertTrue( bw < previous_bw )
previous_bw = bw
else:
break
self.assertTrue( count > 0 )
if __name__ == '__main__':
unittest.main()
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python
"""
Test for multiping.py
"""
import unittest
import pexpect
from collections import defaultdict
class testMultiPing( unittest.TestCase ):
def testMultiPing( self ):
"""Verify that each target is pinged at least once, and
that pings to 'real' targets are successful and unknown targets fail"""
p = pexpect.spawn( 'python -m mininet.examples.multiping' )
opts = [ "Host (h\d+) \(([\d.]+)\) will be pinging ips: ([\d\. ]+)",
"(h\d+): ([\d.]+) -> ([\d.]+) \d packets transmitted, (\d) received",
pexpect.EOF ]
pings = defaultdict( list )
while True:
index = p.expect( opts )
if index == 0:
name = p.match.group(1)
ip = p.match.group(2)
targets = p.match.group(3).split()
pings[ name ] += targets
elif index == 1:
name = p.match.group(1)
ip = p.match.group(2)
target = p.match.group(3)
received = int( p.match.group(4) )
if target == '10.0.0.200':
self.assertEqual( received, 0 )
else:
self.assertEqual( received, 1 )
try:
pings[ name ].remove( target )
except:
pass
else:
break
self.assertTrue( len( pings ) > 0 )
for t in pings.values():
self.assertEqual( len( t ), 0 )
if __name__ == '__main__':
unittest.main()
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python
"""
Test for multipoll.py
"""
import unittest
import pexpect
class testMultiPoll( unittest.TestCase ):
def testMultiPoll( self ):
"Verify that we receive one ping per second per host"
p = pexpect.spawn( 'python -m mininet.examples.multipoll' )
opts = [ "\*\*\* (h\d) :" ,
"(h\d+): \d+ bytes from",
"Monitoring output for (\d+) seconds",
pexpect.EOF ]
pings = {}
while True:
index = p.expect( opts )
if index == 0:
name = p.match.group( 1 )
pings[ name ] = 0
elif index == 1:
name = p.match.group( 1 )
pings[ name ] += 1
elif index == 2:
seconds = int( p.match.group( 1 ) )
else:
break
self.assertTrue( len( pings ) > 0 )
# make sure we have received at least one ping per second
for count in pings.values():
self.assertTrue( count >= seconds )
if __name__ == '__main__':
unittest.main()
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env python
"""
Test for multitest.py
"""
import unittest
import pexpect
class testMultiTest( unittest.TestCase ):
prompt = 'mininet>'
def testMultiTest( self ):
"Verify pingall (0% dropped) and hX-eth0 interface for each host (ifconfig)"
p = pexpect.spawn( 'python -m mininet.examples.multitest' )
p.expect( '(\d+)% dropped' )
dropped = int( p.match.group( 1 ) )
self.assertEqual( dropped, 0 )
ifCount = 0
while True:
index = p.expect( [ 'h\d-eth0', self.prompt ] )
if index == 0:
ifCount += 1
elif index == 1:
p.sendline( 'exit' )
break
p.wait()
self.assertEqual( ifCount, 4 )
if __name__ == '__main__':
unittest.main()
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env python
"""
Test for nat.py
"""
import unittest
import pexpect
from mininet.util import quietRun
destIP = '8.8.8.8' # Google DNS
class testNAT( unittest.TestCase ):
prompt = 'mininet>'
@unittest.skipIf( '0 received' in quietRun( 'ping -c 1 %s' % destIP ),
'Destination IP is not reachable' )
def testNAT( self ):
"Attempt to ping an IP on the Internet and verify 0% packet loss"
p = pexpect.spawn( 'python -m mininet.examples.nat' )
p.expect( self.prompt )
p.sendline( 'h1 ping -c 1 %s' % destIP )
p.expect ( '(\d+)% packet loss' )
percent = int( p.match.group( 1 ) ) if p.match else -1
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
self.assertEqual( percent, 0 )
if __name__ == '__main__':
unittest.main()
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env python
"""
Test for popen.py and popenpoll.py
"""
import unittest
import pexpect
class testPopen( unittest.TestCase ):
def pingTest( self, name ):
"Verify that there are no dropped packets for each host"
p = pexpect.spawn( 'python -m %s' % name )
opts = [ "<(h\d+)>: PING ",
"<(h\d+)>: (\d+) packets transmitted, (\d+) received",
pexpect.EOF ]
pings = {}
while True:
index = p.expect( opts )
if index == 0:
name = p.match.group(1)
pings[ name ] = 0
elif index == 1:
name = p.match.group(1)
transmitted = p.match.group(2)
received = p.match.group(3)
# verify no dropped packets
self.assertEqual( received, transmitted )
pings[ name ] += 1
else:
break
self.assertTrue( len(pings) > 0 )
# verify that each host has gotten results
for count in pings.values():
self.assertEqual( count, 1 )
def testPopen( self ):
self.pingTest( 'mininet.examples.popen' )
def testPopenPoll( self ):
self.pingTest( 'mininet.examples.popenpoll' )
if __name__ == '__main__':
unittest.main()
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env python
"""
Test for scratchnet.py
"""
import unittest
import pexpect
class testScratchNet( unittest.TestCase ):
opts = [ "1 packets transmitted, 1 received, 0% packet loss", pexpect.EOF ]
def pingTest( self, name ):
"Verify that no ping packets were dropped"
p = pexpect.spawn( 'python -m %s' % name )
index = p.expect( self.opts )
self.assertEqual( index, 0 )
def testPingKernel( self ):
self.pingTest( 'mininet.examples.scratchnet' )
def testPingUser( self ):
self.pingTest( 'mininet.examples.scratchnetuser' )
if __name__ == '__main__':
unittest.main()
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env python
"""
Test for simpleperf.py
"""
import unittest
import pexpect
import re
import sys
from mininet.log import setLogLevel
from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.link import TCLink
from mininet.examples.simpleperf import SingleSwitchTopo
class testSimplePerf( unittest.TestCase ):
@unittest.skipIf( '-quick' in sys.argv, 'long test' )
def testE2E( self ):
"Run the example and verify ping and iperf results"
p = pexpect.spawn( 'python -m mininet.examples.simpleperf' )
# check ping results
p.expect( "Results: (\d+)% dropped", timeout=120 )
loss = int( p.match.group( 1 ) )
self.assertTrue( loss > 0 and loss < 100 )
# check iperf results
p.expect( "Results: \['([\d\.]+) .bits/sec", timeout=480 )
bw = float( p.match.group( 1 ) )
self.assertTrue( bw > 0 )
p.wait()
def testTopo( self ):
"""Import SingleSwitchTopo from example and test connectivity between two hosts
Note: this test may fail very rarely because it is non-deterministic
i.e. links are configured with 10% packet loss, but if we get unlucky and
none or all of the packets are dropped, the test will fail"""
topo = SingleSwitchTopo( n=4 )
net = Mininet( topo=topo, host=CPULimitedHost, link=TCLink )
net.start()
h1, h4 = net.get( 'h1', 'h4' )
# have h1 ping h4 ten times
expectStr = '(\d+) packets transmitted, (\d+) received, (\d+)% packet loss'
output = h1.cmd( 'ping -c 10 %s' % h4.IP() )
m = re.search( expectStr, output )
loss = int( m.group( 3 ) )
net.stop()
self.assertTrue( loss > 0 and loss < 100 )
if __name__ == '__main__':
setLogLevel( 'warning' )
unittest.main()
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env python
"""
Test for sshd.py
"""
import unittest
import pexpect
from time import sleep
from mininet.clean import sh
class testSSHD( unittest.TestCase ):
opts = [ '\(yes/no\)\?', 'refused', 'Welcome|\$|#', pexpect.EOF, pexpect.TIMEOUT ]
def connected( self, ip ):
"Log into ssh server, check banner, then exit"
# Note: this test will fail if "Welcome" is not in the sshd banner
# and '#'' or '$'' are not in the prompt
p = pexpect.spawn( 'ssh -i /tmp/ssh/test_rsa %s' % ip, timeout=10 )
while True:
index = p.expect( self.opts )
if index == 0:
print p.match.group(0)
p.sendline( 'yes' )
elif index == 1:
return False
elif index == 2:
p.sendline( 'exit' )
p.wait()
return True
else:
return False
def setUp( self ):
# create public key pair for testing
sh( 'rm -rf /tmp/ssh' )
sh( 'mkdir /tmp/ssh' )
sh( "ssh-keygen -t rsa -P '' -f /tmp/ssh/test_rsa" )
sh( 'cat /tmp/ssh/test_rsa.pub >> /tmp/ssh/authorized_keys' )
cmd = ( 'python -m mininet.examples.sshd -D '
'-o AuthorizedKeysFile=/tmp/ssh/authorized_keys '
'-o StrictModes=no' )
# run example with custom sshd args
self.net = pexpect.spawn( cmd )
self.net.expect( 'mininet>' )
def testSSH( self ):
"Verify that we can ssh into all hosts (h1 to h4)"
for h in range( 1, 5 ):
self.assertTrue( self.connected( '10.0.0.%d' % h ) )
def tearDown( self ):
self.net.sendline( 'exit' )
self.net.wait()
# remove public key pair
sh( 'rm -rf /tmp/ssh' )
if __name__ == '__main__':
unittest.main()
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env python
"""
Test for tree1024.py
"""
import unittest
import pexpect
import sys
class testTree1024( unittest.TestCase ):
prompt = 'mininet>'
@unittest.skipIf( '-quick' in sys.argv, 'long test' )
def testTree1024( self ):
"Run the example and do a simple ping test from h1 to h1024"
p = pexpect.spawn( 'python -m mininet.examples.tree1024' )
p.expect( self.prompt, timeout=6000 ) # it takes awhile to set up
p.sendline( 'h1 ping -c 1 h1024' )
p.expect ( '(\d+)% packet loss' )
percent = int( p.match.group( 1 ) ) if p.match else -1
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
self.assertEqual( percent, 0 )
if __name__ == '__main__':
unittest.main()
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env python
"""
Test for treeping64.py
"""
import unittest
import pexpect
import sys
class testTreePing64( unittest.TestCase ):
prompt = 'mininet>'
@unittest.skipIf( '-quick' in sys.argv, 'long test' )
def testTreePing64( self ):
"Run the example and verify ping results"
p = pexpect.spawn( 'python -m mininet.examples.treeping64' )
p.expect( 'Tree network ping results:', timeout=6000 )
count = 0
while True:
index = p.expect( [ '(\d+)% packet loss', pexpect.EOF ] )
if index == 0:
percent = int( p.match.group( 1 ) ) if p.match else -1
self.assertEqual( percent, 0 )
count += 1
else:
break
self.assertTrue( count > 0 )
if __name__ == '__main__':
unittest.main()
+5 -6
View File
@@ -323,14 +323,13 @@ class CLI( Cmd ):
corresponding IP addrs."""
first, args, line = self.parseline( line )
if not args:
return
if args and len(args) > 0 and args[ -1 ] == '\n':
args = args[ :-1 ]
rest = args.split( ' ' )
if first in self.mn:
if not args:
print "*** Enter a command for node: %s <cmd>" % first
return
node = self.mn[ first ]
rest = args.split( ' ' )
# Substitute IP addresses for node names in command
rest = [ self.mn[ arg ].defaultIntf().updateIP()
if arg in self.mn else arg
@@ -341,7 +340,7 @@ class CLI( Cmd ):
node.sendCmd( rest, printPid=( not builtin ) )
self.waitForNode( node )
else:
error( '*** Unknown command: %s\n' % first )
error( '*** Unknown command: %s\n' % line )
# pylint: enable-msg=R0201
+1
View File
@@ -0,0 +1 @@
../examples
+21 -11
View File
@@ -102,7 +102,7 @@ from mininet.util import macColonHex, ipStr, ipParse, netParse, ipAdd
from mininet.term import cleanUpScreens, makeTerms
# Mininet version: should be consistent with README and LICENSE
VERSION = "2.0.0"
VERSION = "2.1.0"
class Mininet( object ):
"Network emulation with hosts spawned in network namespaces."
@@ -209,9 +209,19 @@ class Mininet( object ):
def addController( self, name='c0', controller=None, **params ):
"""Add controller.
controller: Controller class"""
# Get controller class
if not controller:
controller = self.controller
controller_new = controller( name, **params )
# Construct new controller if one is not given
if isinstance(name, Controller):
controller_new = name
# Pylint thinks controller is a str()
# pylint: disable=E1103
name = controller_new.name
# pylint: enable=E1103
else:
controller_new = controller( name, **params )
# Add new controller to net
if controller_new: # allow controller-less setups
self.controllers.append( controller_new )
self.nameToNode[ name ] = controller_new
@@ -230,31 +240,31 @@ class Mininet( object ):
return self.getNodeByName( *args )
# Even more convenient syntax for node lookup and iteration
def __getitem__( self, *args ):
def __getitem__( self, key ):
"""net [ name ] operator: Return node(s) with given name(s)"""
return self.getNodeByName( *args )
return self.nameToNode[ key ]
def __iter__( self ):
"return iterator over nodes"
#or dow we want to iterate of the keys i.e. node.name like a dict
"return iterator over node names"
for node in chain( self.hosts, self.switches, self.controllers ):
yield node.name
def __len__( self ):
"returns number of nodes in net"
return len( self.hosts ) + len( self.switches ) + len( self.controllers )
return ( len( self.hosts ) + len( self.switches ) +
len( self.controllers ) )
def __contains__( self, item ):
"returns True if net contains named node"
return item in self.keys()
return item in self.nameToNode
def keys( self ):
"return a list of all node names or net's keys"
return list( self.__iter__() )
return list( self )
def values( self ):
"return a list of all nodes or net's values"
return [ self[name] for name in self.__iter__() ]
return [ self[name] for name in self ]
def items( self ):
"return (key,value) tuple list for every node in net"
@@ -307,7 +317,7 @@ class Mininet( object ):
info( '*** Creating network\n' )
if not self.controllers:
if not self.controllers and self.controller:
# Add a default controller
info( '*** Adding controller\n' )
classes = self.controller
+7 -3
View File
@@ -183,7 +183,8 @@ class Node( object ):
def terminate( self ):
"Send kill signal to Node and clean up after it."
os.kill( self.pid, signal.SIGKILL )
if self.shell:
os.kill( self.pid, signal.SIGKILL )
self.cleanup()
def stop( self ):
@@ -1050,6 +1051,8 @@ class OVSSwitch( Switch ):
def stop( self ):
"Terminate OVS switch."
self.cmd( 'ovs-vsctl del-br', self )
if self.datapath == 'user':
self.cmd( 'ip link del', self )
self.deleteIntfs()
OVSKernelSwitch = OVSSwitch
@@ -1140,7 +1143,7 @@ class Controller( Node ):
"installed." )
listening = self.cmd( "echo A | telnet -e A %s %d" %
( self.ip, self.port ) )
if 'refused' not in listening:
if 'Connected' in listening:
servers = self.cmd( 'netstat -atp' ).split( '\n' )
pstr = ':%d ' % self.port
clist = servers[ 0:1 ] + [ s for s in servers if pstr in s ]
@@ -1235,6 +1238,7 @@ class RemoteController( Controller ):
"Warn if remote controller is not accessible"
listening = self.cmd( "echo A | telnet -e A %s %d" %
( self.ip, self.port ) )
if 'refused' in listening:
if 'Connected' not in listening:
warn( "Unable to contact the remote controller"
" at %s:%d\n" % ( self.ip, self.port ) )
+28 -9
View File
@@ -4,13 +4,15 @@
Test creation and pings for topologies with link and/or CPU options."""
import unittest
from functools import partial
from mininet.net import Mininet
from mininet.node import OVSKernelSwitch, UserSwitch, IVSSwitch
from mininet.node import OVSSwitch, UserSwitch, IVSSwitch
from mininet.node import CPULimitedHost
from mininet.link import TCLink
from mininet.topo import Topo
from mininet.log import setLogLevel
from mininet.util import quietRun
# Number of hosts for each test
N = 2
@@ -29,9 +31,12 @@ class SingleSwitchOptionsTopo(Topo):
host = self.addHost('h%s' % (h + 1))
self.addLink(host, switch)
# Tell pylint not to complain about calls to other class
# pylint: disable=E1101
class testOptionsTopoCommon( object ):
"Verify ability to create networks with host and link options (common code)."
"""Verify ability to create networks with host and link options
(common code)."""
switchClass = None # overridden in subclasses
@@ -39,7 +44,8 @@ class testOptionsTopoCommon( object ):
"Generic topology-with-options test runner."
mn = Mininet( topo=SingleSwitchOptionsTopo( n=n, hopts=hopts,
lopts=lopts ),
host=CPULimitedHost, link=TCLink, switch=self.switchClass )
host=CPULimitedHost, link=TCLink,
switch=self.switchClass )
dropped = mn.run( mn.ping )
self.assertEqual( dropped, 0 )
@@ -105,7 +111,8 @@ class testOptionsTopoCommon( object ):
REPS = 1
lopts = { 'loss': LOSS_PERCENT, 'use_htb': True }
mn = Mininet( topo=SingleSwitchOptionsTopo( n=N, lopts=lopts ),
host=CPULimitedHost, link=TCLink, switch=self.switchClass )
host=CPULimitedHost, link=TCLink,
switch=self.switchClass )
# Drops are probabilistic, but the chance of no dropped packets is
# 1 in 100 million with 4 hops for a link w/99% loss.
dropped_total = 0
@@ -121,16 +128,28 @@ class testOptionsTopoCommon( object ):
hopts = { 'cpu': 0.5 / N }
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
# pylint: enable=E1101
class testOptionsTopoOVSKernel( testOptionsTopoCommon, unittest.TestCase ):
"""Verify ability to create networks with host and link options
(OVS kernel switch)."""
switchClass = OVSSwitch
@unittest.skip( 'Skipping OVS user switch test for now' )
class testOptionsTopoOVSUser( testOptionsTopoCommon, unittest.TestCase ):
"""Verify ability to create networks with host and link options
(OVS user switch)."""
switchClass = partial( OVSSwitch, datapath='user' )
@unittest.skipUnless( quietRun( 'which ivs-ctl' ), 'IVS is not installed' )
class testOptionsTopoIVS( testOptionsTopoCommon, unittest.TestCase ):
"Verify ability to create networks with host and link options (IVS switch)."
"Verify ability to create networks with host and link options (IVS)."
switchClass = IVSSwitch
@unittest.skipUnless( quietRun( 'which ofprotocol' ),
'Reference user switch is not installed' )
class testOptionsTopoUserspace( testOptionsTopoCommon, unittest.TestCase ):
"Verify ability to create networks with host and link options (Userspace switch)."
"Verify ability to create networks with host and link options (UserSwitch)."
switchClass = UserSwitch
if __name__ == '__main__':
+31 -4
View File
@@ -4,13 +4,17 @@
Test creation and all-pairs ping for each included mininet topo type."""
import unittest
from functools import partial
from mininet.net import Mininet
from mininet.node import Host, Controller
from mininet.node import UserSwitch, OVSKernelSwitch, IVSSwitch
from mininet.node import UserSwitch, OVSSwitch, IVSSwitch
from mininet.topo import SingleSwitchTopo, LinearTopo
from mininet.log import setLogLevel
from mininet.util import quietRun
# Tell pylint not to complain about calls to other class
# pylint: disable=E1101
class testSingleSwitchCommon( object ):
"Test ping with single switch topology (common code)."
@@ -25,23 +29,36 @@ class testSingleSwitchCommon( object ):
def testSingle5( self ):
"Ping test on 5-host single-switch topology"
mn = Mininet( SingleSwitchTopo( k=5 ), self.switchClass, Host, Controller )
mn = Mininet( SingleSwitchTopo( k=5 ), self.switchClass, Host,
Controller )
dropped = mn.run( mn.ping )
self.assertEqual( dropped, 0 )
# pylint: enable=E1101
class testSingleSwitchOVSKernel( testSingleSwitchCommon, unittest.TestCase ):
"Test ping with single switch topology (OVS kernel switch)."
switchClass = OVSKernelSwitch
switchClass = OVSSwitch
class testSingleSwitchOVSUser( testSingleSwitchCommon, unittest.TestCase ):
"Test ping with single switch topology (OVS user switch)."
switchClass = partial( OVSSwitch, datapath='user' )
@unittest.skipUnless( quietRun( 'which ivs-ctl' ), 'IVS is not installed' )
class testSingleSwitchIVS( testSingleSwitchCommon, unittest.TestCase ):
"Test ping with single switch topology (IVS switch)."
switchClass = IVSSwitch
@unittest.skipUnless( quietRun( 'which ofprotocol' ),
'Reference user switch is not installed' )
class testSingleSwitchUserspace( testSingleSwitchCommon, unittest.TestCase ):
"Test ping with single switch topology (Userspace switch)."
switchClass = UserSwitch
# Tell pylint not to complain about calls to other class
# pylint: disable=E1101
class testLinearCommon( object ):
"Test all-pairs ping with LinearNet (common code)."
@@ -53,14 +70,24 @@ class testLinearCommon( object ):
dropped = mn.run( mn.ping )
self.assertEqual( dropped, 0 )
# pylint: enable=E1101
class testLinearOVSKernel( testLinearCommon, unittest.TestCase ):
"Test all-pairs ping with LinearNet (OVS kernel switch)."
switchClass = OVSKernelSwitch
switchClass = OVSSwitch
class testLinearOVSUser( testLinearCommon, unittest.TestCase ):
"Test all-pairs ping with LinearNet (OVS user switch)."
switchClass = partial( OVSSwitch, datapath='user' )
@unittest.skipUnless( quietRun( 'which ivs-ctl' ), 'IVS is not installed' )
class testLinearIVS( testLinearCommon, unittest.TestCase ):
"Test all-pairs ping with LinearNet (IVS switch)."
switchClass = IVSSwitch
@unittest.skipUnless( quietRun( 'which ofprotocol' ),
'Reference user switch is not installed' )
class testLinearUserspace( testLinearCommon, unittest.TestCase ):
"Test all-pairs ping with LinearNet (Userspace switch)."
switchClass = UserSwitch
+2 -4
View File
@@ -250,9 +250,9 @@ class LinearTopo(Topo):
self.n = n
if n == 1:
genHostName = lambda i,j: 'h%s' % i
genHostName = lambda i, j: 'h%s' % i
else:
genHostName = lambda i,j: 'h%ss%d' % (j,i)
genHostName = lambda i, j: 'h%ss%d' % (j, i)
lastSwitch = None
@@ -261,8 +261,6 @@ class LinearTopo(Topo):
switch = self.addSwitch('s%s' % i)
# Add hosts to switch
for j in irange(1, n):
hostNum = (i-1)*n + j
#host = self.addHost('h%s' % hostNum)
host = self.addHost(genHostName(i, j))
self.addLink(host, switch)
# Connect switch to previous
+36 -29
View File
@@ -1,6 +1,6 @@
"Utility functions for Mininet."
from mininet.log import output, info, error, warn
from mininet.log import output, info, error, warn, debug
from time import sleep
from resource import getrlimit, setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE
@@ -361,16 +361,17 @@ def sysctlTestAndSet( name, limit ):
if '/' not in name:
name = '/proc/sys/' + name.replace( '.', '/' )
#read limit
f = open( name, 'r+' )
oldLimit = f.readline()
if type( limit ) is int:
#compare integer limits before overriding
if int( oldLimit ) < limit:
f.write( "%d" % limit )
else:
#overwrite non-integer limits
f.write( limit )
f.close()
with open( name, 'r' ) as readFile:
oldLimit = readFile.readline()
if type( limit ) is int:
#compare integer limits before overriding
if int( oldLimit ) < limit:
with open( name, 'w' ) as writeFile:
writeFile.write( "%d" % limit )
else:
#overwrite non-integer limits
with open( name, 'w' ) as writeFile:
writeFile.write( limit )
def rlimitTestAndSet( name, limit ):
"Helper function to set rlimits"
@@ -381,24 +382,30 @@ def rlimitTestAndSet( name, limit ):
def fixLimits():
"Fix ridiculously small resource limits."
rlimitTestAndSet( RLIMIT_NPROC, 8192 )
rlimitTestAndSet( RLIMIT_NOFILE, 16384 )
#Increase open file limit
sysctlTestAndSet( 'fs.file-max', 10000 )
#Increase network buffer space
sysctlTestAndSet( 'net.core.wmem_max', 16777216 )
sysctlTestAndSet( 'net.core.rmem_max', 16777216 )
sysctlTestAndSet( 'net.ipv4.tcp_rmem', '10240 87380 16777216' )
sysctlTestAndSet( 'net.ipv4.tcp_wmem', '10240 87380 16777216' )
sysctlTestAndSet( 'net.core.netdev_max_backlog', 5000 )
#Increase arp cache size
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh1', 4096 )
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh2', 8192 )
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh3', 16384 )
#Increase routing table size
sysctlTestAndSet( 'net.ipv4.route.max_size', 32768 )
#Increase number of PTYs for nodes
sysctlTestAndSet( 'kernel.pty.max', 20000 )
debug( "*** Setting resource limits\n" )
try:
rlimitTestAndSet( RLIMIT_NPROC, 8192 )
rlimitTestAndSet( RLIMIT_NOFILE, 16384 )
#Increase open file limit
sysctlTestAndSet( 'fs.file-max', 10000 )
#Increase network buffer space
sysctlTestAndSet( 'net.core.wmem_max', 16777216 )
sysctlTestAndSet( 'net.core.rmem_max', 16777216 )
sysctlTestAndSet( 'net.ipv4.tcp_rmem', '10240 87380 16777216' )
sysctlTestAndSet( 'net.ipv4.tcp_wmem', '10240 87380 16777216' )
sysctlTestAndSet( 'net.core.netdev_max_backlog', 5000 )
#Increase arp cache size
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh1', 4096 )
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh2', 8192 )
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh3', 16384 )
#Increase routing table size
sysctlTestAndSet( 'net.ipv4.route.max_size', 32768 )
#Increase number of PTYs for nodes
sysctlTestAndSet( 'kernel.pty.max', 20000 )
assert False
except:
warn( "*** Error setting resource limits. "
"Mininet's performance may be affected.\n" )
def mountCgroups():
"Make sure cgroups file system is mounted"
+4 -4
View File
@@ -20,19 +20,19 @@ setup(
description='Process-based OpenFlow emulator',
author='Bob Lantz',
author_email='rlantz@cs.stanford.edu',
packages=find_packages(exclude='test'),
packages=[ 'mininet', 'mininet.examples' ],
long_description="""
Mininet is a network emulator which uses lightweight
virtualization to create virtual networks for rapid
prototyping of Software-Defined Network (SDN) designs
using OpenFlow. http://openflow.org/mininet
using OpenFlow. http://mininet.org
""",
classifiers=[
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Development Status :: 2 - Pre-Alpha",
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Topic :: Internet",
"Topic :: System :: Emulators",
],
keywords='networking emulator protocol Internet OpenFlow SDN',
license='BSD',
+10 -7
View File
@@ -10,15 +10,15 @@ set -e
set -o nounset
# Get directory containing mininet folder
MININET_DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
MININET_DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd -P )"
# Set up build directory, which by default is the working directory
# unless the working directory is a subdirectory of mininet,
# in which case we use the directory containing mininet
BUILD_DIR=$PWD
case $PWD in
BUILD_DIR="$(pwd -P)"
case $BUILD_DIR in
$MININET_DIR/*) BUILD_DIR=$MININET_DIR;; # currect directory is a subdirectory
*) BUILD_DIR=$PWD;;
*) BUILD_DIR=$BUILD_DIR;;
esac
# Location of CONFIG_NET_NS-enabled kernel(s)
@@ -281,7 +281,7 @@ function wireshark {
export WIRESHARK=/usr/include/wireshark
scons
# libwireshark0/ on 11.04; libwireshark1/ on later
WSDIR=`ls -d /usr/lib/wireshark/libwireshark* | head -1`
WSDIR=`find /usr/lib -type d -name 'libwireshark*' | head -1`
WSPLUGDIR=$WSDIR/plugins/
sudo cp openflow.so $WSPLUGDIR
echo "Copied openflow plugin to $WSPLUGDIR"
@@ -645,13 +645,16 @@ function all {
printf "with Fedora's kernel (3.10) and openvswitch (1.10.0) packages.\n"
exit 3
fi
echo "Running all commands..."
echo "Installing all packages except for -eix (doxypy, ivs, nox-classic)..."
kernel
mn_deps
mn_dev
# Skip mn_dev (doxypy/texlive/fonts/etc.) because it's huge
# mn_dev
of
wireshark
ovs
# We may add ivs once it's more mature
# ivs
# NOX-classic is deprecated, but you can install it manually if desired.
# nox
pox
+9 -1
View File
@@ -33,4 +33,12 @@ if [ -d "$cgroup" ]; then
cg="-g $host"
fi
exec sudo mnexec -a $pid $cg $cmd
# Check whether host should be running in a chroot dir
rootdir="/var/run/mn/$host/root"
if [ -d $rootdir -a -x $rootdir/bin/bash ]; then
cmd="'cd `pwd`; exec $cmd'"
cmd="chroot $rootdir /bin/bash -c $cmd"
fi
cmd="exec sudo mnexec -a $pid $cg $cmd"
eval $cmd
+678 -255
View File
File diff suppressed because it is too large Load Diff