diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 2e59bee..5ada322 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -9,7 +9,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-18.04, ubuntu-16.04] + os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04] python-version: [3.x, 2.x] steps: - name: Check out Mininet source @@ -47,12 +47,10 @@ jobs: export sudo="sudo env PATH=$PATH" export PYTHON=`which python` rm -f pexpect.out - $sudo $PYTHON mininet/test/runner.py -v -quick || \ - (cat pexpect.out && exit 1) + $sudo $PYTHON mininet/test/runner.py -v -quick - name: Run examples tests (quick) run: | export sudo="sudo env PATH=$PATH" export PYTHON=`which python` rm -f pexpect.out - $sudo $PYTHON examples/test/runner.py -v -quick || \ - (cat pexpect.out && exit 1) + $sudo $PYTHON examples/test/runner.py -v -quick diff --git a/README.md b/README.md index 2b399b6..28b1652 100644 --- a/README.md +++ b/README.md @@ -132,4 +132,4 @@ Bob Lantz Mininet Core Team [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 diff --git a/bin/mn b/bin/mn index ae55e4f..d7f1b2b 100755 --- a/bin/mn +++ b/bin/mn @@ -284,6 +284,8 @@ class MininetRunner( object ): " Mininet's IP subnet, see the --ipbase option." ) opts.add_option( '--version', action='callback', callback=version, 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, metavar='server1,server2...', help=( 'run on multiple servers (experimental!)' ) ) @@ -385,6 +387,7 @@ class MininetRunner( object ): ipBase=opts.ipbase, inNamespace=opts.innamespace, xterms=opts.xterms, autoSetMacs=opts.mac, autoStaticArp=opts.arp, autoPinCpus=opts.pin, + waitConnected=opts.wait, listenPort=opts.listenport ) if opts.ensure_value( 'nat', False ): diff --git a/examples/bind.py b/examples/bind.py index 6a60e63..e2a74d7 100755 --- a/examples/bind.py +++ b/examples/bind.py @@ -53,7 +53,7 @@ def testHostWithPrivateDirs(): '/var/mn' ] host = partial( Host, privateDirs=privateDirs ) - net = Mininet( topo=topo, host=host ) + net = Mininet( topo=topo, host=host, waitConnected=True ) net.start() directories = [ directory[ 0 ] if isinstance( directory, tuple ) else directory for directory in privateDirs ] diff --git a/examples/cluster.py b/examples/cluster.py index aa718da..276b71a 100755 --- a/examples/cluster.py +++ b/examples/cluster.py @@ -875,7 +875,7 @@ class MininetCluster( Mininet ): def testNsTunnels( remote='ubuntu2', link=RemoteGRELink ): "Test tunnels between nodes in namespaces" - net = Mininet( host=RemoteHost, link=link ) + net = Mininet( host=RemoteHost, link=link, waitConnected=True ) h1 = net.addHost( 'h1') h2 = net.addHost( 'h2', server=remote ) net.addLink( h1, h2 ) @@ -891,7 +891,8 @@ def testNsTunnels( remote='ubuntu2', link=RemoteGRELink ): def testRemoteNet( remote='ubuntu2', link=RemoteGRELink ): "Test remote Node classes" 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' ) # Make sure controller knows its non-loopback address Intf( 'eth0', node=c0 ).updateIP() diff --git a/examples/clusterperf.py b/examples/clusterperf.py index 46e483e..2c9486f 100755 --- a/examples/clusterperf.py +++ b/examples/clusterperf.py @@ -8,7 +8,7 @@ from mininet.log import setLogLevel def perf(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') h2 = net.addHost( 'h2', server='ubuntu2' ) net.addLink( h1, h2 ) diff --git a/examples/controllers.py b/examples/controllers.py index 7ed5242..952ced4 100755 --- a/examples/controllers.py +++ b/examples/controllers.py @@ -27,7 +27,7 @@ class MultiSwitch( OVSSwitch ): return OVSSwitch.start( self, [ cmap[ self.name ] ] ) 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 ]: net.addController(c) net.build() diff --git a/examples/controllers2.py b/examples/controllers2.py index fc06269..3169790 100755 --- a/examples/controllers2.py +++ b/examples/controllers2.py @@ -20,7 +20,8 @@ from mininet.log import setLogLevel, info def multiControllerNet(): "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" ) c1 = net.addController( 'c1', port=6633 ) diff --git a/examples/controlnet.py b/examples/controlnet.py index 53fce35..257199b 100755 --- a/examples/controlnet.py +++ b/examples/controlnet.py @@ -123,7 +123,8 @@ def run(): info( '* Creating Control Network\n' ) 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') cnet.addController( 'cc0', controller=Controller ) info( '* Starting Control Network\n') @@ -133,7 +134,8 @@ def run(): 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 ) + net = Mininet( topo=topo, switch=sw, controller=None, + waitConnected=True ) info( '* Adding Controllers to Data Network\n' ) for host in cnet.hosts: if isinstance(host, Controller): diff --git a/examples/cpu.py b/examples/cpu.py index accb0ea..3878cb9 100755 --- a/examples/cpu.py +++ b/examples/cpu.py @@ -52,7 +52,7 @@ def bwtest( cpuLimits, period_us=100000, seconds=10 ): period_us=period_us, cpu=.5*cpu ) try: - net = Mininet( topo=topo, host=host ) + net = Mininet( topo=topo, host=host, waitConnected=True ) # pylint: disable=bare-except except: info( '*** Skipping scheduler %s and cleaning up\n' % sched ) diff --git a/examples/emptynet.py b/examples/emptynet.py index afcf6a8..fa7da67 100755 --- a/examples/emptynet.py +++ b/examples/emptynet.py @@ -14,7 +14,7 @@ def emptyNet(): "Create an empty network and add nodes to it." - net = Mininet( controller=Controller ) + net = Mininet( controller=Controller, waitConnected=True ) info( '*** Adding controller\n' ) net.addController( 'c0' ) diff --git a/examples/hwintf.py b/examples/hwintf.py index bbcff34..af90c9b 100755 --- a/examples/hwintf.py +++ b/examples/hwintf.py @@ -38,7 +38,7 @@ if __name__ == '__main__': checkIntf( intfName ) 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 ] info( '*** Adding hardware interface', intfName, 'to switch', diff --git a/examples/intfoptions.py b/examples/intfoptions.py index 41bd84c..183e73b 100755 --- a/examples/intfoptions.py +++ b/examples/intfoptions.py @@ -13,7 +13,7 @@ from mininet.link import TCLink def intfOptions(): "run various traffic control commands on a single interface" - net = Mininet( autoStaticArp=True ) + net = Mininet( autoStaticArp=True, waitConnected=True ) net.addController( 'c0' ) h1 = net.addHost( 'h1' ) h2 = net.addHost( 'h2' ) diff --git a/examples/limit.py b/examples/limit.py index 4db88ac..903fd73 100755 --- a/examples/limit.py +++ b/examples/limit.py @@ -34,7 +34,7 @@ def limit( bw=10, cpu=.1 ): 'Skipping this test\n' ) continue 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() testLinkLimit( net, bw=bw ) net.runCpuLimitTest( cpu=cpu ) @@ -43,7 +43,7 @@ def limit( bw=10, cpu=.1 ): def verySimpleLimit( bw=150 ): "Absurdly simple limiting test" intf = custom( TCIntf, bw=bw ) - net = Mininet( intf=intf ) + net = Mininet( intf=intf, waitConnected=True ) h1, h2 = net.addHost( 'h1' ), net.addHost( 'h2' ) net.addLink( h1, h2 ) net.start() diff --git a/examples/linearbandwidth.py b/examples/linearbandwidth.py index 3bb608c..1c06ece 100755 --- a/examples/linearbandwidth.py +++ b/examples/linearbandwidth.py @@ -83,10 +83,10 @@ def linearBandwidthTest( lengths ): info( "*** testing", datapath, "datapath\n" ) Switch = switches[ datapath ] results[ datapath ] = [] - link = partial( TCLink, delay='2ms', bw=10 ) + link = partial( TCLink, delay='30ms', bw=100 ) net = Mininet( topo=topo, switch=Switch, - controller=Controller, waitConnected=True, - link=link ) + controller=Controller, link=link, + waitConnected=True ) net.start() info( "*** testing basic connectivity\n" ) for n in lengths: @@ -99,7 +99,7 @@ def linearBandwidthTest( lengths ): src.cmd( 'telnet', dst.IP(), '5001' ) info( "testing", src.name, "<->", dst.name, '\n' ) # serverbw = received; _clientbw = buffered - serverbw, _clientbw = net.iperf( [ src, dst ], seconds=10 ) + serverbw, _clientbw = net.iperf( [ src, dst ], seconds=5 ) info( serverbw, '\n' ) flush() results[ datapath ] += [ ( n, serverbw ) ] @@ -117,6 +117,6 @@ def linearBandwidthTest( lengths ): if __name__ == '__main__': lg.setLogLevel( 'info' ) - sizes = [ 1, 10, 20, 40, 60, 80 ] + sizes = [ 1, 2, 3, 4 ] info( "*** Running linearBandwidthTest", sizes, '\n' ) linearBandwidthTest( sizes ) diff --git a/examples/linuxrouter.py b/examples/linuxrouter.py index a7e312b..37699f3 100755 --- a/examples/linuxrouter.py +++ b/examples/linuxrouter.py @@ -79,7 +79,8 @@ class NetworkTopo( Topo ): def run(): "Test linux router" 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() info( '*** Routing Table on Router:\n' ) info( net[ 'r0' ].cmd( 'route' ) ) diff --git a/examples/mobility.py b/examples/mobility.py index ba09089..d7347da 100755 --- a/examples/mobility.py +++ b/examples/mobility.py @@ -107,7 +107,8 @@ def moveHost( host, oldSwitch, newSwitch, newPort=None ): def mobilityTest(): "A simple test of mobility" 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' ) net.start() printConnections( net.switches ) diff --git a/examples/multilink.py b/examples/multilink.py index 6cde4dc..b6b4051 100755 --- a/examples/multilink.py +++ b/examples/multilink.py @@ -13,7 +13,7 @@ from mininet.topo import Topo def runMultiLink(): "Create and run multiple link network" topo = simpleMultiLinkTopo( n=2 ) - net = Mininet( topo=topo ) + net = Mininet( topo=topo, waitConnected=True ) net.start() CLI( net ) net.stop() diff --git a/examples/multipoll.py b/examples/multipoll.py index bb1c9d3..e9998df 100755 --- a/examples/multipoll.py +++ b/examples/multipoll.py @@ -53,7 +53,7 @@ def monitorFiles( outfiles, seconds, timeoutms ): def monitorTest( N=3, seconds=3 ): "Run pings and monitor multiple hosts" topo = SingleSwitchTopo( N ) - net = Mininet( topo ) + net = Mininet( topo, waitConnected=True ) net.start() hosts = net.hosts info( "Starting test...\n" ) diff --git a/examples/multitest.py b/examples/multitest.py index b50acb2..2d68cd4 100755 --- a/examples/multitest.py +++ b/examples/multitest.py @@ -22,7 +22,8 @@ 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, + waitConnected=True ) info( "*** Starting network\n" ) network.start() info( "*** Running ping test\n" ) diff --git a/examples/nat.py b/examples/nat.py index e6d55f7..bb7e8c4 100755 --- a/examples/nat.py +++ b/examples/nat.py @@ -12,7 +12,7 @@ from mininet.topolib import TreeNet if __name__ == '__main__': lg.setLogLevel( 'info') - net = TreeNet( depth=1, fanout=4 ) + net = TreeNet( depth=1, fanout=4, waitConnected=True ) # Add NAT connectivity net.addNAT().configDefault() net.start() diff --git a/examples/natnet.py b/examples/natnet.py index 59ba6c7..bfbc6df 100755 --- a/examples/natnet.py +++ b/examples/natnet.py @@ -57,7 +57,7 @@ class InternetTopo(Topo): def run(): "Create network and run the CLI" topo = InternetTopo() - net = Mininet(topo=topo) + net = Mininet(topo=topo, waitConnected=True ) net.start() CLI(net) net.stop() diff --git a/examples/numberedports.py b/examples/numberedports.py index 3bd18d6..1fed0da 100755 --- a/examples/numberedports.py +++ b/examples/numberedports.py @@ -28,7 +28,7 @@ def testPortNumbering(): mid-level API) and check that implicit and explicit port numbering works as expected.""" - net = Mininet( controller=Controller ) + net = Mininet( controller=Controller, waitConnected=True ) info( '*** Adding controller\n' ) net.addController( 'c0' ) diff --git a/examples/popen.py b/examples/popen.py index b43fb1c..4de4d61 100755 --- a/examples/popen.py +++ b/examples/popen.py @@ -5,19 +5,15 @@ This example monitors a number of hosts using host.popen() and pmonitor() """ - from mininet.net import Mininet -from mininet.node import CPULimitedHost from mininet.topo import SingleSwitchTopo 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" mytopo = SingleSwitchTopo( hosts ) - cpu = .5 / hosts - myhost = custom( CPULimitedHost, cpu=cpu, sched=sched ) - net = Mininet( topo=mytopo, host=myhost ) + net = Mininet( topo=mytopo, waitConnected=True ) net.start() # Start a bunch of pings popens = {} diff --git a/examples/popenpoll.py b/examples/popenpoll.py index c153dcb..75534c9 100755 --- a/examples/popenpoll.py +++ b/examples/popenpoll.py @@ -13,7 +13,7 @@ from signal import SIGINT def pmonitorTest( N=3, seconds=10 ): "Run pings and monitor multiple hosts using pmonitor" topo = SingleSwitchTopo( N ) - net = Mininet( topo ) + net = Mininet( topo, waitConnected=True ) net.start() hosts = net.hosts info( "Starting test...\n" ) diff --git a/examples/sshd.py b/examples/sshd.py index 7e0f517..a5641ac 100755 --- a/examples/sshd.py +++ b/examples/sshd.py @@ -29,7 +29,7 @@ from mininet.util import waitListening def TreeNet( depth=1, fanout=2, **kwargs ): "Convenience function for creating tree networks." topo = TreeTopo( depth, fanout ) - return Mininet( topo, **kwargs ) + return Mininet( topo, waitConnected=True, **kwargs ) def connectToRootNS( network, switch, ip, routes ): """Connect hosts to root namespace via switch. Starts network. diff --git a/examples/test/test_clusterSanity.py b/examples/test/test_clusterSanity.py index 13e51e2..e91c885 100755 --- a/examples/test/test_clusterSanity.py +++ b/examples/test/test_clusterSanity.py @@ -14,6 +14,8 @@ class clusterSanityCheck( unittest.TestCase ): def testClusterPingAll( self ): p = pexpect.spawn( 'python -m mininet.examples.clusterSanity' ) p.expect( self.prompt ) + p.sendline( 'py net.waitConnected()' ) + p.expect( self.prompt ) p.sendline( 'pingall' ) p.expect ( '(\d+)% dropped' ) percent = int( p.match.group( 1 ) ) if p.match else -1 diff --git a/examples/test/test_linuxrouter.py b/examples/test/test_linuxrouter.py old mode 100644 new mode 100755 diff --git a/examples/test/test_natnet.py b/examples/test/test_natnet.py old mode 100644 new mode 100755 diff --git a/examples/test/test_sshd.py b/examples/test/test_sshd.py index 193b1ea..e012a29 100755 --- a/examples/test/test_sshd.py +++ b/examples/test/test_sshd.py @@ -16,7 +16,8 @@ class testSSHD( unittest.TestCase ): "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 ) + ssh = 'ssh -o StrictHostKeyChecking=no -i /tmp/ssh/test_rsa ' + ip + p = pexpect.spawn( ssh, timeout=5 ) while True: index = p.expect( self.opts ) if index == 0: @@ -57,4 +58,3 @@ class testSSHD( unittest.TestCase ): if __name__ == '__main__': unittest.main() - diff --git a/examples/test/test_vlanhost.py b/examples/test/test_vlanhost.py old mode 100644 new mode 100755 diff --git a/examples/tree1024.py b/examples/tree1024.py index d5c25c2..cfb23cf 100755 --- a/examples/tree1024.py +++ b/examples/tree1024.py @@ -9,10 +9,13 @@ and running sysctl -p. Check util/sysctl_addon. from mininet.cli import CLI from mininet.log import setLogLevel -from mininet.node import OVSSwitch +from mininet.node import OVSSwitch, Host from mininet.topolib import TreeNet +from mininet.examples.treeping64 import HostV4, QuietController if __name__ == '__main__': 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 ) diff --git a/examples/treeping64.py b/examples/treeping64.py index bd54650..35beec8 100755 --- a/examples/treeping64.py +++ b/examples/treeping64.py @@ -4,21 +4,34 @@ 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 + +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(): "Run ping test on 64-node tree networks." results = {} - switches = { # 'reference kernel': KernelSwitch, - 'reference user': UserSwitch, - 'Open vSwitch kernel': OVSKernelSwitch } + switches = { 'reference user': UserSwitch, + 'Open vSwitch kernel': OVSKernelSwitch } for name in switches: info( "*** Testing", name, "datapath\n" ) 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 ) results[ name ] = result diff --git a/examples/vlanhost.py b/examples/vlanhost.py index 3e4dd51..ec68b93 100755 --- a/examples/vlanhost.py +++ b/examples/vlanhost.py @@ -65,7 +65,7 @@ def exampleAllHosts( vlan ): # Start a basic network using our VLANHost topo = SingleSwitchTopo( k=2 ) - net = Mininet( host=host, topo=topo ) + net = Mininet( host=host, topo=topo, waitConnected=True ) net.start() CLI( net ) net.stop() @@ -96,7 +96,7 @@ class VLANStarTopo( Topo ): def exampleCustomTags(): """Simple example that exercises VLANStarTopo""" - net = Mininet( topo=VLANStarTopo() ) + net = Mininet( topo=VLANStarTopo(), waitConnected=True ) net.start() CLI( net ) net.stop() diff --git a/mininet/cli.py b/mininet/cli.py index 0802a95..be20ca8 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -399,6 +399,10 @@ class CLI( Cmd ): error( 'invalid command: ' 'switch {start, stop}\n' ) + def do_wait( self, line ): + "Wait until all switches have connected to a controller" + self.mn.waitConnected() + def default( self, line ): """Called on an input line when the command prefix is not recognized. Overridden to run shell commands when a node is the first diff --git a/mininet/net.py b/mininet/net.py index b23d841..9b94378 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -173,7 +173,7 @@ class Mininet( object ): if topo and 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, up to 5 seconds timeout: time to wait, or None to wait indefinitely diff --git a/mininet/node.py b/mininet/node.py index 8617dee..c3e12a7 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -1382,10 +1382,12 @@ class Controller( Node ): OpenFlow controller.""" def __init__( self, name, inNamespace=False, command='controller', - cargs='-v ptcp:%d', cdir=None, ip="127.0.0.1", - port=6653, protocol='tcp', **params ): + cargs='ptcp:%d', cdir=None, ip="127.0.0.1", + port=6653, protocol='tcp', verbose=False, **params ): self.command = command self.cargs = cargs + if verbose: + cargs = '-v ' + cargs self.cdir = cdir # Accept 'ip:port' syntax as shorthand if ':' in ip: diff --git a/mininet/nodelib.py b/mininet/nodelib.py index 7d87dbd..02fbf00 100644 --- a/mininet/nodelib.py +++ b/mininet/nodelib.py @@ -84,13 +84,35 @@ class NAT( Node ): self.flush = flush 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 ): """Configure the NAT and iptables""" - super( NAT, self).config( **params ) if not self.localIntf: self.localIntf = self.defaultIntf() + self.setManualConfig( self.localIntf ) + + # Now we can configure manually without interference + super( NAT, self).config( **params ) + if self.flush: self.cmd( 'sysctl net.ipv4.ip_forward=0' ) self.cmd( 'iptables -F' ) @@ -114,19 +136,7 @@ class NAT( Node ): # Instruct the kernel to perform forwarding 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 ): "Stop NAT/forwarding between Mininet and external network" diff --git a/mininet/test/test_walkthrough.py b/mininet/test/test_walkthrough.py index c322c13..795f956 100755 --- a/mininet/test/test_walkthrough.py +++ b/mininet/test/test_walkthrough.py @@ -43,17 +43,18 @@ class testWalkthrough( unittest.TestCase ): tshark = pexpect.spawn( 'tshark -i lo -R of' ) else: 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.expect( '0% dropped' ) tshark.expect( [ '74 Hello', '74 of_hello', '74 Type: OFPT_HELLO' ] ) tshark.sendintr() mn.expect( pexpect.EOF ) + tshark.expect( 'aptured' ) # 'xx packets captured' tshark.expect( pexpect.EOF ) def testBasic( self ): "Test basic CLI commands (help, nodes, net, dump)" - p = pexpect.spawn( 'mn' ) + p = pexpect.spawn( 'mn -w' ) p.expect( self.prompt ) # help command p.sendline( 'help' ) @@ -92,7 +93,7 @@ class testWalkthrough( unittest.TestCase ): def testHostCommands( self ): "Test ifconfig and ps on h1 and s1" - p = pexpect.spawn( 'mn' ) + p = pexpect.spawn( 'mn -w' ) p.expect( self.prompt ) # Third pattern is a local interface beginning with 'eth' or 'en' interfaces = [ r'h1-eth0[:\s]', r's1-eth1[:\s]', @@ -144,7 +145,7 @@ class testWalkthrough( unittest.TestCase ): def testConnectivity( self ): "Test ping and pingall" - p = pexpect.spawn( 'mn' ) + p = pexpect.spawn( 'mn -w' ) p.expect( self.prompt ) p.sendline( 'h1 ping -c 1 h2' ) p.expect( '1 packets transmitted, 1 received' ) @@ -161,7 +162,7 @@ class testWalkthrough( unittest.TestCase ): httpserver = 'SimpleHTTPServer' else: httpserver = 'http.server' - p = pexpect.spawn( 'mn' ) + p = pexpect.spawn( 'mn -w' ) p.expect( self.prompt ) p.sendline( 'h1 python -m %s 80 &' % httpserver ) # The walkthrough doesn't specify a delay here, and @@ -213,7 +214,9 @@ class testWalkthrough( unittest.TestCase ): def testLinkChange( self ): "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 p.expect( self.prompt ) p.sendline( 'iperf' ) @@ -319,7 +322,7 @@ class testWalkthrough( unittest.TestCase ): # PART 3 def testPythonInterpreter( self ): "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 ) # test host IP p.sendline( 'py h1.IP()' ) @@ -341,7 +344,7 @@ class testWalkthrough( unittest.TestCase ): def testLink( self ): "Test link CLI command using ping" - p = pexpect.spawn( 'mn' ) + p = pexpect.spawn( 'mn -w' ) p.expect( self.prompt ) p.sendline( 'link s1 h1 down' ) p.expect( self.prompt )