Pass code check with pylint=2.4.4 (#1012)
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
name: code-check
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
code-check:
|
||||||
|
name: Mininet Code Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Set up Python 3.x
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
- name: Check out Mininet source
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Install Mininet code check dependencies
|
||||||
|
run: |
|
||||||
|
PYTHON=`which python` util/install.sh -n
|
||||||
|
python -m pip install pylint==2.4.4
|
||||||
|
- name: Run code check
|
||||||
|
run: make codecheck
|
||||||
@@ -24,9 +24,6 @@ jobs:
|
|||||||
# This seems too slow unfortunately:
|
# This seems too slow unfortunately:
|
||||||
# sudo apt-get upgrade -y -qq
|
# sudo apt-get upgrade -y -qq
|
||||||
PYTHON=`which python` util/install.sh -nv
|
PYTHON=`which python` util/install.sh -nv
|
||||||
- name: Run code check (skipping for now)
|
|
||||||
run: |
|
|
||||||
bash -c "if [ `lsb_release -rs` == '14.04' ]; then make codecheck; fi"
|
|
||||||
- name: Sanity test
|
- name: Sanity test
|
||||||
run: |
|
run: |
|
||||||
export sudo="sudo env PATH=$PATH"
|
export sudo="sudo env PATH=$PATH"
|
||||||
|
|||||||
@@ -41,10 +41,16 @@ load-plugins=
|
|||||||
# can either give multiple identifier separated by comma (,) or put this option
|
# can either give multiple identifier separated by comma (,) or put this option
|
||||||
# multiple time (only on the command line, not in the configuration file where
|
# multiple time (only on the command line, not in the configuration file where
|
||||||
# it should appear only once).
|
# it should appear only once).
|
||||||
|
#
|
||||||
|
# Note: we may want to re-enable some of these at some point, but many of them
|
||||||
|
# are just style issues rather than errors.
|
||||||
|
#
|
||||||
disable=pointless-except, invalid-name, super-init-not-called, fixme, star-args,
|
disable=pointless-except, invalid-name, super-init-not-called, fixme, star-args,
|
||||||
too-many-instance-attributes, too-few-public-methods, too-many-arguments,
|
too-many-instance-attributes, too-few-public-methods,
|
||||||
too-many-locals, too-many-public-methods, duplicate-code, bad-whitespace,
|
too-many-locals, too-many-public-methods, duplicate-code, bad-whitespace,
|
||||||
locally-disabled, locally-enabled
|
locally-disabled, locally-enabled, bad-continuation,
|
||||||
|
useless-object-inheritance, unnecessary-pass, no-else-return,
|
||||||
|
no-else-raise, no-else-continue, super-with-arguments
|
||||||
|
|
||||||
# bad-continuation, wrong-import-order
|
# bad-continuation, wrong-import-order
|
||||||
|
|
||||||
|
|||||||
+4
-7
@@ -3,20 +3,17 @@ sudo: required
|
|||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- dist: trusty
|
- dist: focal
|
||||||
python: 2.7
|
|
||||||
env: dist="14.04 LTS trusty"
|
|
||||||
- dist: trusty
|
|
||||||
python: 3.6
|
python: 3.6
|
||||||
env: dist="14.04 LTS trusty"
|
env: dist="24.04 LTS focal"
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
- sudo apt-get install -qq vlan
|
- sudo apt-get install -qq vlan pyflakes
|
||||||
- PYTHON=`which python` util/install.sh -n
|
- PYTHON=`which python` util/install.sh -n
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- bash -c "if [ `lsb_release -rs` == '14.04' ]; then make codecheck; fi"
|
- make codecheck
|
||||||
- pip install pexpect || pip3 install pexpect
|
- pip install pexpect || pip3 install pexpect
|
||||||
- util/install.sh -nfvw
|
- util/install.sh -nfvw
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ BIN = $(MN)
|
|||||||
PYSRC = $(MININET) $(TEST) $(EXAMPLES) $(BIN)
|
PYSRC = $(MININET) $(TEST) $(EXAMPLES) $(BIN)
|
||||||
MNEXEC = mnexec
|
MNEXEC = mnexec
|
||||||
MANPAGES = mn.1 mnexec.1
|
MANPAGES = mn.1 mnexec.1
|
||||||
P8IGN = E251,E201,E302,E202,E126,E127,E203,E226
|
P8IGN = E251,E201,E302,E202,E126,E127,E203,E226,E402,W504,W503,E731
|
||||||
PREFIX ?= /usr
|
PREFIX ?= /usr
|
||||||
BINDIR ?= $(PREFIX)/bin
|
BINDIR ?= $(PREFIX)/bin
|
||||||
MANDIR ?= $(PREFIX)/share/man/man1
|
MANDIR ?= $(PREFIX)/share/man/man1
|
||||||
|
|||||||
@@ -11,15 +11,20 @@ Example to pull custom params (topo, switch, etc.) from a file:
|
|||||||
sudo mn --custom ~/mininet/custom/custom_example.py
|
sudo mn --custom ~/mininet/custom/custom_example.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from functools import partial
|
||||||
|
from optparse import OptionParser # pylint: disable=deprecated-module
|
||||||
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
# Fix setuptools' evil madness, and open up (more?) security holes
|
# Fix setuptools' evil madness, and open up (more?) security holes
|
||||||
if 'PYTHONPATH' in os.environ:
|
if 'PYTHONPATH' in os.environ:
|
||||||
sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
|
sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
|
||||||
|
|
||||||
|
# pylint: disable=wrong-import-position
|
||||||
|
|
||||||
from mininet.clean import cleanup
|
from mininet.clean import cleanup
|
||||||
import mininet.cli
|
import mininet.cli
|
||||||
from mininet.log import lg, LEVELS, info, debug, warn, error, output
|
from mininet.log import lg, LEVELS, info, debug, warn, error, output
|
||||||
@@ -34,10 +39,7 @@ from mininet.link import Link, TCLink, TCULink, OVSLink
|
|||||||
from mininet.topo import ( SingleSwitchTopo, LinearTopo,
|
from mininet.topo import ( SingleSwitchTopo, LinearTopo,
|
||||||
SingleSwitchReversedTopo, MinimalTopo )
|
SingleSwitchReversedTopo, MinimalTopo )
|
||||||
from mininet.topolib import TreeTopo, TorusTopo
|
from mininet.topolib import TreeTopo, TorusTopo
|
||||||
from mininet.util import customClass, specialClass, splitArgs
|
from mininet.util import customClass, specialClass, splitArgs, buildTopo
|
||||||
from mininet.util import buildTopo
|
|
||||||
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
# Experimental! cluster edition prototype
|
# Experimental! cluster edition prototype
|
||||||
from mininet.examples.cluster import ( MininetCluster, RemoteHost,
|
from mininet.examples.cluster import ( MininetCluster, RemoteHost,
|
||||||
@@ -46,6 +48,7 @@ from mininet.examples.cluster import ( MininetCluster, RemoteHost,
|
|||||||
ClusterCleanup )
|
ClusterCleanup )
|
||||||
from mininet.examples.clustercli import ClusterCLI
|
from mininet.examples.clustercli import ClusterCLI
|
||||||
|
|
||||||
|
|
||||||
PLACEMENT = { 'block': SwitchBinPlacer, 'random': RandomPlacer }
|
PLACEMENT = { 'block': SwitchBinPlacer, 'random': RandomPlacer }
|
||||||
|
|
||||||
# built in topologies, created only when run
|
# built in topologies, created only when run
|
||||||
@@ -107,6 +110,7 @@ def nullTest( _net ):
|
|||||||
"Null 'test' (does nothing)"
|
"Null 'test' (does nothing)"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
TESTS.update( all=allTest, none=nullTest, build=nullTest )
|
TESTS.update( all=allTest, none=nullTest, build=nullTest )
|
||||||
|
|
||||||
# Map to alternate spellings of Mininet() methods
|
# Map to alternate spellings of Mininet() methods
|
||||||
@@ -425,7 +429,7 @@ if __name__ == "__main__":
|
|||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
info( "\n\nKeyboard Interrupt. Shutting down and cleaning up...\n\n")
|
info( "\n\nKeyboard Interrupt. Shutting down and cleaning up...\n\n")
|
||||||
cleanup()
|
cleanup()
|
||||||
except Exception:
|
except Exception: # pylint: disable=broad-except
|
||||||
# Print exception
|
# Print exception
|
||||||
type_, val_, trace_ = sys.exc_info()
|
type_, val_, trace_ = sys.exc_info()
|
||||||
errorMsg = ( "-"*80 + "\n" +
|
errorMsg = ( "-"*80 + "\n" +
|
||||||
|
|||||||
+3
-2
@@ -34,14 +34,14 @@ and '/var/run'. It also has a temporary private directory mounted
|
|||||||
on '/var/mn'
|
on '/var/mn'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
from mininet.node import Host
|
from mininet.node import Host
|
||||||
from mininet.cli import CLI
|
from mininet.cli import CLI
|
||||||
from mininet.topo import SingleSwitchTopo
|
from mininet.topo import SingleSwitchTopo
|
||||||
from mininet.log import setLogLevel, info
|
from mininet.log import setLogLevel, info
|
||||||
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
|
|
||||||
# Sample usage
|
# Sample usage
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ def testHostWithPrivateDirs():
|
|||||||
CLI( net )
|
CLI( net )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
testHostWithPrivateDirs()
|
testHostWithPrivateDirs()
|
||||||
|
|||||||
+38
-28
@@ -74,6 +74,15 @@ Things to do:
|
|||||||
- hifi support (e.g. delay compensation)
|
- hifi support (e.g. delay compensation)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from signal import signal, SIGINT, SIG_IGN
|
||||||
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
import os
|
||||||
|
from random import randrange
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
from itertools import groupby
|
||||||
|
from operator import attrgetter
|
||||||
|
from distutils.version import StrictVersion
|
||||||
|
|
||||||
from mininet.node import Node, Host, OVSSwitch, Controller
|
from mininet.node import Node, Host, OVSSwitch, Controller
|
||||||
from mininet.link import Link, Intf
|
from mininet.link import Link, Intf
|
||||||
@@ -85,15 +94,7 @@ from mininet.examples.clustercli import CLI
|
|||||||
from mininet.log import setLogLevel, debug, info, error
|
from mininet.log import setLogLevel, debug, info, error
|
||||||
from mininet.clean import addCleanupCallback
|
from mininet.clean import addCleanupCallback
|
||||||
|
|
||||||
from signal import signal, SIGINT, SIG_IGN
|
# pylint: disable=too-many-arguments
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
|
||||||
import os
|
|
||||||
from random import randrange
|
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
from itertools import groupby
|
|
||||||
from operator import attrgetter
|
|
||||||
from distutils.version import StrictVersion
|
|
||||||
|
|
||||||
|
|
||||||
def findUser():
|
def findUser():
|
||||||
@@ -261,7 +262,7 @@ class RemoteMixin( object ):
|
|||||||
cmd: remote command to run (list)
|
cmd: remote command to run (list)
|
||||||
**params: parameters to Popen()
|
**params: parameters to Popen()
|
||||||
returns: Popen() object"""
|
returns: Popen() object"""
|
||||||
if type( cmd ) is str:
|
if isinstance( cmd, str):
|
||||||
cmd = cmd.split()
|
cmd = cmd.split()
|
||||||
if self.isRemote:
|
if self.isRemote:
|
||||||
if sudo:
|
if sudo:
|
||||||
@@ -289,6 +290,7 @@ class RemoteMixin( object ):
|
|||||||
def addIntf( self, *args, **kwargs ):
|
def addIntf( self, *args, **kwargs ):
|
||||||
"Override: use RemoteLink.moveIntf"
|
"Override: use RemoteLink.moveIntf"
|
||||||
# kwargs.update( moveIntfFn=RemoteLink.moveIntf )
|
# kwargs.update( moveIntfFn=RemoteLink.moveIntf )
|
||||||
|
# pylint: disable=useless-super-delegation
|
||||||
return super( RemoteMixin, self).addIntf( *args, **kwargs )
|
return super( RemoteMixin, self).addIntf( *args, **kwargs )
|
||||||
|
|
||||||
|
|
||||||
@@ -325,6 +327,7 @@ class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
|
|||||||
StrictVersion( '1.10' ) )
|
StrictVersion( '1.10' ) )
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def batchStartup( cls, switches, **_kwargs ):
|
def batchStartup( cls, switches, **_kwargs ):
|
||||||
"Start up switches in per-server batches"
|
"Start up switches in per-server batches"
|
||||||
key = attrgetter( 'server' )
|
key = attrgetter( 'server' )
|
||||||
@@ -336,6 +339,7 @@ class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
|
|||||||
return switches
|
return switches
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def batchShutdown( cls, switches, **_kwargs ):
|
def batchShutdown( cls, switches, **_kwargs ):
|
||||||
"Stop switches in per-server batches"
|
"Stop switches in per-server batches"
|
||||||
key = attrgetter( 'server' )
|
key = attrgetter( 'server' )
|
||||||
@@ -413,8 +417,9 @@ class RemoteLink( Link ):
|
|||||||
# And we can't ssh into this server remotely as 'localhost',
|
# And we can't ssh into this server remotely as 'localhost',
|
||||||
# so try again swappping node1 and node2
|
# so try again swappping node1 and node2
|
||||||
if node2.server == 'localhost':
|
if node2.server == 'localhost':
|
||||||
return self.makeTunnel( node2, node1, intfname2, intfname1,
|
return self.makeTunnel( node1=node2, node2=node1,
|
||||||
addr2, addr1 )
|
intfname1=intfname2, intfname2=intfname1,
|
||||||
|
addr1=addr2, addr2=addr1 )
|
||||||
debug( '\n*** Make SSH tunnel ' + node1.server + ':' + intfname1 +
|
debug( '\n*** Make SSH tunnel ' + node1.server + ':' + intfname1 +
|
||||||
' == ' + node2.server + ':' + intfname2 )
|
' == ' + node2.server + ':' + intfname2 )
|
||||||
# 1. Create tap interfaces
|
# 1. Create tap interfaces
|
||||||
@@ -526,8 +531,9 @@ class RemoteGRELink( RemoteLink ):
|
|||||||
# We should never try to create a tunnel to ourselves!
|
# We should never try to create a tunnel to ourselves!
|
||||||
assert node1.server != node2.server
|
assert node1.server != node2.server
|
||||||
if node2.server == 'localhost':
|
if node2.server == 'localhost':
|
||||||
return self.makeTunnel( node2, node1, intfname2, intfname1,
|
return self.makeTunnel( node1=node2, node2=node1,
|
||||||
addr2, addr1 )
|
intfname1=intfname2, intfname2=intfname1,
|
||||||
|
addr1=addr2, addr2=addr1 )
|
||||||
IP1, IP2 = node1.serverIP, node2.serverIP
|
IP1, IP2 = node1.serverIP, node2.serverIP
|
||||||
# GRE tunnel needs to be set up with the IP of the local interface
|
# GRE tunnel needs to be set up with the IP of the local interface
|
||||||
# that connects the remote node, NOT '127.0.0.1' of localhost
|
# that connects the remote node, NOT '127.0.0.1' of localhost
|
||||||
@@ -555,6 +561,7 @@ class RemoteGRELink( RemoteLink ):
|
|||||||
node.rcmd('ip link set dev %s mtu 1450' % intfname)
|
node.rcmd('ip link set dev %s mtu 1450' % intfname)
|
||||||
if not self.moveIntf(intfname, node):
|
if not self.moveIntf(intfname, node):
|
||||||
raise Exception('interface move failed on node %s' % node)
|
raise Exception('interface move failed on node %s' % node)
|
||||||
|
return None # May want to return something useful here
|
||||||
|
|
||||||
|
|
||||||
# Some simple placement algorithms for MininetCluster
|
# Some simple placement algorithms for MininetCluster
|
||||||
@@ -589,10 +596,10 @@ class Placer( object ):
|
|||||||
|
|
||||||
class RandomPlacer( Placer ):
|
class RandomPlacer( Placer ):
|
||||||
"Random placement"
|
"Random placement"
|
||||||
def place( self, nodename ):
|
def place( self, node ):
|
||||||
"""Random placement function
|
"""Random placement function
|
||||||
nodename: node name"""
|
node: node"""
|
||||||
assert nodename # please pylint
|
assert node # please pylint
|
||||||
# This may be slow with lots of servers
|
# This may be slow with lots of servers
|
||||||
return self.servers[ randrange( 0, len( self.servers ) ) ]
|
return self.servers[ randrange( 0, len( self.servers ) ) ]
|
||||||
|
|
||||||
@@ -606,10 +613,10 @@ class RoundRobinPlacer( Placer ):
|
|||||||
Placer.__init__( self, *args, **kwargs )
|
Placer.__init__( self, *args, **kwargs )
|
||||||
self.next = 0
|
self.next = 0
|
||||||
|
|
||||||
def place( self, nodename ):
|
def place( self, node ):
|
||||||
"""Round-robin placement function
|
"""Round-robin placement function
|
||||||
nodename: node name"""
|
node: node"""
|
||||||
assert nodename # please pylint
|
assert node # please pylint
|
||||||
# This may be slow with lots of servers
|
# This may be slow with lots of servers
|
||||||
server = self.servers[ self.next ]
|
server = self.servers[ self.next ]
|
||||||
self.next = ( self.next + 1 ) % len( self.servers )
|
self.next = ( self.next + 1 ) % len( self.servers )
|
||||||
@@ -647,7 +654,7 @@ class SwitchBinPlacer( Placer ):
|
|||||||
tickets = sum( [ binsizes[ server ] * [ server ]
|
tickets = sum( [ binsizes[ server ] * [ server ]
|
||||||
for server in servers ], [] )
|
for server in servers ], [] )
|
||||||
# And assign one ticket to each node
|
# And assign one ticket to each node
|
||||||
return { node: ticket for node, ticket in zip( nodes, tickets ) }
|
return dict( zip( nodes, tickets ) )
|
||||||
|
|
||||||
def calculatePlacement( self ):
|
def calculatePlacement( self ):
|
||||||
"Pre-calculate node placement"
|
"Pre-calculate node placement"
|
||||||
@@ -704,21 +711,21 @@ class HostSwitchBinPlacer( Placer ):
|
|||||||
self.cset = frozenset( self.controllers )
|
self.cset = frozenset( self.controllers )
|
||||||
self.hind, self.sind, self.cind = 0, 0, 0
|
self.hind, self.sind, self.cind = 0, 0, 0
|
||||||
|
|
||||||
def place( self, nodename ):
|
def place( self, node ):
|
||||||
"""Simple placement algorithm:
|
"""Simple placement algorithm:
|
||||||
place nodes into evenly sized bins"""
|
place nodes into evenly sized bins"""
|
||||||
# Place nodes into bins
|
# Place nodes into bins
|
||||||
if nodename in self.hset:
|
if node in self.hset:
|
||||||
server = self.servdict[ self.hind / self.hbin ]
|
server = self.servdict[ self.hind / self.hbin ]
|
||||||
self.hind += 1
|
self.hind += 1
|
||||||
elif nodename in self.sset:
|
elif node in self.sset:
|
||||||
server = self.servdict[ self.sind / self.sbin ]
|
server = self.servdict[ self.sind / self.sbin ]
|
||||||
self.sind += 1
|
self.sind += 1
|
||||||
elif nodename in self.cset:
|
elif node in self.cset:
|
||||||
server = self.servdict[ self.cind / self.cbin ]
|
server = self.servdict[ self.cind / self.cbin ]
|
||||||
self.cind += 1
|
self.cind += 1
|
||||||
else:
|
else:
|
||||||
info( 'warning: unknown node', nodename )
|
info( 'warning: unknown node', node )
|
||||||
server = self.servdict[ 0 ]
|
server = self.servdict[ 0 ]
|
||||||
return server
|
return server
|
||||||
|
|
||||||
@@ -764,6 +771,7 @@ class MininetCluster( Mininet ):
|
|||||||
# Make sure control directory exists
|
# Make sure control directory exists
|
||||||
self.cdir = os.environ[ 'HOME' ] + '/.ssh/mn'
|
self.cdir = os.environ[ 'HOME' ] + '/.ssh/mn'
|
||||||
errRun( [ 'mkdir', '-p', self.cdir ] )
|
errRun( [ 'mkdir', '-p', self.cdir ] )
|
||||||
|
# pylint: disable=unexpected-keyword-arg
|
||||||
Mininet.__init__( self, *args, **params )
|
Mininet.__init__( self, *args, **params )
|
||||||
|
|
||||||
def popen( self, cmd ):
|
def popen( self, cmd ):
|
||||||
@@ -840,18 +848,19 @@ class MininetCluster( Mininet ):
|
|||||||
if cfile:
|
if cfile:
|
||||||
config.setdefault( 'controlPath', cfile )
|
config.setdefault( 'controlPath', cfile )
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ,signature-differs
|
||||||
def addController( self, *args, **kwargs ):
|
def addController( self, *args, **kwargs ):
|
||||||
"Patch to update IP address to global IP address"
|
"Patch to update IP address to global IP address"
|
||||||
controller = Mininet.addController( self, *args, **kwargs )
|
controller = Mininet.addController( self, *args, **kwargs )
|
||||||
loopback = '127.0.0.1'
|
loopback = '127.0.0.1'
|
||||||
if ( not isinstance( controller, Controller ) or
|
if ( not isinstance( controller, Controller ) or
|
||||||
controller.IP() != loopback ):
|
controller.IP() != loopback ):
|
||||||
return
|
return None
|
||||||
# Find route to a different server IP address
|
# Find route to a different server IP address
|
||||||
serverIPs = [ ip for ip in self.serverIP.values()
|
serverIPs = [ ip for ip in self.serverIP.values()
|
||||||
if ip is not controller.IP() ]
|
if ip is not controller.IP() ]
|
||||||
if not serverIPs:
|
if not serverIPs:
|
||||||
return # no remote servers - loopback is fine
|
return None # no remote servers - loopback is fine
|
||||||
remoteIP = serverIPs[ 0 ]
|
remoteIP = serverIPs[ 0 ]
|
||||||
# Route should contain 'dev <intfname>'
|
# Route should contain 'dev <intfname>'
|
||||||
route = controller.cmd( 'ip route get', remoteIP,
|
route = controller.cmd( 'ip route get', remoteIP,
|
||||||
@@ -865,6 +874,7 @@ class MininetCluster( Mininet ):
|
|||||||
debug( controller, 'IP address updated to', controller.IP() )
|
debug( controller, 'IP address updated to', controller.IP() )
|
||||||
return controller
|
return controller
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ,signature-differs
|
||||||
def buildFromTopo( self, *args, **kwargs ):
|
def buildFromTopo( self, *args, **kwargs ):
|
||||||
"Start network"
|
"Start network"
|
||||||
info( '*** Placing nodes\n' )
|
info( '*** Placing nodes\n' )
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ def clusterSanity():
|
|||||||
CLI( net )
|
CLI( net )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
clusterSanity()
|
clusterSanity()
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class ClusterCLI( CLI ):
|
|||||||
if not nx:
|
if not nx:
|
||||||
try:
|
try:
|
||||||
# pylint: disable=import-error,no-member
|
# pylint: disable=import-error,no-member
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
import networkx
|
import networkx
|
||||||
nx = networkx # satisfy pylint
|
nx = networkx # satisfy pylint
|
||||||
from matplotlib import pyplot
|
from matplotlib import pyplot
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ def demo():
|
|||||||
CLI( net )
|
CLI( net )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
demo()
|
demo()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ def perf(Link):
|
|||||||
net.iperf()
|
net.iperf()
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel('info')
|
setLogLevel('info')
|
||||||
perf( RemoteSSHLink )
|
perf( RemoteSSHLink )
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ Bob Lantz, April 2010
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
# pylint: disable=import-error
|
||||||
from Tkinter import Frame, Button, Label, Text, Scrollbar, Canvas, Wm, READABLE
|
from Tkinter import Frame, Button, Label, Text, Scrollbar, Canvas, Wm, READABLE
|
||||||
|
|
||||||
from mininet.log import setLogLevel
|
from mininet.log import setLogLevel
|
||||||
@@ -34,6 +35,9 @@ from mininet.topolib import TreeNet
|
|||||||
from mininet.term import makeTerms, cleanUpScreens
|
from mininet.term import makeTerms, cleanUpScreens
|
||||||
from mininet.util import quietRun
|
from mininet.util import quietRun
|
||||||
|
|
||||||
|
# pylint: disable=too-many-arguments
|
||||||
|
|
||||||
|
|
||||||
class Console( Frame ):
|
class Console( Frame ):
|
||||||
"A simple console on a host."
|
"A simple console on a host."
|
||||||
|
|
||||||
@@ -319,7 +323,7 @@ class ConsoleApp( Frame ):
|
|||||||
if not m:
|
if not m:
|
||||||
return
|
return
|
||||||
val, units = float( m.group( 1 ) ), m.group( 2 )
|
val, units = float( m.group( 1 ) ), m.group( 2 )
|
||||||
#convert to Gbps
|
# convert to Gbps
|
||||||
if units[0] == 'M':
|
if units[0] == 'M':
|
||||||
val *= 10 ** -3
|
val *= 10 ** -3
|
||||||
elif units[0] == 'K':
|
elif units[0] == 'K':
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class MultiSwitch( OVSSwitch ):
|
|||||||
def start( self, controllers ):
|
def start( self, controllers ):
|
||||||
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, waitConnected=True )
|
net = Mininet( topo=topo, switch=MultiSwitch, build=False, waitConnected=True )
|
||||||
for c in [ c0, c1 ]:
|
for c in [ c0, c1 ]:
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ def multiControllerNet():
|
|||||||
info( "*** Stopping network\n" )
|
info( "*** Stopping network\n" )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' ) # for CLI output
|
setLogLevel( 'info' ) # for CLI output
|
||||||
multiControllerNet()
|
multiControllerNet()
|
||||||
|
|||||||
@@ -59,13 +59,14 @@ class MininetFacade( object ):
|
|||||||
|
|
||||||
def __getitem__( self, key ):
|
def __getitem__( self, key ):
|
||||||
"returns primary/named networks or node from any net"
|
"returns primary/named networks or node from any net"
|
||||||
#search kwargs for net named key
|
# search kwargs for net named key
|
||||||
if key in self.nameToNet:
|
if key in self.nameToNet:
|
||||||
return self.nameToNet[ key ]
|
return self.nameToNet[ key ]
|
||||||
#search each net for node named key
|
# search each net for node named key
|
||||||
for net in self.nets:
|
for net in self.nets:
|
||||||
if key in net:
|
if key in net:
|
||||||
return net[ key ]
|
return net[ key ]
|
||||||
|
return None
|
||||||
|
|
||||||
def __iter__( self ):
|
def __iter__( self ):
|
||||||
"Iterate through all nodes in all Mininet objects"
|
"Iterate through all nodes in all Mininet objects"
|
||||||
@@ -100,6 +101,7 @@ class MininetFacade( object ):
|
|||||||
|
|
||||||
class ControlNetwork( Topo ):
|
class ControlNetwork( Topo ):
|
||||||
"Control Network Topology"
|
"Control Network Topology"
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def build( self, n, dataController=DataController, **_kwargs ):
|
def build( self, n, dataController=DataController, **_kwargs ):
|
||||||
"""n: number of data network controller nodes
|
"""n: number of data network controller nodes
|
||||||
dataController: class for data network controllers"""
|
dataController: class for data network controllers"""
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ def bwtest( cpuLimits, period_us=100000, seconds=10 ):
|
|||||||
try:
|
try:
|
||||||
net = Mininet( topo=topo, host=host, waitConnected=True )
|
net = Mininet( topo=topo, host=host, waitConnected=True )
|
||||||
# pylint: disable=bare-except
|
# pylint: disable=bare-except
|
||||||
except:
|
except: # noqa
|
||||||
info( '*** Skipping scheduler %s and cleaning up\n' % sched )
|
info( '*** Skipping scheduler %s and cleaning up\n' % sched )
|
||||||
cleanup()
|
cleanup()
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ def emptyNet():
|
|||||||
info( '*** Stopping network' )
|
info( '*** Stopping network' )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
emptyNet()
|
emptyNet()
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ hardware interface) to a network after the network is created.
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from mininet.cli import CLI
|
from mininet.cli import CLI
|
||||||
from mininet.log import setLogLevel, info, error
|
from mininet.log import setLogLevel, info, error
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
@@ -15,6 +17,7 @@ from mininet.link import Intf
|
|||||||
from mininet.topolib import TreeTopo
|
from mininet.topolib import TreeTopo
|
||||||
from mininet.util import quietRun
|
from mininet.util import quietRun
|
||||||
|
|
||||||
|
|
||||||
def checkIntf( intf ):
|
def checkIntf( intf ):
|
||||||
"Make sure intf exists and is not configured."
|
"Make sure intf exists and is not configured."
|
||||||
config = quietRun( 'ifconfig %s 2>/dev/null' % intf, shell=True )
|
config = quietRun( 'ifconfig %s 2>/dev/null' % intf, shell=True )
|
||||||
@@ -27,6 +30,7 @@ def checkIntf( intf ):
|
|||||||
'and is probably in use!\n' )
|
'and is probably in use!\n' )
|
||||||
exit( 1 )
|
exit( 1 )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ def intfOptions():
|
|||||||
info( '\n*** Done testing\n' )
|
info( '\n*** Done testing\n' )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
intfOptions()
|
intfOptions()
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ def verySimpleLimit( bw=150 ):
|
|||||||
h2.cmdPrint( 'tc -d class show dev', h2.defaultIntf() )
|
h2.cmdPrint( 'tc -d class show dev', h2.defaultIntf() )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
limit()
|
limit()
|
||||||
|
|||||||
@@ -24,20 +24,24 @@ of switches, this example demonstrates:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
from mininet.node import UserSwitch, OVSKernelSwitch, Controller
|
from mininet.node import UserSwitch, OVSKernelSwitch, Controller
|
||||||
from mininet.topo import Topo
|
from mininet.topo import Topo
|
||||||
from mininet.log import lg, info
|
from mininet.log import lg, info
|
||||||
from mininet.util import irange, quietRun
|
from mininet.util import irange, quietRun
|
||||||
from mininet.link import TCLink
|
from mininet.link import TCLink
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
import sys
|
|
||||||
flush = sys.stdout.flush
|
flush = sys.stdout.flush
|
||||||
|
|
||||||
|
|
||||||
class LinearTestTopo( Topo ):
|
class LinearTestTopo( Topo ):
|
||||||
"Topology for a string of N hosts and N-1 switches."
|
"Topology for a string of N hosts and N-1 switches."
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def build( self, N, **params ):
|
def build( self, N, **params ):
|
||||||
# Create switches and hosts
|
# Create switches and hosts
|
||||||
hosts = [ self.addHost( 'h%s' % h )
|
hosts = [ self.addHost( 'h%s' % h )
|
||||||
@@ -79,7 +83,7 @@ def linearBandwidthTest( lengths ):
|
|||||||
output = quietRun( 'sysctl -w net.ipv4.tcp_congestion_control=reno' )
|
output = quietRun( 'sysctl -w net.ipv4.tcp_congestion_control=reno' )
|
||||||
assert 'reno' in output
|
assert 'reno' in output
|
||||||
|
|
||||||
for datapath in switches.keys():
|
for datapath in switches:
|
||||||
info( "*** testing", datapath, "datapath\n" )
|
info( "*** testing", datapath, "datapath\n" )
|
||||||
Switch = switches[ datapath ]
|
Switch = switches[ datapath ]
|
||||||
results[ datapath ] = []
|
results[ datapath ] = []
|
||||||
@@ -105,7 +109,7 @@ def linearBandwidthTest( lengths ):
|
|||||||
results[ datapath ] += [ ( n, serverbw ) ]
|
results[ datapath ] += [ ( n, serverbw ) ]
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
for datapath in switches.keys():
|
for datapath in switches:
|
||||||
info( "\n*** Linear network results for", datapath, "datapath:\n" )
|
info( "\n*** Linear network results for", datapath, "datapath:\n" )
|
||||||
result = results[ datapath ]
|
result = results[ datapath ]
|
||||||
info( "SwitchCount\tiperf Results\n" )
|
info( "SwitchCount\tiperf Results\n" )
|
||||||
@@ -115,6 +119,7 @@ def linearBandwidthTest( lengths ):
|
|||||||
info( '\n')
|
info( '\n')
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
lg.setLogLevel( 'info' )
|
lg.setLogLevel( 'info' )
|
||||||
sizes = [ 1, 2, 3, 4 ]
|
sizes = [ 1, 2, 3, 4 ]
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ from mininet.cli import CLI
|
|||||||
class LinuxRouter( Node ):
|
class LinuxRouter( Node ):
|
||||||
"A Node with IP forwarding enabled."
|
"A Node with IP forwarding enabled."
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def config( self, **params ):
|
def config( self, **params ):
|
||||||
super( LinuxRouter, self).config( **params )
|
super( LinuxRouter, self).config( **params )
|
||||||
# Enable forwarding on the router
|
# Enable forwarding on the router
|
||||||
@@ -51,6 +52,7 @@ class LinuxRouter( Node ):
|
|||||||
class NetworkTopo( Topo ):
|
class NetworkTopo( Topo ):
|
||||||
"A LinuxRouter connecting three IP subnets"
|
"A LinuxRouter connecting three IP subnets"
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def build( self, **_opts ):
|
def build( self, **_opts ):
|
||||||
|
|
||||||
defaultIP = '192.168.1.1/24' # IP address for r0-eth1
|
defaultIP = '192.168.1.1/24' # IP address for r0-eth1
|
||||||
@@ -87,6 +89,7 @@ def run():
|
|||||||
CLI( net )
|
CLI( net )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
run()
|
run()
|
||||||
|
|||||||
+65
-60
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
MiniEdit: a simple network editor for Mininet
|
MiniEdit: a simple network editor for Mininet
|
||||||
@@ -13,16 +13,30 @@ Controller icon from http://semlabs.co.uk/
|
|||||||
OpenFlow icon from https://www.opennetworking.org/
|
OpenFlow icon from https://www.opennetworking.org/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Miniedit needs some work in order to pass pylint...
|
import json
|
||||||
# pylint: disable=line-too-long,too-many-branches
|
import os
|
||||||
# pylint: disable=too-many-statements,attribute-defined-outside-init
|
import re
|
||||||
# pylint: disable=missing-docstring
|
|
||||||
|
|
||||||
MINIEDIT_VERSION = '2.2.0.1'
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from distutils.version import StrictVersion
|
||||||
|
from functools import partial
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
from subprocess import call
|
from subprocess import call
|
||||||
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
|
from mininet.log import info, debug, warn, setLogLevel
|
||||||
|
from mininet.net import Mininet, VERSION
|
||||||
|
from mininet.util import (netParse, ipAdd, quietRun,
|
||||||
|
buildTopo, custom, customClass )
|
||||||
|
from mininet.term import makeTerm, cleanUpScreens
|
||||||
|
from mininet.node import (Controller, RemoteController, NOX, OVSController,
|
||||||
|
CPULimitedHost, Host, Node,
|
||||||
|
OVSSwitch, UserSwitch, IVSSwitch )
|
||||||
|
from mininet.link import TCLink, Intf, Link
|
||||||
|
from mininet.cli import CLI
|
||||||
|
from mininet.moduledeps import moduleDeps
|
||||||
|
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
|
||||||
|
from mininet.topolib import TreeTopo
|
||||||
|
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
if sys.version_info[0] == 2:
|
if sys.version_info[0] == 2:
|
||||||
@@ -47,38 +61,24 @@ else:
|
|||||||
from tkinter import font as tkFont
|
from tkinter import font as tkFont
|
||||||
from tkinter import simpledialog as tkSimpleDialog
|
from tkinter import simpledialog as tkSimpleDialog
|
||||||
from tkinter import filedialog as tkFileDialog
|
from tkinter import filedialog as tkFileDialog
|
||||||
|
# someday: from ttk import *
|
||||||
# pylint: enable=import-error
|
# pylint: enable=import-error
|
||||||
|
|
||||||
import re
|
|
||||||
import json
|
# Miniedit still needs work in order to pass pylint...
|
||||||
from distutils.version import StrictVersion
|
# pylint: disable=line-too-long,too-many-branches
|
||||||
import os
|
# pylint: disable=too-many-statements,attribute-defined-outside-init
|
||||||
from functools import partial
|
# pylint: disable=missing-docstring,too-many-ancestors
|
||||||
|
# pylint: disable=too-many-nested-blocks,too-many-arguments
|
||||||
|
|
||||||
|
|
||||||
|
MINIEDIT_VERSION = '2.2.0.1'
|
||||||
|
|
||||||
if 'PYTHONPATH' in os.environ:
|
if 'PYTHONPATH' in os.environ:
|
||||||
sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
|
sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
|
||||||
|
|
||||||
# someday: from ttk import *
|
|
||||||
|
|
||||||
from mininet.log import info, debug, warn, setLogLevel
|
|
||||||
from mininet.net import Mininet, VERSION
|
|
||||||
from mininet.util import netParse, ipAdd, quietRun
|
|
||||||
from mininet.util import buildTopo
|
|
||||||
from mininet.util import custom, customClass
|
|
||||||
from mininet.term import makeTerm, cleanUpScreens
|
|
||||||
from mininet.node import Controller, RemoteController, NOX, OVSController
|
|
||||||
from mininet.node import CPULimitedHost, Host, Node
|
|
||||||
from mininet.node import OVSSwitch, UserSwitch
|
|
||||||
from mininet.link import TCLink, Intf, Link
|
|
||||||
from mininet.cli import CLI
|
|
||||||
from mininet.moduledeps import moduleDeps
|
|
||||||
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
|
|
||||||
from mininet.topolib import TreeTopo
|
|
||||||
|
|
||||||
info( 'MiniEdit running against Mininet '+VERSION, '\n' )
|
info( 'MiniEdit running against Mininet '+VERSION, '\n' )
|
||||||
MININET_VERSION = re.sub(r'[^\d\.]', '', VERSION)
|
MININET_VERSION = re.sub(r'[^\d\.]', '', VERSION)
|
||||||
if StrictVersion(MININET_VERSION) > StrictVersion('2.0'):
|
|
||||||
from mininet.node import IVSSwitch
|
|
||||||
|
|
||||||
TOPODEF = 'none'
|
TOPODEF = 'none'
|
||||||
TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
|
TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
|
||||||
@@ -138,6 +138,7 @@ class LegacyRouter( Node ):
|
|||||||
def __init__( self, name, inNamespace=True, **params ):
|
def __init__( self, name, inNamespace=True, **params ):
|
||||||
Node.__init__( self, name, inNamespace, **params )
|
Node.__init__( self, name, inNamespace, **params )
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def config( self, **_params ):
|
def config( self, **_params ):
|
||||||
if self.intfs:
|
if self.intfs:
|
||||||
self.setParam( _params, 'setIP', ip='0.0.0.0' )
|
self.setParam( _params, 'setIP', ip='0.0.0.0' )
|
||||||
@@ -818,8 +819,8 @@ class VerticalScrolledTable(LabelFrame):
|
|||||||
* This frame only allows vertical scrolling
|
* This frame only allows vertical scrolling
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent, rows=2, columns=2, title=None, *args, **kw):
|
def __init__(self, parent, rows=2, columns=2, title=None, **kw):
|
||||||
LabelFrame.__init__(self, parent, text=title, padx=5, pady=5, *args, **kw)
|
LabelFrame.__init__(self, parent, text=title, padx=5, pady=5, **kw)
|
||||||
|
|
||||||
# create a canvas object and a vertical scrollbar for scrolling it
|
# create a canvas object and a vertical scrollbar for scrolling it
|
||||||
vscrollbar = Scrollbar(self, orient=VERTICAL)
|
vscrollbar = Scrollbar(self, orient=VERTICAL)
|
||||||
@@ -855,8 +856,6 @@ class VerticalScrolledTable(LabelFrame):
|
|||||||
canvas.itemconfigure(interior_id, width=canvas.winfo_width())
|
canvas.itemconfigure(interior_id, width=canvas.winfo_width())
|
||||||
canvas.bind('<Configure>', _configure_canvas)
|
canvas.bind('<Configure>', _configure_canvas)
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
class TableFrame(Frame):
|
class TableFrame(Frame):
|
||||||
def __init__(self, parent, rows=2, columns=2):
|
def __init__(self, parent, rows=2, columns=2):
|
||||||
|
|
||||||
@@ -888,7 +887,7 @@ class TableFrame(Frame):
|
|||||||
label.grid(row=self.rows, column=column, sticky="wens", padx=1, pady=1)
|
label.grid(row=self.rows, column=column, sticky="wens", padx=1, pady=1)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
label.insert(0, value[column])
|
label.insert(0, value[column])
|
||||||
if readonly == True:
|
if readonly:
|
||||||
label.configure(state='readonly')
|
label.configure(state='readonly')
|
||||||
current_row.append(label)
|
current_row.append(label)
|
||||||
self._widgets.append(current_row)
|
self._widgets.append(current_row)
|
||||||
@@ -1401,11 +1400,11 @@ class MiniEdit( Frame ):
|
|||||||
|
|
||||||
def addNode( self, node, nodeNum, x, y, name=None):
|
def addNode( self, node, nodeNum, x, y, name=None):
|
||||||
"Add a new node to our canvas."
|
"Add a new node to our canvas."
|
||||||
if 'Switch' == node:
|
if node == 'Switch':
|
||||||
self.switchCount += 1
|
self.switchCount += 1
|
||||||
if 'Host' == node:
|
if node == 'Host':
|
||||||
self.hostCount += 1
|
self.hostCount += 1
|
||||||
if 'Controller' == node:
|
if node == 'Controller':
|
||||||
self.controllerCount += 1
|
self.controllerCount += 1
|
||||||
if name is None:
|
if name is None:
|
||||||
name = self.nodePrefixes[ node ] + nodeNum
|
name = self.nodePrefixes[ node ] + nodeNum
|
||||||
@@ -1422,13 +1421,16 @@ class MiniEdit( Frame ):
|
|||||||
|
|
||||||
def convertJsonUnicode(self, text):
|
def convertJsonUnicode(self, text):
|
||||||
"Some part of Mininet don't like Unicode"
|
"Some part of Mininet don't like Unicode"
|
||||||
|
try:
|
||||||
|
unicode
|
||||||
|
except NameError:
|
||||||
|
return text
|
||||||
if isinstance(text, dict):
|
if isinstance(text, dict):
|
||||||
return {self.convertJsonUnicode(key): self.convertJsonUnicode(value) for key, value in text.items()}
|
return {self.convertJsonUnicode(key): self.convertJsonUnicode(value) for key, value in text.items()}
|
||||||
elif isinstance(text, list):
|
if isinstance(text, list):
|
||||||
return [self.convertJsonUnicode(element) for element in text]
|
return [self.convertJsonUnicode(element) for element in text]
|
||||||
elif isinstance(text, unicode):
|
if isinstance(text, unicode): # pylint: disable=undefined-variable
|
||||||
return text.encode('utf-8')
|
return text.encode('utf-8')
|
||||||
else:
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def loadTopology( self ):
|
def loadTopology( self ):
|
||||||
@@ -1440,7 +1442,7 @@ class MiniEdit( Frame ):
|
|||||||
('All Files','*'),
|
('All Files','*'),
|
||||||
]
|
]
|
||||||
f = tkFileDialog.askopenfile(filetypes=myFormats, mode='rb')
|
f = tkFileDialog.askopenfile(filetypes=myFormats, mode='rb')
|
||||||
if f == None:
|
if f is None:
|
||||||
return
|
return
|
||||||
self.newTopology()
|
self.newTopology()
|
||||||
loadedTopology = self.convertJsonUnicode(json.load(f))
|
loadedTopology = self.convertJsonUnicode(json.load(f))
|
||||||
@@ -1601,10 +1603,11 @@ class MiniEdit( Frame ):
|
|||||||
for widget in self.widgetToItem:
|
for widget in self.widgetToItem:
|
||||||
if name == widget[ 'text' ]:
|
if name == widget[ 'text' ]:
|
||||||
return widget
|
return widget
|
||||||
|
return None
|
||||||
|
|
||||||
def newTopology( self ):
|
def newTopology( self ):
|
||||||
"New command."
|
"New command."
|
||||||
for widget in self.widgetToItem.keys():
|
for widget in self.widgetToItem:
|
||||||
self.deleteItem( self.widgetToItem[ widget ] )
|
self.deleteItem( self.widgetToItem[ widget ] )
|
||||||
self.hostCount = 0
|
self.hostCount = 0
|
||||||
self.switchCount = 0
|
self.switchCount = 0
|
||||||
@@ -1725,7 +1728,7 @@ class MiniEdit( Frame ):
|
|||||||
if controllerType == 'inband':
|
if controllerType == 'inband':
|
||||||
inBandCtrl = True
|
inBandCtrl = True
|
||||||
|
|
||||||
if inBandCtrl == True:
|
if inBandCtrl:
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
f.write("class InbandController( RemoteController ):\n")
|
f.write("class InbandController( RemoteController ):\n")
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
@@ -2122,7 +2125,7 @@ class MiniEdit( Frame ):
|
|||||||
c = self.canvas
|
c = self.canvas
|
||||||
x, y = c.canvasx( event.x ), c.canvasy( event.y )
|
x, y = c.canvasx( event.x ), c.canvasy( event.y )
|
||||||
name = self.nodePrefixes[ node ]
|
name = self.nodePrefixes[ node ]
|
||||||
if 'Switch' == node:
|
if node == 'Switch':
|
||||||
self.switchCount += 1
|
self.switchCount += 1
|
||||||
name = self.nodePrefixes[ node ] + str( self.switchCount )
|
name = self.nodePrefixes[ node ] + str( self.switchCount )
|
||||||
self.switchOpts[name] = {}
|
self.switchOpts[name] = {}
|
||||||
@@ -2130,14 +2133,14 @@ class MiniEdit( Frame ):
|
|||||||
self.switchOpts[name]['hostname']=name
|
self.switchOpts[name]['hostname']=name
|
||||||
self.switchOpts[name]['switchType']='default'
|
self.switchOpts[name]['switchType']='default'
|
||||||
self.switchOpts[name]['controllers']=[]
|
self.switchOpts[name]['controllers']=[]
|
||||||
if 'LegacyRouter' == node:
|
if node == 'LegacyRouter':
|
||||||
self.switchCount += 1
|
self.switchCount += 1
|
||||||
name = self.nodePrefixes[ node ] + str( self.switchCount )
|
name = self.nodePrefixes[ node ] + str( self.switchCount )
|
||||||
self.switchOpts[name] = {}
|
self.switchOpts[name] = {}
|
||||||
self.switchOpts[name]['nodeNum']=self.switchCount
|
self.switchOpts[name]['nodeNum']=self.switchCount
|
||||||
self.switchOpts[name]['hostname']=name
|
self.switchOpts[name]['hostname']=name
|
||||||
self.switchOpts[name]['switchType']='legacyRouter'
|
self.switchOpts[name]['switchType']='legacyRouter'
|
||||||
if 'LegacySwitch' == node:
|
if node == 'LegacySwitch':
|
||||||
self.switchCount += 1
|
self.switchCount += 1
|
||||||
name = self.nodePrefixes[ node ] + str( self.switchCount )
|
name = self.nodePrefixes[ node ] + str( self.switchCount )
|
||||||
self.switchOpts[name] = {}
|
self.switchOpts[name] = {}
|
||||||
@@ -2145,13 +2148,13 @@ class MiniEdit( Frame ):
|
|||||||
self.switchOpts[name]['hostname']=name
|
self.switchOpts[name]['hostname']=name
|
||||||
self.switchOpts[name]['switchType']='legacySwitch'
|
self.switchOpts[name]['switchType']='legacySwitch'
|
||||||
self.switchOpts[name]['controllers']=[]
|
self.switchOpts[name]['controllers']=[]
|
||||||
if 'Host' == node:
|
if node == 'Host':
|
||||||
self.hostCount += 1
|
self.hostCount += 1
|
||||||
name = self.nodePrefixes[ node ] + str( self.hostCount )
|
name = self.nodePrefixes[ node ] + str( self.hostCount )
|
||||||
self.hostOpts[name] = {'sched':'host'}
|
self.hostOpts[name] = {'sched':'host'}
|
||||||
self.hostOpts[name]['nodeNum']=self.hostCount
|
self.hostOpts[name]['nodeNum']=self.hostCount
|
||||||
self.hostOpts[name]['hostname']=name
|
self.hostOpts[name]['hostname']=name
|
||||||
if 'Controller' == node:
|
if node == 'Controller':
|
||||||
name = self.nodePrefixes[ node ] + str( self.controllerCount )
|
name = self.nodePrefixes[ node ] + str( self.controllerCount )
|
||||||
ctrlr = { 'controllerType': 'ref',
|
ctrlr = { 'controllerType': 'ref',
|
||||||
'hostname': name,
|
'hostname': name,
|
||||||
@@ -2169,15 +2172,15 @@ class MiniEdit( Frame ):
|
|||||||
self.itemToWidget[ item ] = icon
|
self.itemToWidget[ item ] = icon
|
||||||
self.selectItem( item )
|
self.selectItem( item )
|
||||||
icon.links = {}
|
icon.links = {}
|
||||||
if 'Switch' == node:
|
if node == 'Switch':
|
||||||
icon.bind('<Button-3>', self.do_switchPopup )
|
icon.bind('<Button-3>', self.do_switchPopup )
|
||||||
if 'LegacyRouter' == node:
|
if node == 'LegacyRouter':
|
||||||
icon.bind('<Button-3>', self.do_legacyRouterPopup )
|
icon.bind('<Button-3>', self.do_legacyRouterPopup )
|
||||||
if 'LegacySwitch' == node:
|
if node == 'LegacySwitch':
|
||||||
icon.bind('<Button-3>', self.do_legacySwitchPopup )
|
icon.bind('<Button-3>', self.do_legacySwitchPopup )
|
||||||
if 'Host' == node:
|
if node == 'Host':
|
||||||
icon.bind('<Button-3>', self.do_hostPopup )
|
icon.bind('<Button-3>', self.do_hostPopup )
|
||||||
if 'Controller' == node:
|
if node == 'Controller':
|
||||||
icon.bind('<Button-3>', self.do_controllerPopup )
|
icon.bind('<Button-3>', self.do_controllerPopup )
|
||||||
|
|
||||||
def clickController( self, event ):
|
def clickController( self, event ):
|
||||||
@@ -2374,6 +2377,8 @@ class MiniEdit( Frame ):
|
|||||||
# For now, don't allow hosts to be directly linked
|
# For now, don't allow hosts to be directly linked
|
||||||
stags = self.canvas.gettags( self.widgetToItem[ source ] )
|
stags = self.canvas.gettags( self.widgetToItem[ source ] )
|
||||||
dtags = self.canvas.gettags( target )
|
dtags = self.canvas.gettags( target )
|
||||||
|
# TODO: Make this less confusing
|
||||||
|
# pylint: disable=too-many-boolean-expressions
|
||||||
if (('Host' in stags and 'Host' in dtags) or
|
if (('Host' in stags and 'Host' in dtags) or
|
||||||
('Controller' in dtags and 'LegacyRouter' in stags) or
|
('Controller' in dtags and 'LegacyRouter' in stags) or
|
||||||
('Controller' in stags and 'LegacyRouter' in dtags) or
|
('Controller' in stags and 'LegacyRouter' in dtags) or
|
||||||
@@ -2657,7 +2662,7 @@ class MiniEdit( Frame ):
|
|||||||
linkopts = {}
|
linkopts = {}
|
||||||
source.links[ dest ] = self.link
|
source.links[ dest ] = self.link
|
||||||
dest.links[ source ] = self.link
|
dest.links[ source ] = self.link
|
||||||
self.links[ self.link ] = {'type' :linktype,
|
self.links[ self.link ] = {'type':linktype,
|
||||||
'src':source,
|
'src':source,
|
||||||
'dest':dest,
|
'dest':dest,
|
||||||
'linkOpts':linkopts}
|
'linkOpts':linkopts}
|
||||||
@@ -3225,7 +3230,8 @@ class MiniEdit( Frame ):
|
|||||||
"Parse custom file and add params before parsing cmd-line options."
|
"Parse custom file and add params before parsing cmd-line options."
|
||||||
customs = {}
|
customs = {}
|
||||||
if os.path.isfile( fileName ):
|
if os.path.isfile( fileName ):
|
||||||
execfile( fileName, customs, customs )
|
with open( fileName, 'r' ) as f:
|
||||||
|
exec( f.read() ) # pylint: disable=exec-used
|
||||||
for name, val in customs.items():
|
for name, val in customs.items():
|
||||||
self.setCustom( name, val )
|
self.setCustom( name, val )
|
||||||
else:
|
else:
|
||||||
@@ -3592,8 +3598,7 @@ def addDictOption( opts, choicesDict, default, name, helpStr=None ):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
app = MiniEdit()
|
app = MiniEdit()
|
||||||
### import topology if specified ###
|
|
||||||
app.parseArgs()
|
app.parseArgs()
|
||||||
|
### import topology if specified ###
|
||||||
app.importTopo()
|
app.importTopo()
|
||||||
|
|
||||||
app.mainloop()
|
app.mainloop()
|
||||||
|
|||||||
@@ -19,14 +19,13 @@ to-do:
|
|||||||
- think about clearing last hop - why doesn't that work?
|
- think about clearing last hop - why doesn't that work?
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from random import randint
|
||||||
|
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
from mininet.node import OVSSwitch
|
from mininet.node import OVSSwitch
|
||||||
from mininet.topo import LinearTopo
|
from mininet.topo import LinearTopo
|
||||||
from mininet.log import info, output, warn, setLogLevel
|
from mininet.log import info, output, warn, setLogLevel
|
||||||
|
|
||||||
from random import randint
|
|
||||||
|
|
||||||
|
|
||||||
class MobilitySwitch( OVSSwitch ):
|
class MobilitySwitch( OVSSwitch ):
|
||||||
"Switch that can reattach and rename interfaces"
|
"Switch that can reattach and rename interfaces"
|
||||||
@@ -38,6 +37,7 @@ class MobilitySwitch( OVSSwitch ):
|
|||||||
del self.intfs[ port ]
|
del self.intfs[ port ]
|
||||||
del self.nameToIntf[ intf.name ]
|
del self.nameToIntf[ intf.name ]
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def addIntf( self, intf, rename=False, **kwargs ):
|
def addIntf( self, intf, rename=False, **kwargs ):
|
||||||
"Add (and reparent) an interface"
|
"Add (and reparent) an interface"
|
||||||
OVSSwitch.addIntf( self, intf, **kwargs )
|
OVSSwitch.addIntf( self, intf, **kwargs )
|
||||||
@@ -132,6 +132,7 @@ def mobilityTest():
|
|||||||
old = new
|
old = new
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
mobilityTest()
|
mobilityTest()
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ def runMultiLink():
|
|||||||
class simpleMultiLinkTopo( Topo ):
|
class simpleMultiLinkTopo( Topo ):
|
||||||
"Simple topology with multiple links"
|
"Simple topology with multiple links"
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def build( self, n, **_kwargs ):
|
def build( self, n, **_kwargs ):
|
||||||
h1, h2 = self.addHost( 'h1' ), self.addHost( 'h2' )
|
h1, h2 = self.addHost( 'h1' ), self.addHost( 'h2' )
|
||||||
s1 = self.addSwitch( 's1' )
|
s1 = self.addSwitch( 's1' )
|
||||||
@@ -29,6 +30,7 @@ class simpleMultiLinkTopo( Topo ):
|
|||||||
self.addLink( s1, h1 )
|
self.addLink( s1, h1 )
|
||||||
self.addLink( s1, h2 )
|
self.addLink( s1, h2 )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
runMultiLink()
|
runMultiLink()
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ multiple hosts and monitor their output interactively for a period=
|
|||||||
of time.
|
of time.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from select import poll, POLLIN
|
||||||
|
from time import time
|
||||||
|
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
from mininet.node import Node
|
from mininet.node import Node
|
||||||
from mininet.topo import SingleSwitchTopo
|
from mininet.topo import SingleSwitchTopo
|
||||||
from mininet.log import info, setLogLevel
|
from mininet.log import info, setLogLevel
|
||||||
|
|
||||||
from select import poll, POLLIN
|
|
||||||
from time import time
|
|
||||||
|
|
||||||
def chunks( l, n ):
|
def chunks( l, n ):
|
||||||
"Divide list l into chunks of size n - thanks Stackoverflow"
|
"Divide list l into chunks of size n - thanks Stackoverflow"
|
||||||
@@ -59,7 +59,7 @@ def multiping( netsize, chunksize, seconds):
|
|||||||
# Start pings
|
# Start pings
|
||||||
for subnet in subnets:
|
for subnet in subnets:
|
||||||
ips = [ host.IP() for host in subnet ]
|
ips = [ host.IP() for host in subnet ]
|
||||||
#adding bogus to generate packet loss
|
# adding bogus to generate packet loss
|
||||||
ips.append( '10.0.0.200' )
|
ips.append( '10.0.0.200' )
|
||||||
for host in subnet:
|
for host in subnet:
|
||||||
startpings( host, ips )
|
startpings( host, ips )
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ monitoring them
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
from select import poll, POLLIN
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
from mininet.topo import SingleSwitchTopo
|
from mininet.topo import SingleSwitchTopo
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
from mininet.log import info, setLogLevel
|
from mininet.log import info, setLogLevel
|
||||||
from mininet.util import decode
|
from mininet.util import decode
|
||||||
|
|
||||||
from time import time
|
|
||||||
from select import poll, POLLIN
|
|
||||||
from subprocess import Popen, PIPE
|
|
||||||
|
|
||||||
|
|
||||||
def monitorFiles( outfiles, seconds, timeoutms ):
|
def monitorFiles( outfiles, seconds, timeoutms ):
|
||||||
"Monitor set of files and return [(host, line)...]"
|
"Monitor set of files and return [(host, line)...]"
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ def ifconfigTest( net ):
|
|||||||
for host in hosts:
|
for host in hosts:
|
||||||
info( host.cmd( 'ifconfig' ) )
|
info( host.cmd( 'ifconfig' ) )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
lg.setLogLevel( 'info' )
|
lg.setLogLevel( 'info' )
|
||||||
info( "*** Initializing Mininet and kernel modules\n" )
|
info( "*** Initializing Mininet and kernel modules\n" )
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ from mininet.util import irange
|
|||||||
|
|
||||||
class InternetTopo(Topo):
|
class InternetTopo(Topo):
|
||||||
"Single switch connected to n hosts."
|
"Single switch connected to n hosts."
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def build(self, n=2, **_kwargs ):
|
def build(self, n=2, **_kwargs ):
|
||||||
# set up inet switch
|
# set up inet switch
|
||||||
inetSwitch = self.addSwitch('s0')
|
inetSwitch = self.addSwitch('s0')
|
||||||
@@ -62,6 +63,7 @@ def run():
|
|||||||
CLI(net)
|
CLI(net)
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel('info')
|
setLogLevel('info')
|
||||||
run()
|
run()
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ def testPortNumbering():
|
|||||||
info( '*** Stopping network\n' )
|
info( '*** Stopping network\n' )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
testPortNumbering()
|
testPortNumbering()
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ def monitorhosts( hosts=5 ):
|
|||||||
# Done
|
# Done
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
monitorhosts( hosts=5 )
|
monitorhosts( hosts=5 )
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
"Monitor multiple hosts using popen()/pmonitor()"
|
"Monitor multiple hosts using popen()/pmonitor()"
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
from signal import SIGINT
|
||||||
|
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
from mininet.topo import SingleSwitchTopo
|
from mininet.topo import SingleSwitchTopo
|
||||||
from mininet.util import pmonitor
|
from mininet.util import pmonitor
|
||||||
from mininet.log import setLogLevel, info
|
from mininet.log import setLogLevel, info
|
||||||
|
|
||||||
from time import time
|
|
||||||
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"
|
||||||
@@ -31,6 +32,7 @@ def pmonitorTest( N=3, seconds=10 ):
|
|||||||
p.send_signal( SIGINT )
|
p.send_signal( SIGINT )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
pmonitorTest()
|
pmonitorTest()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ but it exposes the configuration details and allows customization.
|
|||||||
For most tasks, the higher-level API will be preferable.
|
For most tasks, the higher-level API will be preferable.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
from mininet.node import Node
|
from mininet.node import Node
|
||||||
@@ -15,7 +16,6 @@ from mininet.link import Link
|
|||||||
from mininet.log import setLogLevel, info
|
from mininet.log import setLogLevel, info
|
||||||
from mininet.util import quietRun
|
from mininet.util import quietRun
|
||||||
|
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
def scratchNet( cname='controller', cargs='-v ptcp:' ):
|
def scratchNet( cname='controller', cargs='-v ptcp:' ):
|
||||||
"Create network from scratch using Open vSwitch."
|
"Create network from scratch using Open vSwitch."
|
||||||
@@ -62,6 +62,7 @@ def scratchNet( cname='controller', cargs='-v ptcp:' ):
|
|||||||
switch.deleteIntfs()
|
switch.deleteIntfs()
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
info( '*** Scratch network demo (kernel datapath)\n' )
|
info( '*** Scratch network demo (kernel datapath)\n' )
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ def scratchNetUser( cname='controller', cargs='ptcp:' ):
|
|||||||
switch.deleteIntfs()
|
switch.deleteIntfs()
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
info( '*** Scratch network demo (user datapath)\n' )
|
info( '*** Scratch network demo (user datapath)\n' )
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ iperf will hang indefinitely if the TCP handshake fails
|
|||||||
to complete.
|
to complete.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
from mininet.topo import Topo
|
from mininet.topo import Topo
|
||||||
from mininet.net import Mininet
|
from mininet.net import Mininet
|
||||||
@@ -17,7 +18,6 @@ from mininet.link import TCLink
|
|||||||
from mininet.util import dumpNodeConnections
|
from mininet.util import dumpNodeConnections
|
||||||
from mininet.log import setLogLevel, info
|
from mininet.log import setLogLevel, info
|
||||||
|
|
||||||
from sys import argv
|
|
||||||
|
|
||||||
# It would be nice if we didn't have to do this:
|
# It would be nice if we didn't have to do this:
|
||||||
# pylint: disable=arguments-differ
|
# pylint: disable=arguments-differ
|
||||||
@@ -54,6 +54,7 @@ def perfTest( lossy=True ):
|
|||||||
net.iperf( ( h1, h4 ), l4Type='UDP' )
|
net.iperf( ( h1, h4 ), l4Type='UDP' )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
# Prevent test_simpleperf from failing due to packet loss
|
# Prevent test_simpleperf from failing due to packet loss
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ def connectToRootNS( network, switch, ip, routes ):
|
|||||||
for route in routes:
|
for route in routes:
|
||||||
root.cmd( 'route add -net ' + route + ' dev ' + str( intf ) )
|
root.cmd( 'route add -net ' + route + ' dev ' + str( intf ) )
|
||||||
|
|
||||||
|
# pylint: disable=too-many-arguments
|
||||||
def sshd( network, cmd='/usr/sbin/sshd', opts='-D',
|
def sshd( network, cmd='/usr/sbin/sshd', opts='-D',
|
||||||
ip='10.123.123.1/32', routes=None, switch=None ):
|
ip='10.123.123.1/32', routes=None, switch=None ):
|
||||||
"""Start a network, connect it to root ns, and run sshd on all hosts.
|
"""Start a network, connect it to root ns, and run sshd on all hosts.
|
||||||
@@ -73,6 +74,7 @@ def sshd( network, cmd='/usr/sbin/sshd', opts='-D',
|
|||||||
host.cmd( 'kill %' + cmd )
|
host.cmd( 'kill %' + cmd )
|
||||||
network.stop()
|
network.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
lg.setLogLevel( 'info')
|
lg.setLogLevel( 'info')
|
||||||
net = TreeNet( depth=1, fanout=4 )
|
net = TreeNet( depth=1, fanout=4 )
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ def treePing64():
|
|||||||
info( "%s: %d%% packet loss\n" % ( name, results[ name ] ) )
|
info( "%s: %d%% packet loss\n" % ( name, results[ name ] ) )
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'info' )
|
setLogLevel( 'info' )
|
||||||
treePing64()
|
treePing64()
|
||||||
|
|||||||
@@ -24,14 +24,18 @@ Usage (example uses VLAN ID=1000):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from mininet.node import Host
|
from mininet.node import Host
|
||||||
from mininet.topo import Topo
|
from mininet.topo import Topo
|
||||||
from mininet.util import quietRun
|
from mininet.util import quietRun
|
||||||
from mininet.log import error
|
from mininet.log import error
|
||||||
|
|
||||||
|
|
||||||
class VLANHost( Host ):
|
class VLANHost( Host ):
|
||||||
"Host connected to VLAN interface"
|
"Host connected to VLAN interface"
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def config( self, vlan=100, **params ):
|
def config( self, vlan=100, **params ):
|
||||||
"""Configure VLANHost according to (optional) parameters:
|
"""Configure VLANHost according to (optional) parameters:
|
||||||
vlan: VLAN ID for default interface"""
|
vlan: VLAN ID for default interface"""
|
||||||
@@ -54,6 +58,7 @@ class VLANHost( Host ):
|
|||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
hosts = { 'vlan': VLANHost }
|
hosts = { 'vlan': VLANHost }
|
||||||
|
|
||||||
|
|
||||||
@@ -101,6 +106,7 @@ def exampleCustomTags():
|
|||||||
CLI( net )
|
CLI( net )
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|||||||
+8
-5
@@ -47,7 +47,7 @@ class CLI( Cmd ):
|
|||||||
prompt = 'mininet> '
|
prompt = 'mininet> '
|
||||||
|
|
||||||
def __init__( self, mininet, stdin=sys.stdin, script=None,
|
def __init__( self, mininet, stdin=sys.stdin, script=None,
|
||||||
*args, **kwargs ):
|
**kwargs ):
|
||||||
"""Start and run interactive or batch mode CLI
|
"""Start and run interactive or batch mode CLI
|
||||||
mininet: Mininet network object
|
mininet: Mininet network object
|
||||||
stdin: standard input for CLI
|
stdin: standard input for CLI
|
||||||
@@ -59,7 +59,7 @@ class CLI( Cmd ):
|
|||||||
self.inPoller = poll()
|
self.inPoller = poll()
|
||||||
self.inPoller.register( stdin )
|
self.inPoller.register( stdin )
|
||||||
self.inputFile = script
|
self.inputFile = script
|
||||||
Cmd.__init__( self, *args, stdin=stdin, **kwargs )
|
Cmd.__init__( self, stdin=stdin, **kwargs )
|
||||||
info( '*** Starting CLI:\n' )
|
info( '*** Starting CLI:\n' )
|
||||||
|
|
||||||
if self.inputFile:
|
if self.inputFile:
|
||||||
@@ -79,6 +79,7 @@ class CLI( Cmd ):
|
|||||||
return
|
return
|
||||||
cls.readlineInited = True
|
cls.readlineInited = True
|
||||||
try:
|
try:
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
from readline import ( read_history_file, write_history_file,
|
from readline import ( read_history_file, write_history_file,
|
||||||
set_history_length )
|
set_history_length )
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -141,7 +142,7 @@ class CLI( Cmd ):
|
|||||||
' mininet> xterm h2\n\n'
|
' mininet> xterm h2\n\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
def do_help( self, line ):
|
def do_help( self, line ): # pylint: disable=arguments-differ
|
||||||
"Describe available CLI commands."
|
"Describe available CLI commands."
|
||||||
Cmd.do_help( self, line )
|
Cmd.do_help( self, line )
|
||||||
if line == '':
|
if line == '':
|
||||||
@@ -173,6 +174,7 @@ class CLI( Cmd ):
|
|||||||
"""Evaluate a Python expression.
|
"""Evaluate a Python expression.
|
||||||
Node names may be used, e.g.: py h1.cmd('ls')"""
|
Node names may be used, e.g.: py h1.cmd('ls')"""
|
||||||
try:
|
try:
|
||||||
|
# pylint: disable=eval-used
|
||||||
result = eval( line, globals(), self.getLocals() )
|
result = eval( line, globals(), self.getLocals() )
|
||||||
if not result:
|
if not result:
|
||||||
return
|
return
|
||||||
@@ -467,10 +469,10 @@ class CLI( Cmd ):
|
|||||||
node.sendInt()
|
node.sendInt()
|
||||||
except select.error as e:
|
except select.error as e:
|
||||||
# pylint: disable=unpacking-non-sequence
|
# pylint: disable=unpacking-non-sequence
|
||||||
|
# pylint: disable=unbalanced-tuple-unpacking
|
||||||
errno_, errmsg = e.args
|
errno_, errmsg = e.args
|
||||||
# pylint: enable=unpacking-non-sequence
|
|
||||||
if errno_ != errno.EINTR:
|
if errno_ != errno.EINTR:
|
||||||
error( "select.error: %d, %s" % (errno_, errmsg) )
|
error( "select.error: %s, %s" % (errno_, errmsg) )
|
||||||
node.sendInt()
|
node.sendInt()
|
||||||
|
|
||||||
def precmd( self, line ):
|
def precmd( self, line ):
|
||||||
@@ -488,3 +490,4 @@ def isReadable( poller ):
|
|||||||
mask = fdmask[ 1 ]
|
mask = fdmask[ 1 ]
|
||||||
if mask & POLLIN:
|
if mask & POLLIN:
|
||||||
return True
|
return True
|
||||||
|
return False
|
||||||
|
|||||||
+14
-3
@@ -24,9 +24,14 @@ TCIntf: interface with bandwidth limiting and delay via tc
|
|||||||
Link: basic link class for creating veth pairs
|
Link: basic link class for creating veth pairs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
from mininet.log import info, error, debug
|
from mininet.log import info, error, debug
|
||||||
from mininet.util import makeIntfPair
|
from mininet.util import makeIntfPair
|
||||||
import re
|
|
||||||
|
# Make pylint happy:
|
||||||
|
# pylint: disable=too-many-arguments
|
||||||
|
|
||||||
|
|
||||||
class Intf( object ):
|
class Intf( object ):
|
||||||
|
|
||||||
@@ -170,7 +175,7 @@ class Intf( object ):
|
|||||||
name, value = list( param.items() )[ 0 ]
|
name, value = list( param.items() )[ 0 ]
|
||||||
f = getattr( self, method, None )
|
f = getattr( self, method, None )
|
||||||
if not f or value is None:
|
if not f or value is None:
|
||||||
return
|
return None
|
||||||
if isinstance( value, list ):
|
if isinstance( value, list ):
|
||||||
result = f( *value )
|
result = f( *value )
|
||||||
elif isinstance( value, dict ):
|
elif isinstance( value, dict ):
|
||||||
@@ -311,6 +316,7 @@ class TCIntf( Intf ):
|
|||||||
debug(" *** executing command: %s\n" % c)
|
debug(" *** executing command: %s\n" % c)
|
||||||
return self.cmd( c )
|
return self.cmd( c )
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def config( self, bw=None, delay=None, jitter=None, loss=None,
|
def config( self, bw=None, delay=None, jitter=None, loss=None,
|
||||||
gro=False, txo=True, rxo=True,
|
gro=False, txo=True, rxo=True,
|
||||||
speedup=0, use_hfsc=False, use_tbf=False,
|
speedup=0, use_hfsc=False, use_tbf=False,
|
||||||
@@ -351,7 +357,7 @@ class TCIntf( Intf ):
|
|||||||
# Question: what happens if we want to reset things?
|
# Question: what happens if we want to reset things?
|
||||||
if ( bw is None and not delay and not loss
|
if ( bw is None and not delay and not loss
|
||||||
and max_queue_size is None ):
|
and max_queue_size is None ):
|
||||||
return
|
return None
|
||||||
|
|
||||||
# Clear existing configuration
|
# Clear existing configuration
|
||||||
tcoutput = self.tc( '%s qdisc show dev %s' )
|
tcoutput = self.tc( '%s qdisc show dev %s' )
|
||||||
@@ -533,6 +539,10 @@ class OVSLink( Link ):
|
|||||||
|
|
||||||
def __init__( self, node1, node2, **kwargs ):
|
def __init__( self, node1, node2, **kwargs ):
|
||||||
"See Link.__init__() for options"
|
"See Link.__init__() for options"
|
||||||
|
try:
|
||||||
|
OVSSwitch
|
||||||
|
except NameError:
|
||||||
|
# pylint: disable=import-outside-toplevel,cyclic-import
|
||||||
from mininet.node import OVSSwitch
|
from mininet.node import OVSSwitch
|
||||||
self.isPatchLink = False
|
self.isPatchLink = False
|
||||||
if ( isinstance( node1, OVSSwitch ) and
|
if ( isinstance( node1, OVSSwitch ) and
|
||||||
@@ -541,6 +551,7 @@ class OVSLink( Link ):
|
|||||||
kwargs.update( cls1=OVSIntf, cls2=OVSIntf )
|
kwargs.update( cls1=OVSIntf, cls2=OVSIntf )
|
||||||
Link.__init__( self, node1, node2, **kwargs )
|
Link.__init__( self, node1, node2, **kwargs )
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ, signature-differs
|
||||||
def makeIntfPair( self, *args, **kwargs ):
|
def makeIntfPair( self, *args, **kwargs ):
|
||||||
"Usually delegated to OVSSwitch"
|
"Usually delegated to OVSSwitch"
|
||||||
if self.isPatchLink:
|
if self.isPatchLink:
|
||||||
|
|||||||
+5
-3
@@ -20,7 +20,7 @@ LEVELS = { 'debug': logging.DEBUG,
|
|||||||
# change this to logging.INFO to get printouts when running unit tests
|
# change this to logging.INFO to get printouts when running unit tests
|
||||||
LOGLEVELDEFAULT = OUTPUT
|
LOGLEVELDEFAULT = OUTPUT
|
||||||
|
|
||||||
#default: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
# default: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
LOGMSGFORMAT = '%(message)s'
|
LOGMSGFORMAT = '%(message)s'
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ class StreamHandlerNoNewline( logging.StreamHandler ):
|
|||||||
self.flush()
|
self.flush()
|
||||||
except ( KeyboardInterrupt, SystemExit ):
|
except ( KeyboardInterrupt, SystemExit ):
|
||||||
raise
|
raise
|
||||||
except:
|
except: # noqa pylint: disable=bare-except
|
||||||
self.handleError( record )
|
self.handleError( record )
|
||||||
|
|
||||||
|
|
||||||
@@ -137,13 +137,14 @@ class MininetLogger( Logger, object ):
|
|||||||
|
|
||||||
logger.warning("Houston, we have a %s", "cli output", exc_info=1)
|
logger.warning("Houston, we have a %s", "cli output", exc_info=1)
|
||||||
"""
|
"""
|
||||||
if self.manager.disable >= OUTPUT:
|
if getattr( self.manager, 'disabled', 0 ) >= OUTPUT:
|
||||||
return
|
return
|
||||||
if self.isEnabledFor( OUTPUT ):
|
if self.isEnabledFor( OUTPUT ):
|
||||||
self._log( OUTPUT, msg, args, kwargs )
|
self._log( OUTPUT, msg, args, kwargs )
|
||||||
|
|
||||||
# pylint: enable=method-hidden
|
# pylint: enable=method-hidden
|
||||||
|
|
||||||
|
|
||||||
lg = MininetLogger()
|
lg = MininetLogger()
|
||||||
|
|
||||||
# Make things a bit more convenient by adding aliases
|
# Make things a bit more convenient by adding aliases
|
||||||
@@ -168,6 +169,7 @@ def makeListCompatible( fn ):
|
|||||||
setattr( newfn, '__doc__', fn.__doc__ )
|
setattr( newfn, '__doc__', fn.__doc__ )
|
||||||
return newfn
|
return newfn
|
||||||
|
|
||||||
|
|
||||||
_loggers = lg.info, lg.output, lg.warn, lg.error, lg.debug
|
_loggers = lg.info, lg.output, lg.warn, lg.error, lg.debug
|
||||||
_loggers = tuple( makeListCompatible( logger )
|
_loggers = tuple( makeListCompatible( logger )
|
||||||
for logger in _loggers )
|
for logger in _loggers )
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
"Module dependency utility functions for Mininet."
|
"Module dependency utility functions for Mininet."
|
||||||
|
|
||||||
|
from os import environ
|
||||||
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from mininet.util import quietRun, BaseString
|
from mininet.util import quietRun, BaseString
|
||||||
from mininet.log import info, error, debug
|
from mininet.log import info, error, debug
|
||||||
from os import environ
|
|
||||||
|
|
||||||
def lsmod():
|
def lsmod():
|
||||||
"Return output of lsmod."
|
"Return output of lsmod."
|
||||||
@@ -18,6 +21,7 @@ def modprobe( mod ):
|
|||||||
mod: module string"""
|
mod: module string"""
|
||||||
return quietRun( [ 'modprobe', mod ] )
|
return quietRun( [ 'modprobe', mod ] )
|
||||||
|
|
||||||
|
|
||||||
OF_KMOD = 'ofdatapath'
|
OF_KMOD = 'ofdatapath'
|
||||||
OVS_KMOD = 'openvswitch_mod' # Renamed 'openvswitch' in OVS 1.7+/Linux 3.5+
|
OVS_KMOD = 'openvswitch_mod' # Renamed 'openvswitch' in OVS 1.7+/Linux 3.5+
|
||||||
TUN = 'tun'
|
TUN = 'tun'
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ import select
|
|||||||
import signal
|
import signal
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from itertools import chain, groupby
|
from itertools import chain, groupby
|
||||||
from math import ceil
|
from math import ceil
|
||||||
@@ -113,6 +114,7 @@ VERSION = "2.3.0a1"
|
|||||||
class Mininet( object ):
|
class Mininet( object ):
|
||||||
"Network emulation with hosts spawned in network namespaces."
|
"Network emulation with hosts spawned in network namespaces."
|
||||||
|
|
||||||
|
# pylint: disable=too-many-arguments
|
||||||
def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
|
def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
|
||||||
controller=DefaultController, link=Link, intf=Intf,
|
controller=DefaultController, link=Link, intf=Intf,
|
||||||
build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8',
|
build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8',
|
||||||
|
|||||||
+34
-14
@@ -57,7 +57,10 @@ import pty
|
|||||||
import re
|
import re
|
||||||
import signal
|
import signal
|
||||||
import select
|
import select
|
||||||
|
from distutils.version import StrictVersion
|
||||||
|
from re import findall
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from mininet.log import info, error, warn, debug
|
from mininet.log import info, error, warn, debug
|
||||||
@@ -66,8 +69,10 @@ from mininet.util import ( quietRun, errRun, errFail, moveIntf, isShellBuiltin,
|
|||||||
encode, getincrementaldecoder, Python3, which )
|
encode, getincrementaldecoder, Python3, which )
|
||||||
from mininet.moduledeps import moduleDeps, pathCheck, TUN
|
from mininet.moduledeps import moduleDeps, pathCheck, TUN
|
||||||
from mininet.link import Link, Intf, TCIntf, OVSIntf
|
from mininet.link import Link, Intf, TCIntf, OVSIntf
|
||||||
from re import findall
|
|
||||||
from distutils.version import StrictVersion
|
|
||||||
|
# pylint: disable=too-many-arguments
|
||||||
|
|
||||||
|
|
||||||
class Node( object ):
|
class Node( object ):
|
||||||
"""A virtual network node is simply a shell in a network namespace.
|
"""A virtual network node is simply a shell in a network namespace.
|
||||||
@@ -94,9 +99,13 @@ class Node( object ):
|
|||||||
# Stash configuration parameters for future reference
|
# Stash configuration parameters for future reference
|
||||||
self.params = params
|
self.params = params
|
||||||
|
|
||||||
self.intfs = {} # dict of port numbers to interfaces
|
# dict of port numbers to interfacse
|
||||||
self.ports = {} # dict of interfaces to port numbers
|
self.intfs = {}
|
||||||
# replace with Port objects, eventually ?
|
|
||||||
|
# dict of interfaces to port numbers
|
||||||
|
# todo: replace with Port objects, eventually ?
|
||||||
|
self.ports = {}
|
||||||
|
|
||||||
self.nameToIntf = {} # dict of interface names to Intfs
|
self.nameToIntf = {} # dict of interface names to Intfs
|
||||||
|
|
||||||
# Make pylint happy
|
# Make pylint happy
|
||||||
@@ -284,6 +293,7 @@ class Node( object ):
|
|||||||
returns: result of poll()"""
|
returns: result of poll()"""
|
||||||
if len( self.readbuf ) == 0:
|
if len( self.readbuf ) == 0:
|
||||||
return self.pollOut.poll( timeoutms )
|
return self.pollOut.poll( timeoutms )
|
||||||
|
return None
|
||||||
|
|
||||||
def sendCmd( self, *args, **kwargs ):
|
def sendCmd( self, *args, **kwargs ):
|
||||||
"""Send a command, followed by a command to echo a sentinel,
|
"""Send a command, followed by a command to echo a sentinel,
|
||||||
@@ -377,6 +387,7 @@ class Node( object ):
|
|||||||
return self.waitOutput( verbose )
|
return self.waitOutput( verbose )
|
||||||
else:
|
else:
|
||||||
warn( '(%s exited - ignoring cmd%s)\n' % ( self, args ) )
|
warn( '(%s exited - ignoring cmd%s)\n' % ( self, args ) )
|
||||||
|
return None
|
||||||
|
|
||||||
def cmdPrint( self, *args):
|
def cmdPrint( self, *args):
|
||||||
"""Call cmd and printing its output
|
"""Call cmd and printing its output
|
||||||
@@ -469,6 +480,7 @@ class Node( object ):
|
|||||||
else:
|
else:
|
||||||
warn( '*** defaultIntf: warning:', self.name,
|
warn( '*** defaultIntf: warning:', self.name,
|
||||||
'has no interfaces\n' )
|
'has no interfaces\n' )
|
||||||
|
return None
|
||||||
|
|
||||||
def intf( self, intf=None ):
|
def intf( self, intf=None ):
|
||||||
"""Return our interface object with given string name,
|
"""Return our interface object with given string name,
|
||||||
@@ -582,10 +594,10 @@ class Node( object ):
|
|||||||
value may also be list or dict"""
|
value may also be list or dict"""
|
||||||
name, value = list( param.items() )[ 0 ]
|
name, value = list( param.items() )[ 0 ]
|
||||||
if value is None:
|
if value is None:
|
||||||
return
|
return None
|
||||||
f = getattr( self, method, None )
|
f = getattr( self, method, None )
|
||||||
if not f:
|
if not f:
|
||||||
return
|
return None
|
||||||
if isinstance( value, list ):
|
if isinstance( value, list ):
|
||||||
result = f( *value )
|
result = f( *value )
|
||||||
elif isinstance( value, dict ):
|
elif isinstance( value, dict ):
|
||||||
@@ -653,11 +665,12 @@ class Node( object ):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def checkSetup( cls ):
|
def checkSetup( cls ):
|
||||||
"Make sure our class and superclasses are set up"
|
"Make sure our class and superclasses are set up"
|
||||||
while cls and not getattr( cls, 'isSetup', True ):
|
clas = cls
|
||||||
cls.setup()
|
while clas and not getattr( clas, 'isSetup', True ):
|
||||||
cls.isSetup = True
|
clas.setup()
|
||||||
|
clas.isSetup = True
|
||||||
# Make pylint happy
|
# Make pylint happy
|
||||||
cls = getattr( type( cls ), '__base__', None )
|
clas = getattr( type( clas ), '__base__', None )
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup( cls ):
|
def setup( cls ):
|
||||||
@@ -838,6 +851,7 @@ class CPULimitedHost( Host ):
|
|||||||
errFail( 'cgclassify -g cpuset:/%s %s' % (
|
errFail( 'cgclassify -g cpuset:/%s %s' % (
|
||||||
self.name, self.pid ) )
|
self.name, self.pid ) )
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def config( self, cpu=-1, cores=None, **params ):
|
def config( self, cpu=-1, cores=None, **params ):
|
||||||
"""cpu: desired overall system CPU fraction
|
"""cpu: desired overall system CPU fraction
|
||||||
cores: (real) core(s) this host can run on
|
cores: (real) core(s) this host can run on
|
||||||
@@ -930,6 +944,7 @@ class Switch( Node ):
|
|||||||
else:
|
else:
|
||||||
error( '*** Error: %s has execed and cannot accept commands' %
|
error( '*** Error: %s has execed and cannot accept commands' %
|
||||||
self.name )
|
self.name )
|
||||||
|
return None
|
||||||
|
|
||||||
def connected( self ):
|
def connected( self ):
|
||||||
"Is the switch connected to a controller? (override this method)"
|
"Is the switch connected to a controller? (override this method)"
|
||||||
@@ -1115,6 +1130,7 @@ class OVSSwitch( Switch ):
|
|||||||
if self.batch:
|
if self.batch:
|
||||||
cmd = ' '.join( str( arg ).strip() for arg in args )
|
cmd = ' '.join( str( arg ).strip() for arg in args )
|
||||||
self.commands.append( cmd )
|
self.commands.append( cmd )
|
||||||
|
return None
|
||||||
else:
|
else:
|
||||||
return self.cmd( 'ovs-vsctl', *args, **kwargs )
|
return self.cmd( 'ovs-vsctl', *args, **kwargs )
|
||||||
|
|
||||||
@@ -1302,7 +1318,7 @@ class OVSBridge( OVSSwitch ):
|
|||||||
"Are we forwarding yet?"
|
"Are we forwarding yet?"
|
||||||
if self.stp:
|
if self.stp:
|
||||||
status = self.dpctl( 'show' )
|
status = self.dpctl( 'show' )
|
||||||
return 'STP_FORWARD' in status and not 'STP_LEARN' in status
|
return 'STP_FORWARD' in status and 'STP_LEARN' not in status
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -1429,6 +1445,7 @@ class Controller( Node ):
|
|||||||
' 1>' + cout + ' 2>' + cout + ' &' )
|
' 1>' + cout + ' 2>' + cout + ' &' )
|
||||||
self.execed = False
|
self.execed = False
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ,signature-differs
|
||||||
def stop( self, *args, **kwargs ):
|
def stop( self, *args, **kwargs ):
|
||||||
"Stop controller."
|
"Stop controller."
|
||||||
self.cmd( 'kill %' + self.command )
|
self.cmd( 'kill %' + self.command )
|
||||||
@@ -1479,7 +1496,7 @@ class NOX( Controller ):
|
|||||||
warn( 'warning: no NOX modules specified; '
|
warn( 'warning: no NOX modules specified; '
|
||||||
'running packetdump only\n' )
|
'running packetdump only\n' )
|
||||||
noxArgs = [ 'packetdump' ]
|
noxArgs = [ 'packetdump' ]
|
||||||
elif type( noxArgs ) not in ( list, tuple ):
|
elif not isinstance( noxArgs, ( list, tuple ) ):
|
||||||
noxArgs = [ noxArgs ]
|
noxArgs = [ noxArgs ]
|
||||||
|
|
||||||
if 'NOX_CORE_DIR' not in os.environ:
|
if 'NOX_CORE_DIR' not in os.environ:
|
||||||
@@ -1505,7 +1522,7 @@ class Ryu( Controller ):
|
|||||||
warn( 'warning: no Ryu modules specified; '
|
warn( 'warning: no Ryu modules specified; '
|
||||||
'running simple_switch only\n' )
|
'running simple_switch only\n' )
|
||||||
ryuArgs = [ ryuCoreDir + 'simple_switch.py' ]
|
ryuArgs = [ ryuCoreDir + 'simple_switch.py' ]
|
||||||
elif type( ryuArgs ) not in ( list, tuple ):
|
elif not isinstance( ryuArgs, ( list, tuple ) ):
|
||||||
ryuArgs = [ ryuArgs ]
|
ryuArgs = [ ryuArgs ]
|
||||||
|
|
||||||
Controller.__init__( self, name,
|
Controller.__init__( self, name,
|
||||||
@@ -1532,6 +1549,7 @@ class RemoteController( Controller ):
|
|||||||
"Overridden to do nothing."
|
"Overridden to do nothing."
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def stop( self ):
|
def stop( self ):
|
||||||
"Overridden to do nothing."
|
"Overridden to do nothing."
|
||||||
return
|
return
|
||||||
@@ -1563,6 +1581,7 @@ class RemoteController( Controller ):
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
DefaultControllers = ( Controller, OVSController )
|
DefaultControllers = ( Controller, OVSController )
|
||||||
|
|
||||||
def findController( controllers=DefaultControllers ):
|
def findController( controllers=DefaultControllers ):
|
||||||
@@ -1570,6 +1589,7 @@ def findController( controllers=DefaultControllers ):
|
|||||||
for controller in controllers:
|
for controller in controllers:
|
||||||
if controller.isAvailable():
|
if controller.isAvailable():
|
||||||
return controller
|
return controller
|
||||||
|
return None
|
||||||
|
|
||||||
def DefaultController( name, controllers=DefaultControllers, **kwargs ):
|
def DefaultController( name, controllers=DefaultControllers, **kwargs ):
|
||||||
"Find a controller that is available and instantiate it"
|
"Find a controller that is available and instantiate it"
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ class NAT( Node ):
|
|||||||
# hopefully this won't disconnect you
|
# hopefully this won't disconnect you
|
||||||
self.cmd( 'service network-manager restart || netplan apply' )
|
self.cmd( 'service network-manager restart || netplan apply' )
|
||||||
|
|
||||||
|
# pylint: disable=arguments-differ
|
||||||
def config( self, **params ):
|
def config( self, **params ):
|
||||||
"""Configure the NAT and iptables"""
|
"""Configure the NAT and iptables"""
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ def makeTerm( node, title='Node', term='xterm', display=None, cmd='bash'):
|
|||||||
}
|
}
|
||||||
if term not in cmds:
|
if term not in cmds:
|
||||||
error( 'invalid terminal type: %s' % term )
|
error( 'invalid terminal type: %s' % term )
|
||||||
return
|
return None
|
||||||
display, tunnel = tunnelX11( node, display )
|
display, tunnel = tunnelX11( node, display )
|
||||||
if display is None:
|
if display is None:
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ def runTests( testDir, verbosity=1 ):
|
|||||||
.run( testSuite ).wasSuccessful() )
|
.run( testSuite ).wasSuccessful() )
|
||||||
sys.exit( 0 if success else 1 )
|
sys.exit( 0 if success else 1 )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'warning' )
|
setLogLevel( 'warning' )
|
||||||
# get the directory containing example tests
|
# get the directory containing example tests
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class testOptionsTopoCommon( object ):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def tearDown():
|
def tearDown():
|
||||||
"Clean up if necessary"
|
"Clean up if necessary"
|
||||||
if sys.exc_info != ( None, None, None ):
|
if sys.exc_info() != ( None, None, None ):
|
||||||
cleanup()
|
cleanup()
|
||||||
|
|
||||||
def runOptionsTopoTest( self, n, msg, hopts=None, lopts=None ):
|
def runOptionsTopoTest( self, n, msg, hopts=None, lopts=None ):
|
||||||
@@ -95,7 +95,7 @@ class testOptionsTopoCommon( object ):
|
|||||||
CPU_FRACTION = 0.1
|
CPU_FRACTION = 0.1
|
||||||
CPU_TOLERANCE = 0.8 # CPU fraction below which test should fail
|
CPU_TOLERANCE = 0.8 # CPU fraction below which test should fail
|
||||||
hopts = { 'cpu': CPU_FRACTION }
|
hopts = { 'cpu': CPU_FRACTION }
|
||||||
#self.runOptionsTopoTest( N, hopts=hopts )
|
# self.runOptionsTopoTest( N, hopts=hopts )
|
||||||
|
|
||||||
mn = Mininet( SingleSwitchOptionsTopo( n=N, hopts=hopts ),
|
mn = Mininet( SingleSwitchOptionsTopo( n=N, hopts=hopts ),
|
||||||
host=CPULimitedHost, switch=self.switchClass,
|
host=CPULimitedHost, switch=self.switchClass,
|
||||||
@@ -118,7 +118,7 @@ class testOptionsTopoCommon( object ):
|
|||||||
% ( CPU_FRACTION * 100, hostUsage, N, hoptsStr,
|
% ( CPU_FRACTION * 100, hostUsage, N, hoptsStr,
|
||||||
self.switchClass ) )
|
self.switchClass ) )
|
||||||
for pct in results:
|
for pct in results:
|
||||||
#divide cpu by 100 to convert from percentage to fraction
|
# divide cpu by 100 to convert from percentage to fraction
|
||||||
self.assertWithinTolerance( pct/100, CPU_FRACTION,
|
self.assertWithinTolerance( pct/100, CPU_FRACTION,
|
||||||
CPU_TOLERANCE, msg )
|
CPU_TOLERANCE, msg )
|
||||||
|
|
||||||
@@ -263,6 +263,7 @@ class testOptionsTopoUserspace( testOptionsTopoCommon, unittest.TestCase ):
|
|||||||
longMessage = True
|
longMessage = True
|
||||||
switchClass = UserSwitch
|
switchClass = UserSwitch
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'warning' )
|
setLogLevel( 'warning' )
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class testSingleSwitchCommon( object ):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def tearDown():
|
def tearDown():
|
||||||
"Clean up if necessary"
|
"Clean up if necessary"
|
||||||
if sys.exc_info != ( None, None, None ):
|
if sys.exc_info() != ( None, None, None ):
|
||||||
cleanup()
|
cleanup()
|
||||||
|
|
||||||
def testMinimal( self ):
|
def testMinimal( self ):
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class TestPtyLeak( unittest.TestCase ):
|
|||||||
assert ( host.slave, host.master ) == oldptys
|
assert ( host.slave, host.master ) == oldptys
|
||||||
net.stop()
|
net.stop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
cleanup()
|
cleanup()
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class TestSwitchDpidAssignmentOVS( unittest.TestCase ):
|
|||||||
"Clean up if necessary"
|
"Clean up if necessary"
|
||||||
# satisfy pylint
|
# satisfy pylint
|
||||||
assert self
|
assert self
|
||||||
if sys.exc_info != ( None, None, None ):
|
if sys.exc_info() != ( None, None, None ):
|
||||||
cleanup()
|
cleanup()
|
||||||
|
|
||||||
def testDefaultDpid( self ):
|
def testDefaultDpid( self ):
|
||||||
@@ -95,6 +95,7 @@ class testSwitchUserspace( TestSwitchDpidAssignmentOVS ):
|
|||||||
"Test dpid assignment of Userspace switch."
|
"Test dpid assignment of Userspace switch."
|
||||||
switchClass = UserSwitch
|
switchClass = UserSwitch
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setLogLevel( 'warning' )
|
setLogLevel( 'warning' )
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -35,5 +35,6 @@ class testQuietRun( unittest.TestCase ):
|
|||||||
output = quietRun(testQuietRun.getEchoCmd( n ) )
|
output = quietRun(testQuietRun.getEchoCmd( n ) )
|
||||||
self.assertEqual( n, len( output ) )
|
self.assertEqual( n, len( output ) )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -6,14 +6,16 @@ Tests for the Mininet Walkthrough
|
|||||||
TODO: missing xterm test
|
TODO: missing xterm test
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import unittest
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from mininet.util import quietRun, pexpect
|
import unittest
|
||||||
from mininet.clean import cleanup
|
|
||||||
from distutils.version import StrictVersion
|
from distutils.version import StrictVersion
|
||||||
from sys import stdout
|
from sys import stdout
|
||||||
|
|
||||||
|
from mininet.util import quietRun, pexpect
|
||||||
|
from mininet.clean import cleanup
|
||||||
|
|
||||||
|
|
||||||
def tsharkVersion():
|
def tsharkVersion():
|
||||||
"Return tshark version"
|
"Return tshark version"
|
||||||
@@ -74,7 +76,7 @@ class testWalkthrough( unittest.TestCase ):
|
|||||||
p.expect( self.prompt )
|
p.expect( self.prompt )
|
||||||
# net command
|
# net command
|
||||||
p.sendline( 'net' )
|
p.sendline( 'net' )
|
||||||
expected = [ x for x in nodes ]
|
expected = list( nodes )
|
||||||
while len( expected ) > 0:
|
while len( expected ) > 0:
|
||||||
index = p.expect( expected )
|
index = p.expect( expected )
|
||||||
node = p.match.group( 0 )
|
node = p.match.group( 0 )
|
||||||
@@ -110,7 +112,7 @@ class testWalkthrough( unittest.TestCase ):
|
|||||||
ifcount = 0
|
ifcount = 0
|
||||||
while True:
|
while True:
|
||||||
index = p.expect( interfaces )
|
index = p.expect( interfaces )
|
||||||
if index == 0 or index == 3:
|
if index in (0, 3):
|
||||||
ifcount += 1
|
ifcount += 1
|
||||||
elif index == 1:
|
elif index == 1:
|
||||||
self.fail( 's1 interface displayed in "h1 ifconfig"' )
|
self.fail( 's1 interface displayed in "h1 ifconfig"' )
|
||||||
@@ -126,7 +128,7 @@ class testWalkthrough( unittest.TestCase ):
|
|||||||
index = p.expect( interfaces )
|
index = p.expect( interfaces )
|
||||||
if index == 0:
|
if index == 0:
|
||||||
self.fail( 'h1 interface displayed in "s1 ifconfig"' )
|
self.fail( 'h1 interface displayed in "s1 ifconfig"' )
|
||||||
elif index == 1 or index == 2 or index == 3:
|
elif index in (1, 2, 3):
|
||||||
ifcount += 1
|
ifcount += 1
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
@@ -309,7 +311,7 @@ class testWalkthrough( unittest.TestCase ):
|
|||||||
ifcount = 0
|
ifcount = 0
|
||||||
while True:
|
while True:
|
||||||
index = p.expect( interfaces )
|
index = p.expect( interfaces )
|
||||||
if index == 1 or index == 3:
|
if index in (1, 3):
|
||||||
ifcount += 1
|
ifcount += 1
|
||||||
elif index == 0:
|
elif index == 0:
|
||||||
self.fail( 'h1 interface displayed in "s1 ifconfig"' )
|
self.fail( 'h1 interface displayed in "s1 ifconfig"' )
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ setup for testing, and can even be emulated with the Mininet package.
|
|||||||
|
|
||||||
from mininet.util import irange, natural, naturalSeq
|
from mininet.util import irange, natural, naturalSeq
|
||||||
|
|
||||||
|
# pylint: disable=too-many-arguments
|
||||||
|
|
||||||
|
|
||||||
class MultiGraph( object ):
|
class MultiGraph( object ):
|
||||||
"Utility class to track nodes and edges - replaces networkx.MultiGraph"
|
"Utility class to track nodes and edges - replaces networkx.MultiGraph"
|
||||||
|
|
||||||
|
|||||||
+15
-11
@@ -1,19 +1,23 @@
|
|||||||
"Utility functions for Mininet."
|
"Utility functions for Mininet."
|
||||||
|
|
||||||
|
import codecs
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
from mininet.log import output, info, error, warn, debug
|
from fcntl import fcntl, F_GETFL, F_SETFL
|
||||||
|
from functools import partial
|
||||||
from time import sleep
|
from os import O_NONBLOCK
|
||||||
from resource import getrlimit, setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE
|
from resource import getrlimit, setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE
|
||||||
from select import poll, POLLIN, POLLHUP
|
from select import poll, POLLIN, POLLHUP
|
||||||
from subprocess import call, check_call, Popen, PIPE, STDOUT
|
from subprocess import call, check_call, Popen, PIPE, STDOUT
|
||||||
import re
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
from fcntl import fcntl, F_GETFL, F_SETFL
|
from time import sleep
|
||||||
from os import O_NONBLOCK
|
|
||||||
import os
|
from mininet.log import output, info, error, warn, debug
|
||||||
from functools import partial
|
|
||||||
import sys
|
# pylint: disable=too-many-arguments
|
||||||
import codecs
|
|
||||||
|
|
||||||
# Python 2/3 compatibility
|
# Python 2/3 compatibility
|
||||||
|
|
||||||
@@ -454,6 +458,7 @@ def pmonitor(popens, timeoutms=500, readline=True,
|
|||||||
poller.register( fd, POLLIN )
|
poller.register( fd, POLLIN )
|
||||||
flags = fcntl( fd, F_GETFL )
|
flags = fcntl( fd, F_GETFL )
|
||||||
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
|
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
|
||||||
|
# pylint: disable=too-many-nested-blocks
|
||||||
while popens:
|
while popens:
|
||||||
fds = poller.poll( timeoutms )
|
fds = poller.poll( timeoutms )
|
||||||
if fds:
|
if fds:
|
||||||
@@ -665,7 +670,6 @@ def ensureRoot():
|
|||||||
if os.getuid() != 0:
|
if os.getuid() != 0:
|
||||||
error( '*** Mininet must run as root.\n' )
|
error( '*** Mininet must run as root.\n' )
|
||||||
exit( 1 )
|
exit( 1 )
|
||||||
return
|
|
||||||
|
|
||||||
def waitListening( client=None, server='127.0.0.1', port=80, timeout=None ):
|
def waitListening( client=None, server='127.0.0.1', port=80, timeout=None ):
|
||||||
"""Wait until server is listening on port.
|
"""Wait until server is listening on port.
|
||||||
|
|||||||
Reference in New Issue
Block a user