CI matrix build + 20.04 fixes (#990)

Ubuntu 20.04 fixes:
- fixes sshd test
- speeds up examples/{treeping64,tree1024}.py
- debugging hacks/output for testLinkChange
- removes cfs from examples/popen.py
- improves nat in nodelib (netplan fixes?)
- makes some tests executable
- waits for switches to connect in tests to
  avoid race conditions
-- adds mn -w option and wait CLI command
Changes:
- REMOVES default "-v" argument for Controller()
  and adds verbose(=False) option; avoiding logging
  makes it faster
- CHANGES waitConnected to wait for 5 seconds
  as documented; we may wish to implement an argument
  to -w to set this timeout
Issues?
- There may still be an issue with the ovs-netplan-clean
  service causing the boot to hang ;-(
This commit is contained in:
lantz
2021-01-03 20:00:33 -08:00
committed by GitHub
parent afdf9fd571
commit b7c412073a
39 changed files with 119 additions and 78 deletions
+3 -5
View File
@@ -9,7 +9,7 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-18.04, ubuntu-16.04] os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04]
python-version: [3.x, 2.x] python-version: [3.x, 2.x]
steps: steps:
- name: Check out Mininet source - name: Check out Mininet source
@@ -47,12 +47,10 @@ jobs:
export sudo="sudo env PATH=$PATH" export sudo="sudo env PATH=$PATH"
export PYTHON=`which python` export PYTHON=`which python`
rm -f pexpect.out rm -f pexpect.out
$sudo $PYTHON mininet/test/runner.py -v -quick || \ $sudo $PYTHON mininet/test/runner.py -v -quick
(cat pexpect.out && exit 1)
- name: Run examples tests (quick) - name: Run examples tests (quick)
run: | run: |
export sudo="sudo env PATH=$PATH" export sudo="sudo env PATH=$PATH"
export PYTHON=`which python` export PYTHON=`which python`
rm -f pexpect.out rm -f pexpect.out
$sudo $PYTHON examples/test/runner.py -v -quick || \ $sudo $PYTHON examples/test/runner.py -v -quick
(cat pexpect.out && exit 1)
+1 -1
View File
@@ -132,4 +132,4 @@ Bob Lantz
Mininet Core Team Mininet Core Team
[1]: https://travis-ci.org/mininet/mininet.svg?branch=master [1]: https://travis-ci.org/mininet/mininet.svg?branch=master
[2]: https://github.com/mininet/mininet/workflows/mininet%20tests/badge.svg [2]: https://github.com/mininet/mininet/workflows/mininet-tests/badge.svg
+3
View File
@@ -284,6 +284,8 @@ class MininetRunner( object ):
" Mininet's IP subnet, see the --ipbase option." ) " Mininet's IP subnet, see the --ipbase option." )
opts.add_option( '--version', action='callback', callback=version, opts.add_option( '--version', action='callback', callback=version,
help='prints the version and exits' ) help='prints the version and exits' )
opts.add_option( '--wait', '-w', action='store_true',
default=False, help='wait for switches to connect' )
opts.add_option( '--cluster', type='string', default=None, opts.add_option( '--cluster', type='string', default=None,
metavar='server1,server2...', metavar='server1,server2...',
help=( 'run on multiple servers (experimental!)' ) ) help=( 'run on multiple servers (experimental!)' ) )
@@ -385,6 +387,7 @@ class MininetRunner( object ):
ipBase=opts.ipbase, inNamespace=opts.innamespace, ipBase=opts.ipbase, inNamespace=opts.innamespace,
xterms=opts.xterms, autoSetMacs=opts.mac, xterms=opts.xterms, autoSetMacs=opts.mac,
autoStaticArp=opts.arp, autoPinCpus=opts.pin, autoStaticArp=opts.arp, autoPinCpus=opts.pin,
waitConnected=opts.wait,
listenPort=opts.listenport ) listenPort=opts.listenport )
if opts.ensure_value( 'nat', False ): if opts.ensure_value( 'nat', False ):
+1 -1
View File
@@ -53,7 +53,7 @@ def testHostWithPrivateDirs():
'/var/mn' ] '/var/mn' ]
host = partial( Host, host = partial( Host,
privateDirs=privateDirs ) privateDirs=privateDirs )
net = Mininet( topo=topo, host=host ) net = Mininet( topo=topo, host=host, waitConnected=True )
net.start() net.start()
directories = [ directory[ 0 ] if isinstance( directory, tuple ) directories = [ directory[ 0 ] if isinstance( directory, tuple )
else directory for directory in privateDirs ] else directory for directory in privateDirs ]
+3 -2
View File
@@ -875,7 +875,7 @@ class MininetCluster( Mininet ):
def testNsTunnels( remote='ubuntu2', link=RemoteGRELink ): def testNsTunnels( remote='ubuntu2', link=RemoteGRELink ):
"Test tunnels between nodes in namespaces" "Test tunnels between nodes in namespaces"
net = Mininet( host=RemoteHost, link=link ) net = Mininet( host=RemoteHost, link=link, waitConnected=True )
h1 = net.addHost( 'h1') h1 = net.addHost( 'h1')
h2 = net.addHost( 'h2', server=remote ) h2 = net.addHost( 'h2', server=remote )
net.addLink( h1, h2 ) net.addLink( h1, h2 )
@@ -891,7 +891,8 @@ def testNsTunnels( remote='ubuntu2', link=RemoteGRELink ):
def testRemoteNet( remote='ubuntu2', link=RemoteGRELink ): def testRemoteNet( remote='ubuntu2', link=RemoteGRELink ):
"Test remote Node classes" "Test remote Node classes"
info( '*** Remote Node Test\n' ) info( '*** Remote Node Test\n' )
net = Mininet( host=RemoteHost, switch=RemoteOVSSwitch, link=link ) net = Mininet( host=RemoteHost, switch=RemoteOVSSwitch, link=link,
waitConnected=True )
c0 = net.addController( 'c0' ) c0 = net.addController( 'c0' )
# Make sure controller knows its non-loopback address # Make sure controller knows its non-loopback address
Intf( 'eth0', node=c0 ).updateIP() Intf( 'eth0', node=c0 ).updateIP()
+1 -1
View File
@@ -8,7 +8,7 @@ from mininet.log import setLogLevel
def perf(Link): def perf(Link):
"Test connectivity nand performance over Link" "Test connectivity nand performance over Link"
net = Mininet( host=RemoteHost, link=Link ) net = Mininet( host=RemoteHost, link=Link, waitConnected=True )
h1 = net.addHost( 'h1') h1 = net.addHost( 'h1')
h2 = net.addHost( 'h2', server='ubuntu2' ) h2 = net.addHost( 'h2', server='ubuntu2' )
net.addLink( h1, h2 ) net.addLink( h1, h2 )
+1 -1
View File
@@ -27,7 +27,7 @@ class MultiSwitch( OVSSwitch ):
return OVSSwitch.start( self, [ cmap[ self.name ] ] ) return OVSSwitch.start( self, [ cmap[ self.name ] ] )
topo = TreeTopo( depth=2, fanout=2 ) topo = TreeTopo( depth=2, fanout=2 )
net = Mininet( topo=topo, switch=MultiSwitch, build=False ) net = Mininet( topo=topo, switch=MultiSwitch, build=False, waitConnected=True )
for c in [ c0, c1 ]: for c in [ c0, c1 ]:
net.addController(c) net.addController(c)
net.build() net.build()
+2 -1
View File
@@ -20,7 +20,8 @@ from mininet.log import setLogLevel, info
def multiControllerNet(): def multiControllerNet():
"Create a network from semi-scratch with multiple controllers." "Create a network from semi-scratch with multiple controllers."
net = Mininet( controller=Controller, switch=OVSSwitch ) net = Mininet( controller=Controller, switch=OVSSwitch,
waitConnected=True )
info( "*** Creating (reference) controllers\n" ) info( "*** Creating (reference) controllers\n" )
c1 = net.addController( 'c1', port=6633 ) c1 = net.addController( 'c1', port=6633 )
+4 -2
View File
@@ -123,7 +123,8 @@ def run():
info( '* Creating Control Network\n' ) info( '* Creating Control Network\n' )
ctopo = ControlNetwork( n=4, dataController=DataController ) ctopo = ControlNetwork( n=4, dataController=DataController )
cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24', controller=None ) cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24',
controller=None, waitConnected=True )
info( '* Adding Control Network Controller\n') info( '* Adding Control Network Controller\n')
cnet.addController( 'cc0', controller=Controller ) cnet.addController( 'cc0', controller=Controller )
info( '* Starting Control Network\n') info( '* Starting Control Network\n')
@@ -133,7 +134,8 @@ def run():
topo = TreeTopo( depth=2, fanout=2 ) topo = TreeTopo( depth=2, fanout=2 )
# UserSwitch so we can easily test failover # UserSwitch so we can easily test failover
sw = partial( UserSwitch, opts='--inactivity-probe=1 --max-backoff=1' ) sw = partial( UserSwitch, opts='--inactivity-probe=1 --max-backoff=1' )
net = Mininet( topo=topo, switch=sw, controller=None ) net = Mininet( topo=topo, switch=sw, controller=None,
waitConnected=True )
info( '* Adding Controllers to Data Network\n' ) info( '* Adding Controllers to Data Network\n' )
for host in cnet.hosts: for host in cnet.hosts:
if isinstance(host, Controller): if isinstance(host, Controller):
+1 -1
View File
@@ -52,7 +52,7 @@ def bwtest( cpuLimits, period_us=100000, seconds=10 ):
period_us=period_us, period_us=period_us,
cpu=.5*cpu ) cpu=.5*cpu )
try: try:
net = Mininet( topo=topo, host=host ) net = Mininet( topo=topo, host=host, waitConnected=True )
# pylint: disable=bare-except # pylint: disable=bare-except
except: except:
info( '*** Skipping scheduler %s and cleaning up\n' % sched ) info( '*** Skipping scheduler %s and cleaning up\n' % sched )
+1 -1
View File
@@ -14,7 +14,7 @@ def emptyNet():
"Create an empty network and add nodes to it." "Create an empty network and add nodes to it."
net = Mininet( controller=Controller ) net = Mininet( controller=Controller, waitConnected=True )
info( '*** Adding controller\n' ) info( '*** Adding controller\n' )
net.addController( 'c0' ) net.addController( 'c0' )
+1 -1
View File
@@ -38,7 +38,7 @@ if __name__ == '__main__':
checkIntf( intfName ) checkIntf( intfName )
info( '*** Creating network\n' ) info( '*** Creating network\n' )
net = Mininet( topo=TreeTopo( depth=1, fanout=2 ) ) net = Mininet( topo=TreeTopo( depth=1, fanout=2 ), waitConnected=True )
switch = net.switches[ 0 ] switch = net.switches[ 0 ]
info( '*** Adding hardware interface', intfName, 'to switch', info( '*** Adding hardware interface', intfName, 'to switch',
+1 -1
View File
@@ -13,7 +13,7 @@ from mininet.link import TCLink
def intfOptions(): def intfOptions():
"run various traffic control commands on a single interface" "run various traffic control commands on a single interface"
net = Mininet( autoStaticArp=True ) net = Mininet( autoStaticArp=True, waitConnected=True )
net.addController( 'c0' ) net.addController( 'c0' )
h1 = net.addHost( 'h1' ) h1 = net.addHost( 'h1' )
h2 = net.addHost( 'h2' ) h2 = net.addHost( 'h2' )
+2 -2
View File
@@ -34,7 +34,7 @@ def limit( bw=10, cpu=.1 ):
'Skipping this test\n' ) 'Skipping this test\n' )
continue continue
host = custom( CPULimitedHost, sched=sched, cpu=cpu ) host = custom( CPULimitedHost, sched=sched, cpu=cpu )
net = Mininet( topo=myTopo, intf=intf, host=host ) net = Mininet( topo=myTopo, intf=intf, host=host, waitConnected=True )
net.start() net.start()
testLinkLimit( net, bw=bw ) testLinkLimit( net, bw=bw )
net.runCpuLimitTest( cpu=cpu ) net.runCpuLimitTest( cpu=cpu )
@@ -43,7 +43,7 @@ def limit( bw=10, cpu=.1 ):
def verySimpleLimit( bw=150 ): def verySimpleLimit( bw=150 ):
"Absurdly simple limiting test" "Absurdly simple limiting test"
intf = custom( TCIntf, bw=bw ) intf = custom( TCIntf, bw=bw )
net = Mininet( intf=intf ) net = Mininet( intf=intf, waitConnected=True )
h1, h2 = net.addHost( 'h1' ), net.addHost( 'h2' ) h1, h2 = net.addHost( 'h1' ), net.addHost( 'h2' )
net.addLink( h1, h2 ) net.addLink( h1, h2 )
net.start() net.start()
+5 -5
View File
@@ -83,10 +83,10 @@ def linearBandwidthTest( lengths ):
info( "*** testing", datapath, "datapath\n" ) info( "*** testing", datapath, "datapath\n" )
Switch = switches[ datapath ] Switch = switches[ datapath ]
results[ datapath ] = [] results[ datapath ] = []
link = partial( TCLink, delay='2ms', bw=10 ) link = partial( TCLink, delay='30ms', bw=100 )
net = Mininet( topo=topo, switch=Switch, net = Mininet( topo=topo, switch=Switch,
controller=Controller, waitConnected=True, controller=Controller, link=link,
link=link ) waitConnected=True )
net.start() net.start()
info( "*** testing basic connectivity\n" ) info( "*** testing basic connectivity\n" )
for n in lengths: for n in lengths:
@@ -99,7 +99,7 @@ def linearBandwidthTest( lengths ):
src.cmd( 'telnet', dst.IP(), '5001' ) src.cmd( 'telnet', dst.IP(), '5001' )
info( "testing", src.name, "<->", dst.name, '\n' ) info( "testing", src.name, "<->", dst.name, '\n' )
# serverbw = received; _clientbw = buffered # serverbw = received; _clientbw = buffered
serverbw, _clientbw = net.iperf( [ src, dst ], seconds=10 ) serverbw, _clientbw = net.iperf( [ src, dst ], seconds=5 )
info( serverbw, '\n' ) info( serverbw, '\n' )
flush() flush()
results[ datapath ] += [ ( n, serverbw ) ] results[ datapath ] += [ ( n, serverbw ) ]
@@ -117,6 +117,6 @@ def linearBandwidthTest( lengths ):
if __name__ == '__main__': if __name__ == '__main__':
lg.setLogLevel( 'info' ) lg.setLogLevel( 'info' )
sizes = [ 1, 10, 20, 40, 60, 80 ] sizes = [ 1, 2, 3, 4 ]
info( "*** Running linearBandwidthTest", sizes, '\n' ) info( "*** Running linearBandwidthTest", sizes, '\n' )
linearBandwidthTest( sizes ) linearBandwidthTest( sizes )
+2 -1
View File
@@ -79,7 +79,8 @@ class NetworkTopo( Topo ):
def run(): def run():
"Test linux router" "Test linux router"
topo = NetworkTopo() topo = NetworkTopo()
net = Mininet( topo=topo ) # controller is used by s1-s3 net = Mininet( topo=topo,
waitConnected=True ) # controller is used by s1-s3
net.start() net.start()
info( '*** Routing Table on Router:\n' ) info( '*** Routing Table on Router:\n' )
info( net[ 'r0' ].cmd( 'route' ) ) info( net[ 'r0' ].cmd( 'route' ) )
+2 -1
View File
@@ -107,7 +107,8 @@ def moveHost( host, oldSwitch, newSwitch, newPort=None ):
def mobilityTest(): def mobilityTest():
"A simple test of mobility" "A simple test of mobility"
info( '* Simple mobility test\n' ) info( '* Simple mobility test\n' )
net = Mininet( topo=LinearTopo( 3 ), switch=MobilitySwitch ) net = Mininet( topo=LinearTopo( 3 ), switch=MobilitySwitch,
waitConnected=True )
info( '* Starting network:\n' ) info( '* Starting network:\n' )
net.start() net.start()
printConnections( net.switches ) printConnections( net.switches )
+1 -1
View File
@@ -13,7 +13,7 @@ from mininet.topo import Topo
def runMultiLink(): def runMultiLink():
"Create and run multiple link network" "Create and run multiple link network"
topo = simpleMultiLinkTopo( n=2 ) topo = simpleMultiLinkTopo( n=2 )
net = Mininet( topo=topo ) net = Mininet( topo=topo, waitConnected=True )
net.start() net.start()
CLI( net ) CLI( net )
net.stop() net.stop()
+1 -1
View File
@@ -53,7 +53,7 @@ def monitorFiles( outfiles, seconds, timeoutms ):
def monitorTest( N=3, seconds=3 ): def monitorTest( N=3, seconds=3 ):
"Run pings and monitor multiple hosts" "Run pings and monitor multiple hosts"
topo = SingleSwitchTopo( N ) topo = SingleSwitchTopo( N )
net = Mininet( topo ) net = Mininet( topo, waitConnected=True )
net.start() net.start()
hosts = net.hosts hosts = net.hosts
info( "Starting test...\n" ) info( "Starting test...\n" )
+2 -1
View File
@@ -22,7 +22,8 @@ if __name__ == '__main__':
info( "*** Initializing Mininet and kernel modules\n" ) info( "*** Initializing Mininet and kernel modules\n" )
OVSKernelSwitch.setup() OVSKernelSwitch.setup()
info( "*** Creating network\n" ) info( "*** Creating network\n" )
network = Mininet( TreeTopo( depth=2, fanout=2 ), switch=OVSKernelSwitch ) network = Mininet( TreeTopo( depth=2, fanout=2), switch=OVSKernelSwitch,
waitConnected=True )
info( "*** Starting network\n" ) info( "*** Starting network\n" )
network.start() network.start()
info( "*** Running ping test\n" ) info( "*** Running ping test\n" )
+1 -1
View File
@@ -12,7 +12,7 @@ from mininet.topolib import TreeNet
if __name__ == '__main__': if __name__ == '__main__':
lg.setLogLevel( 'info') lg.setLogLevel( 'info')
net = TreeNet( depth=1, fanout=4 ) net = TreeNet( depth=1, fanout=4, waitConnected=True )
# Add NAT connectivity # Add NAT connectivity
net.addNAT().configDefault() net.addNAT().configDefault()
net.start() net.start()
+1 -1
View File
@@ -57,7 +57,7 @@ class InternetTopo(Topo):
def run(): def run():
"Create network and run the CLI" "Create network and run the CLI"
topo = InternetTopo() topo = InternetTopo()
net = Mininet(topo=topo) net = Mininet(topo=topo, waitConnected=True )
net.start() net.start()
CLI(net) CLI(net)
net.stop() net.stop()
+1 -1
View File
@@ -28,7 +28,7 @@ def testPortNumbering():
mid-level API) and check that implicit and mid-level API) and check that implicit and
explicit port numbering works as expected.""" explicit port numbering works as expected."""
net = Mininet( controller=Controller ) net = Mininet( controller=Controller, waitConnected=True )
info( '*** Adding controller\n' ) info( '*** Adding controller\n' )
net.addController( 'c0' ) net.addController( 'c0' )
+3 -7
View File
@@ -5,19 +5,15 @@ This example monitors a number of hosts using host.popen() and
pmonitor() pmonitor()
""" """
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.topo import SingleSwitchTopo from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel, info from mininet.log import setLogLevel, info
from mininet.util import custom, pmonitor from mininet.util import pmonitor
def monitorhosts( hosts=5, sched='cfs' ): def monitorhosts( hosts=5 ):
"Start a bunch of pings and monitor them using popen" "Start a bunch of pings and monitor them using popen"
mytopo = SingleSwitchTopo( hosts ) mytopo = SingleSwitchTopo( hosts )
cpu = .5 / hosts net = Mininet( topo=mytopo, waitConnected=True )
myhost = custom( CPULimitedHost, cpu=cpu, sched=sched )
net = Mininet( topo=mytopo, host=myhost )
net.start() net.start()
# Start a bunch of pings # Start a bunch of pings
popens = {} popens = {}
+1 -1
View File
@@ -13,7 +13,7 @@ from signal import SIGINT
def pmonitorTest( N=3, seconds=10 ): def pmonitorTest( N=3, seconds=10 ):
"Run pings and monitor multiple hosts using pmonitor" "Run pings and monitor multiple hosts using pmonitor"
topo = SingleSwitchTopo( N ) topo = SingleSwitchTopo( N )
net = Mininet( topo ) net = Mininet( topo, waitConnected=True )
net.start() net.start()
hosts = net.hosts hosts = net.hosts
info( "Starting test...\n" ) info( "Starting test...\n" )
+1 -1
View File
@@ -29,7 +29,7 @@ from mininet.util import waitListening
def TreeNet( depth=1, fanout=2, **kwargs ): def TreeNet( depth=1, fanout=2, **kwargs ):
"Convenience function for creating tree networks." "Convenience function for creating tree networks."
topo = TreeTopo( depth, fanout ) topo = TreeTopo( depth, fanout )
return Mininet( topo, **kwargs ) return Mininet( topo, waitConnected=True, **kwargs )
def connectToRootNS( network, switch, ip, routes ): def connectToRootNS( network, switch, ip, routes ):
"""Connect hosts to root namespace via switch. Starts network. """Connect hosts to root namespace via switch. Starts network.
+2
View File
@@ -14,6 +14,8 @@ class clusterSanityCheck( unittest.TestCase ):
def testClusterPingAll( self ): def testClusterPingAll( self ):
p = pexpect.spawn( 'python -m mininet.examples.clusterSanity' ) p = pexpect.spawn( 'python -m mininet.examples.clusterSanity' )
p.expect( self.prompt ) p.expect( self.prompt )
p.sendline( 'py net.waitConnected()' )
p.expect( self.prompt )
p.sendline( 'pingall' ) p.sendline( 'pingall' )
p.expect ( '(\d+)% dropped' ) p.expect ( '(\d+)% dropped' )
percent = int( p.match.group( 1 ) ) if p.match else -1 percent = int( p.match.group( 1 ) ) if p.match else -1
View File
Regular → Executable
View File
+2 -2
View File
@@ -16,7 +16,8 @@ class testSSHD( unittest.TestCase ):
"Log into ssh server, check banner, then exit" "Log into ssh server, check banner, then exit"
# Note: this test will fail if "Welcome" is not in the sshd banner # Note: this test will fail if "Welcome" is not in the sshd banner
# and '#'' or '$'' are not in the prompt # and '#'' or '$'' are not in the prompt
p = pexpect.spawn( 'ssh -i /tmp/ssh/test_rsa %s' % ip, timeout=10 ) ssh = 'ssh -o StrictHostKeyChecking=no -i /tmp/ssh/test_rsa ' + ip
p = pexpect.spawn( ssh, timeout=5 )
while True: while True:
index = p.expect( self.opts ) index = p.expect( self.opts )
if index == 0: if index == 0:
@@ -57,4 +58,3 @@ class testSSHD( unittest.TestCase ):
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
Regular → Executable
View File
+5 -2
View File
@@ -9,10 +9,13 @@ and running sysctl -p. Check util/sysctl_addon.
from mininet.cli import CLI from mininet.cli import CLI
from mininet.log import setLogLevel from mininet.log import setLogLevel
from mininet.node import OVSSwitch from mininet.node import OVSSwitch, Host
from mininet.topolib import TreeNet from mininet.topolib import TreeNet
from mininet.examples.treeping64 import HostV4, QuietController
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
network = TreeNet( depth=2, fanout=32, switch=OVSSwitch ) network = TreeNet( depth=2, fanout=32, host=HostV4,
switch=OVSSwitch, controller=QuietController,
waitConnected=True)
network.run( CLI, network ) network.run( CLI, network )
+18 -5
View File
@@ -4,21 +4,34 @@
from mininet.log import setLogLevel, info from mininet.log import setLogLevel, info
from mininet.node import UserSwitch, OVSKernelSwitch # , KernelSwitch from mininet.node import UserSwitch, OVSKernelSwitch, Host, Controller
from mininet.topolib import TreeNet from mininet.topolib import TreeNet
class HostV4( Host ):
"Try to IPv6 and its awful neighbor discovery"
def __init__( self, *args, **kwargs ):
super( HostV4, self ).__init__( *args, **kwargs )
cfgs = [ 'all.disable_ipv6=1', 'default.disable_ipv6=1',
'default.autoconf=0', 'lo.autoconf=0' ]
for cfg in cfgs:
self.cmd( 'sysctl -w net.ipv6.conf.' + cfg )
def treePing64(): def treePing64():
"Run ping test on 64-node tree networks." "Run ping test on 64-node tree networks."
results = {} results = {}
switches = { # 'reference kernel': KernelSwitch, switches = { 'reference user': UserSwitch,
'reference user': UserSwitch, 'Open vSwitch kernel': OVSKernelSwitch }
'Open vSwitch kernel': OVSKernelSwitch }
for name in switches: for name in switches:
info( "*** Testing", name, "datapath\n" ) info( "*** Testing", name, "datapath\n" )
switch = switches[ name ] switch = switches[ name ]
network = TreeNet( depth=2, fanout=8, switch=switch ) network = TreeNet( depth=2, fanout=8, switch=switch,
waitConnected=True )
result = network.run( network.pingAll ) result = network.run( network.pingAll )
results[ name ] = result results[ name ] = result
+2 -2
View File
@@ -65,7 +65,7 @@ def exampleAllHosts( vlan ):
# Start a basic network using our VLANHost # Start a basic network using our VLANHost
topo = SingleSwitchTopo( k=2 ) topo = SingleSwitchTopo( k=2 )
net = Mininet( host=host, topo=topo ) net = Mininet( host=host, topo=topo, waitConnected=True )
net.start() net.start()
CLI( net ) CLI( net )
net.stop() net.stop()
@@ -96,7 +96,7 @@ class VLANStarTopo( Topo ):
def exampleCustomTags(): def exampleCustomTags():
"""Simple example that exercises VLANStarTopo""" """Simple example that exercises VLANStarTopo"""
net = Mininet( topo=VLANStarTopo() ) net = Mininet( topo=VLANStarTopo(), waitConnected=True )
net.start() net.start()
CLI( net ) CLI( net )
net.stop() net.stop()
+4
View File
@@ -399,6 +399,10 @@ class CLI( Cmd ):
error( 'invalid command: ' error( 'invalid command: '
'switch <switch name> {start, stop}\n' ) 'switch <switch name> {start, stop}\n' )
def do_wait( self, line ):
"Wait until all switches have connected to a controller"
self.mn.waitConnected()
def default( self, line ): def default( self, line ):
"""Called on an input line when the command prefix is not recognized. """Called on an input line when the command prefix is not recognized.
Overridden to run shell commands when a node is the first Overridden to run shell commands when a node is the first
+1 -1
View File
@@ -173,7 +173,7 @@ class Mininet( object ):
if topo and build: if topo and build:
self.build() self.build()
def waitConnected( self, timeout=None, delay=.5 ): def waitConnected( self, timeout=5, delay=.5 ):
"""wait for each switch to connect to a controller, """wait for each switch to connect to a controller,
up to 5 seconds up to 5 seconds
timeout: time to wait, or None to wait indefinitely timeout: time to wait, or None to wait indefinitely
+4 -2
View File
@@ -1382,10 +1382,12 @@ class Controller( Node ):
OpenFlow controller.""" OpenFlow controller."""
def __init__( self, name, inNamespace=False, command='controller', def __init__( self, name, inNamespace=False, command='controller',
cargs='-v ptcp:%d', cdir=None, ip="127.0.0.1", cargs='ptcp:%d', cdir=None, ip="127.0.0.1",
port=6653, protocol='tcp', **params ): port=6653, protocol='tcp', verbose=False, **params ):
self.command = command self.command = command
self.cargs = cargs self.cargs = cargs
if verbose:
cargs = '-v ' + cargs
self.cdir = cdir self.cdir = cdir
# Accept 'ip:port' syntax as shorthand # Accept 'ip:port' syntax as shorthand
if ':' in ip: if ':' in ip:
+24 -14
View File
@@ -84,13 +84,35 @@ class NAT( Node ):
self.flush = flush self.flush = flush
self.forwardState = self.cmd( 'sysctl -n net.ipv4.ip_forward' ).strip() self.forwardState = self.cmd( 'sysctl -n net.ipv4.ip_forward' ).strip()
def setManualConfig( self, intf ):
"""Prevent network-manager/networkd from messing with our interface
by specifying manual configuration in /etc/network/interfaces"""
cfile = '/etc/network/interfaces'
line = '\niface %s inet manual\n' % intf
try:
with open( cfile ) as f:
config = f.read()
except IOError:
config = ''
if ( line ) not in config:
info( '*** Adding "' + line.strip() + '" to ' + cfile + '\n' )
with open( cfile, 'a' ) as f:
f.write( line )
# Probably need to restart network manager to be safe -
# hopefully this won't disconnect you
self.cmd( 'service network-manager restart || netplan apply' )
def config( self, **params ): def config( self, **params ):
"""Configure the NAT and iptables""" """Configure the NAT and iptables"""
super( NAT, self).config( **params )
if not self.localIntf: if not self.localIntf:
self.localIntf = self.defaultIntf() self.localIntf = self.defaultIntf()
self.setManualConfig( self.localIntf )
# Now we can configure manually without interference
super( NAT, self).config( **params )
if self.flush: if self.flush:
self.cmd( 'sysctl net.ipv4.ip_forward=0' ) self.cmd( 'sysctl net.ipv4.ip_forward=0' )
self.cmd( 'iptables -F' ) self.cmd( 'iptables -F' )
@@ -114,19 +136,7 @@ class NAT( Node ):
# Instruct the kernel to perform forwarding # Instruct the kernel to perform forwarding
self.cmd( 'sysctl net.ipv4.ip_forward=1' ) self.cmd( 'sysctl net.ipv4.ip_forward=1' )
# Prevent network-manager from messing with our interface
# by specifying manual configuration in /etc/network/interfaces
intf = self.localIntf
cfile = '/etc/network/interfaces'
line = '\niface %s inet manual\n' % intf
config = open( cfile ).read()
if ( line ) not in config:
info( '*** Adding "' + line.strip() + '" to ' + cfile + '\n' )
with open( cfile, 'a' ) as f:
f.write( line )
# Probably need to restart network-manager to be safe -
# hopefully this won't disconnect you
self.cmd( 'service network-manager restart' )
def terminate( self ): def terminate( self ):
"Stop NAT/forwarding between Mininet and external network" "Stop NAT/forwarding between Mininet and external network"
+11 -8
View File
@@ -43,17 +43,18 @@ class testWalkthrough( unittest.TestCase ):
tshark = pexpect.spawn( 'tshark -i lo -R of' ) tshark = pexpect.spawn( 'tshark -i lo -R of' )
else: else:
tshark = pexpect.spawn( 'tshark -i lo -Y openflow_v1' ) tshark = pexpect.spawn( 'tshark -i lo -Y openflow_v1' )
tshark.expect( [ 'Capturing on lo', "Capturing on 'Loopback'" ] ) tshark.expect( [ 'Capturing on lo', "Capturing on 'Loopback" ] )
mn = pexpect.spawn( 'mn --test pingall' ) mn = pexpect.spawn( 'mn --test pingall' )
mn.expect( '0% dropped' ) mn.expect( '0% dropped' )
tshark.expect( [ '74 Hello', '74 of_hello', '74 Type: OFPT_HELLO' ] ) tshark.expect( [ '74 Hello', '74 of_hello', '74 Type: OFPT_HELLO' ] )
tshark.sendintr() tshark.sendintr()
mn.expect( pexpect.EOF ) mn.expect( pexpect.EOF )
tshark.expect( 'aptured' ) # 'xx packets captured'
tshark.expect( pexpect.EOF ) tshark.expect( pexpect.EOF )
def testBasic( self ): def testBasic( self ):
"Test basic CLI commands (help, nodes, net, dump)" "Test basic CLI commands (help, nodes, net, dump)"
p = pexpect.spawn( 'mn' ) p = pexpect.spawn( 'mn -w' )
p.expect( self.prompt ) p.expect( self.prompt )
# help command # help command
p.sendline( 'help' ) p.sendline( 'help' )
@@ -92,7 +93,7 @@ class testWalkthrough( unittest.TestCase ):
def testHostCommands( self ): def testHostCommands( self ):
"Test ifconfig and ps on h1 and s1" "Test ifconfig and ps on h1 and s1"
p = pexpect.spawn( 'mn' ) p = pexpect.spawn( 'mn -w' )
p.expect( self.prompt ) p.expect( self.prompt )
# Third pattern is a local interface beginning with 'eth' or 'en' # Third pattern is a local interface beginning with 'eth' or 'en'
interfaces = [ r'h1-eth0[:\s]', r's1-eth1[:\s]', interfaces = [ r'h1-eth0[:\s]', r's1-eth1[:\s]',
@@ -144,7 +145,7 @@ class testWalkthrough( unittest.TestCase ):
def testConnectivity( self ): def testConnectivity( self ):
"Test ping and pingall" "Test ping and pingall"
p = pexpect.spawn( 'mn' ) p = pexpect.spawn( 'mn -w' )
p.expect( self.prompt ) p.expect( self.prompt )
p.sendline( 'h1 ping -c 1 h2' ) p.sendline( 'h1 ping -c 1 h2' )
p.expect( '1 packets transmitted, 1 received' ) p.expect( '1 packets transmitted, 1 received' )
@@ -161,7 +162,7 @@ class testWalkthrough( unittest.TestCase ):
httpserver = 'SimpleHTTPServer' httpserver = 'SimpleHTTPServer'
else: else:
httpserver = 'http.server' httpserver = 'http.server'
p = pexpect.spawn( 'mn' ) p = pexpect.spawn( 'mn -w' )
p.expect( self.prompt ) p.expect( self.prompt )
p.sendline( 'h1 python -m %s 80 &' % httpserver ) p.sendline( 'h1 python -m %s 80 &' % httpserver )
# The walkthrough doesn't specify a delay here, and # The walkthrough doesn't specify a delay here, and
@@ -213,7 +214,9 @@ class testWalkthrough( unittest.TestCase ):
def testLinkChange( self ): def testLinkChange( self ):
"Test TCLink bw and delay" "Test TCLink bw and delay"
p = pexpect.spawn( 'mn --link tc,bw=10,delay=10ms' ) p = pexpect.spawn( 'mn -w --link tc,bw=10,delay=10ms' )
p.expect( self.prompt )
p.sendline( 'h1 route && ping -c1 h2' )
# test bw # test bw
p.expect( self.prompt ) p.expect( self.prompt )
p.sendline( 'iperf' ) p.sendline( 'iperf' )
@@ -319,7 +322,7 @@ class testWalkthrough( unittest.TestCase ):
# PART 3 # PART 3
def testPythonInterpreter( self ): def testPythonInterpreter( self ):
"Test py and px by checking IP for h1 and adding h3" "Test py and px by checking IP for h1 and adding h3"
p = pexpect.spawn( 'mn' ) p = pexpect.spawn( 'mn -w' )
p.expect( self.prompt ) p.expect( self.prompt )
# test host IP # test host IP
p.sendline( 'py h1.IP()' ) p.sendline( 'py h1.IP()' )
@@ -341,7 +344,7 @@ class testWalkthrough( unittest.TestCase ):
def testLink( self ): def testLink( self ):
"Test link CLI command using ping" "Test link CLI command using ping"
p = pexpect.spawn( 'mn' ) p = pexpect.spawn( 'mn -w' )
p.expect( self.prompt ) p.expect( self.prompt )
p.sendline( 'link s1 h1 down' ) p.sendline( 'link s1 h1 down' )
p.expect( self.prompt ) p.expect( self.prompt )