Made it possible to create a Mininet() without using a Topo object.
This increases flexibility by allowing a topology to be manually created in Python, or specified using another format, without having to create a Topo object first. However, Topos are useful, and are still the default topology object!
This commit is contained in:
+112
-114
@@ -84,7 +84,7 @@ from mininet.cli import CLI
|
|||||||
from mininet.log import info, error
|
from mininet.log import info, error
|
||||||
from mininet.node import KernelSwitch, OVSKernelSwitch
|
from mininet.node import KernelSwitch, OVSKernelSwitch
|
||||||
from mininet.util import quietRun, fixLimits
|
from mininet.util import quietRun, fixLimits
|
||||||
from mininet.util import makeIntfPair, moveIntf
|
from mininet.util import makeIntfPair, moveIntf, macColonHex
|
||||||
from mininet.xterm import cleanUpScreens, makeXterms
|
from mininet.xterm import cleanUpScreens, makeXterms
|
||||||
|
|
||||||
DATAPATHS = [ 'kernel' ] #[ 'user', 'kernel' ]
|
DATAPATHS = [ 'kernel' ] #[ 'user', 'kernel' ]
|
||||||
@@ -110,92 +110,103 @@ class Mininet( object ):
|
|||||||
inNamespace=False,
|
inNamespace=False,
|
||||||
autoSetMacs=False, autoStaticArp=False ):
|
autoSetMacs=False, autoStaticArp=False ):
|
||||||
"""Create Mininet object.
|
"""Create Mininet object.
|
||||||
topo: Topo object
|
topo: Topo (topology) object or None
|
||||||
switch: Switch class
|
switch: Switch class
|
||||||
host: Host class
|
host: Host class
|
||||||
controller: Controller class
|
controller: Controller class
|
||||||
cparams: ControllerParams object
|
cparams: ControllerParams object
|
||||||
now: build now?
|
now: build now from topo?
|
||||||
xterms: if build now, spawn xterms?
|
xterms: if build now, spawn xterms?
|
||||||
cleanup: if build now, cleanup before creating?
|
cleanup: if build now, cleanup before creating?
|
||||||
inNamespace: spawn switches and controller in net namespaces?
|
inNamespace: spawn switches and controller in net namespaces?
|
||||||
autoSetMacs: set MAC addrs to DPIDs?
|
autoSetMacs: set MAC addrs to DPIDs?
|
||||||
autoStaticArp: set all-pairs static MAC addrs?"""
|
autoStaticArp: set all-pairs static MAC addrs?"""
|
||||||
self.topo = topo
|
|
||||||
self.switch = switch
|
self.switch = switch
|
||||||
self.host = host
|
self.host = host
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.cparams = cparams
|
self.cparams = cparams
|
||||||
self.nodes = {} # dpid to Node{ Host, Switch } objects
|
self.topo = topo
|
||||||
self.controllers = {} # controller name to Controller objects
|
|
||||||
self.dps = 0 # number of created kernel datapaths
|
|
||||||
self.inNamespace = inNamespace
|
self.inNamespace = inNamespace
|
||||||
self.xterms = xterms
|
self.xterms = xterms
|
||||||
self.cleanup = cleanup
|
self.cleanup = cleanup
|
||||||
self.autoSetMacs = autoSetMacs
|
self.autoSetMacs = autoSetMacs
|
||||||
self.autoStaticArp = autoStaticArp
|
self.autoStaticArp = autoStaticArp
|
||||||
|
|
||||||
|
self.hosts = []
|
||||||
|
self.switches = []
|
||||||
|
self.controllers = []
|
||||||
|
self.nameToNode = {} # name to Node (Host/Switch) objects
|
||||||
|
self.idToNode = {} # dpid to Node (Host/Switch) objects
|
||||||
|
self.dps = 0 # number of created kernel datapaths
|
||||||
self.terms = [] # list of spawned xterm processes
|
self.terms = [] # list of spawned xterm processes
|
||||||
|
|
||||||
if build:
|
if topo and build:
|
||||||
self.build()
|
self.buildFromTopo( self.topo )
|
||||||
|
|
||||||
def _addHost( self, dpid ):
|
def addHost( self, name, defaultMac=None, defaultIp=None ):
|
||||||
"""Add host.
|
"""Add host.
|
||||||
dpid: DPID of host to add"""
|
name: name of host to add
|
||||||
host = self.host( 'h' + self.topo.name( dpid ) )
|
defaultMac: default MAC address for intf 0
|
||||||
|
defaultIp: default IP address for intf 0
|
||||||
|
returns: added host"""
|
||||||
|
host = self.host( name )
|
||||||
# for now, assume one interface per host.
|
# for now, assume one interface per host.
|
||||||
host.intfs.append( 'h' + self.topo.name( dpid ) + '-eth0' )
|
host.intfs.append( name + '-eth0' )
|
||||||
self.nodes[ dpid ] = host
|
self.hosts.append( host )
|
||||||
#info( '%s ' % host.name )
|
self.nameToNode[ name ] = host
|
||||||
|
# May wish to add this to actual object
|
||||||
|
if defaultMac:
|
||||||
|
host.defaultMac = defaultMac
|
||||||
|
if defaultIp:
|
||||||
|
host.defaultIP = defaultIp
|
||||||
|
return host
|
||||||
|
|
||||||
def _addSwitch( self, dpid ):
|
def addSwitch( self, name, defaultMac=None ):
|
||||||
"""Add switch.
|
"""Add switch.
|
||||||
dpid: DPID of switch to add"""
|
name: name of switch to add
|
||||||
sw = None
|
defaultMac: default MAC address for kernel/OVS switch intf 0
|
||||||
swDpid = None
|
returns: added switch"""
|
||||||
if self.autoSetMacs:
|
|
||||||
swDpid = dpid
|
|
||||||
if self.switch is KernelSwitch or self.switch is OVSKernelSwitch:
|
if self.switch is KernelSwitch or self.switch is OVSKernelSwitch:
|
||||||
sw = self.switch( 's_' + self.topo.name( dpid ), dp = self.dps,
|
sw = self.switch( name, dp=self.dps, defaultMac=defaultMac )
|
||||||
dpid = swDpid )
|
|
||||||
self.dps += 1
|
self.dps += 1
|
||||||
else:
|
else:
|
||||||
sw = self.switch( 's_' + self.topo.name( dpid ) )
|
sw = self.switch( name )
|
||||||
self.nodes[ dpid ] = sw
|
self.switches.append( sw )
|
||||||
|
self.nameToNode[ name ] = sw
|
||||||
|
return sw
|
||||||
|
|
||||||
def _addLink( self, src, dst ):
|
def addLink( self, src, srcPort, dst, dstPort ):
|
||||||
"""Add link.
|
"""Add link.
|
||||||
src: source DPID
|
src: source Node
|
||||||
dst: destination DPID"""
|
srcPort: source port
|
||||||
srcPort, dstPort = self.topo.port( src, dst )
|
dst: destination Node
|
||||||
srcNode = self.nodes[ src ]
|
dstPort: destination port"""
|
||||||
dstNode = self.nodes[ dst ]
|
srcIntf = src.intfName( srcPort )
|
||||||
srcIntf = srcNode.intfName( srcPort )
|
dstIntf = dst.intfName( dstPort )
|
||||||
dstIntf = dstNode.intfName( dstPort )
|
|
||||||
makeIntfPair( srcIntf, dstIntf )
|
makeIntfPair( srcIntf, dstIntf )
|
||||||
srcNode.intfs.append( srcIntf )
|
src.intfs.append( srcIntf )
|
||||||
dstNode.intfs.append( dstIntf )
|
dst.intfs.append( dstIntf )
|
||||||
srcNode.ports[ srcPort ] = srcIntf
|
src.ports[ srcPort ] = srcIntf
|
||||||
dstNode.ports[ dstPort ] = dstIntf
|
dst.ports[ dstPort ] = dstIntf
|
||||||
#info( '\n' )
|
#info( '\n' )
|
||||||
#info( 'added intf %s to src node %x\n' % ( srcIntf, src ) )
|
#info( 'added intf %s to src node %x\n' % ( srcIntf, src ) )
|
||||||
#info( 'added intf %s to dst node %x\n' % ( dstIntf, dst ) )
|
#info( 'added intf %s to dst node %x\n' % ( dstIntf, dst ) )
|
||||||
if srcNode.inNamespace:
|
if src.inNamespace:
|
||||||
#info( 'moving src w/inNamespace set\n' )
|
#info( 'moving src w/inNamespace set\n' )
|
||||||
moveIntf( srcIntf, srcNode )
|
moveIntf( srcIntf, src )
|
||||||
if dstNode.inNamespace:
|
if dst.inNamespace:
|
||||||
#info( 'moving dst w/inNamespace set\n' )
|
#info( 'moving dst w/inNamespace set\n' )
|
||||||
moveIntf( dstIntf, dstNode )
|
moveIntf( dstIntf, dst )
|
||||||
srcNode.connection[ srcIntf ] = ( dstNode, dstIntf )
|
src.connection[ srcIntf ] = ( dst, dstIntf )
|
||||||
dstNode.connection[ dstIntf ] = ( srcNode, srcIntf )
|
dst.connection[ dstIntf ] = ( src, srcIntf )
|
||||||
|
|
||||||
def _addController( self, controller ):
|
def addController( self, controller ):
|
||||||
"""Add controller.
|
"""Add controller.
|
||||||
controller: Controller class"""
|
controller: Controller class"""
|
||||||
controller = self.controller( 'c0', self.inNamespace )
|
controller = self.controller( 'c0', self.inNamespace )
|
||||||
if controller: # allow controller-less setups
|
if controller: # allow controller-less setups
|
||||||
self.controllers[ 'c0' ] = controller
|
self.controllers.append( controller )
|
||||||
|
self.nameToNode[ 'c0' ] = controller
|
||||||
|
|
||||||
# Control network support:
|
# Control network support:
|
||||||
#
|
#
|
||||||
@@ -229,12 +240,11 @@ class Mininet( object ):
|
|||||||
"""
|
"""
|
||||||
# params were: controller, switches, ips
|
# params were: controller, switches, ips
|
||||||
|
|
||||||
controller = self.controllers[ 'c0' ]
|
controller = self.controllers[ 0 ]
|
||||||
info( '%s <-> ' % controller.name )
|
info( '%s <-> ' % controller.name )
|
||||||
for switchDpid in self.topo.switches():
|
for switch in self.switches:
|
||||||
switch = self.nodes[ switchDpid ]
|
|
||||||
info( '%s ' % switch.name )
|
info( '%s ' % switch.name )
|
||||||
sip = self.topo.ip( switchDpid )#ips.next()
|
sip = switch.defaultIP
|
||||||
sintf = switch.intfs[ 0 ]
|
sintf = switch.intfs[ 0 ]
|
||||||
node, cintf = switch.connection[ sintf ]
|
node, cintf = switch.connection[ sintf ]
|
||||||
if node != controller:
|
if node != controller:
|
||||||
@@ -253,8 +263,7 @@ class Mininet( object ):
|
|||||||
info( '*** Waiting for %s to come up\n',
|
info( '*** Waiting for %s to come up\n',
|
||||||
controller.intfs[ 0 ] )
|
controller.intfs[ 0 ] )
|
||||||
sleep( 1 )
|
sleep( 1 )
|
||||||
for switchDpid in self.topo.switches():
|
for switch in self.switches:
|
||||||
switch = self.nodes[ switchDpid ]
|
|
||||||
while not switch.intfIsUp( switch.intfs[ 0 ] ):
|
while not switch.intfIsUp( switch.intfs[ 0 ] ):
|
||||||
info( '*** Waiting for %s to come up\n' %
|
info( '*** Waiting for %s to come up\n' %
|
||||||
switch.intfs[ 0 ] )
|
switch.intfs[ 0 ] )
|
||||||
@@ -267,10 +276,9 @@ class Mininet( object ):
|
|||||||
def _configHosts( self ):
|
def _configHosts( self ):
|
||||||
"Configure a set of hosts."
|
"Configure a set of hosts."
|
||||||
# params were: hosts, ips
|
# params were: hosts, ips
|
||||||
for hostDpid in self.topo.hosts():
|
for host in self.hosts:
|
||||||
host = self.nodes[ hostDpid ]
|
|
||||||
hintf = host.intfs[ 0 ]
|
hintf = host.intfs[ 0 ]
|
||||||
host.setIP( hintf, self.topo.ip( hostDpid ),
|
host.setIP( hintf, host.defaultIP,
|
||||||
'/' + str( self.cparams.subnetSize ) )
|
'/' + str( self.cparams.subnetSize ) )
|
||||||
host.setDefaultRoute( hintf )
|
host.setDefaultRoute( hintf )
|
||||||
# You're low priority, dude!
|
# You're low priority, dude!
|
||||||
@@ -278,28 +286,37 @@ class Mininet( object ):
|
|||||||
info( '%s ', host.name )
|
info( '%s ', host.name )
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
def build( self ):
|
def buildFromTopo( self, topo ):
|
||||||
"""Build mininet.
|
"""Build mininet from a topology object
|
||||||
At the end of this function, everything should be connected
|
At the end of this function, everything should be connected
|
||||||
and up."""
|
and up."""
|
||||||
if self.cleanup:
|
if self.cleanup:
|
||||||
pass # cleanup
|
pass # cleanup
|
||||||
# validate topo?
|
# validate topo?
|
||||||
info( '*** Adding controller\n' )
|
info( '*** Adding controller\n' )
|
||||||
self._addController( self.controller )
|
self.addController( self.controller )
|
||||||
info( '*** Creating network\n' )
|
info( '*** Creating network\n' )
|
||||||
info( '*** Adding hosts:\n' )
|
info( '*** Adding hosts:\n' )
|
||||||
for host in sorted( self.topo.hosts() ):
|
for hostId in sorted( topo.hosts() ):
|
||||||
self._addHost( host )
|
name = 'h' + topo.name( hostId )
|
||||||
info( '0x%x ' % host )
|
mac = macColonHex( hostId ) if self.setMacs else None
|
||||||
|
ip = topo.ip( hostId )
|
||||||
|
host = self.addHost( name, defaultIp=ip, defaultMac=mac )
|
||||||
|
self.idToNode[ hostId ] = host
|
||||||
|
info( name )
|
||||||
info( '\n*** Adding switches:\n' )
|
info( '\n*** Adding switches:\n' )
|
||||||
for switch in sorted( self.topo.switches() ):
|
for switchId in sorted( topo.switches() ):
|
||||||
self._addSwitch( switch )
|
name = 's' + topo.name( switchId )
|
||||||
info( '0x%x ' % switch )
|
mac = macColonHex( switchId) if self.setMacs else None
|
||||||
|
switch = self.addSwitch( name, defaultMac=mac )
|
||||||
|
self.idToNode[ switchId ] = switch
|
||||||
|
info( name )
|
||||||
info( '\n*** Adding edges:\n' )
|
info( '\n*** Adding edges:\n' )
|
||||||
for src, dst in sorted( self.topo.edges() ):
|
for srcId, dstId in sorted( topo.edges() ):
|
||||||
self._addLink( src, dst )
|
src, dst = self.idToNode[ srcId ], self.idToNode[ dstId ]
|
||||||
info( '(0x%x, 0x%x) ' % ( src, dst ) )
|
srcPort, dstPort = topo.port( srcId, dstId )
|
||||||
|
self.addLink( src, srcPort, dst, dstPort )
|
||||||
|
info( '(%s, %s) ' % ( src.name, dst.name ) )
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
if self.inNamespace:
|
if self.inNamespace:
|
||||||
@@ -316,21 +333,13 @@ class Mininet( object ):
|
|||||||
if self.autoStaticArp:
|
if self.autoStaticArp:
|
||||||
self.staticArp()
|
self.staticArp()
|
||||||
|
|
||||||
def switchNodes( self ):
|
|
||||||
"Return switch nodes."
|
|
||||||
return [ self.nodes[ dpid ] for dpid in self.topo.switches() ]
|
|
||||||
|
|
||||||
def hostNodes( self ):
|
|
||||||
"Return host nodes."
|
|
||||||
return [ self.nodes[ dpid ] for dpid in self.topo.hosts() ]
|
|
||||||
|
|
||||||
def startXterms( self ):
|
def startXterms( self ):
|
||||||
"Start an xterm for each node in the topo."
|
"Start an xterm for each node."
|
||||||
info( "*** Running xterms on %s\n" % os.environ[ 'DISPLAY' ] )
|
info( "*** Running xterms on %s\n" % os.environ[ 'DISPLAY' ] )
|
||||||
cleanUpScreens()
|
cleanUpScreens()
|
||||||
self.terms += makeXterms( self.controllers.values(), 'controller' )
|
self.terms += makeXterms( self.controllers, 'controller' )
|
||||||
self.terms += makeXterms( self.switchNodes(), 'switch' )
|
self.terms += makeXterms( self.switches, 'switch' )
|
||||||
self.terms += makeXterms( self.hostNodes(), 'host' )
|
self.terms += makeXterms( self.hosts, 'host' )
|
||||||
|
|
||||||
def stopXterms( self ):
|
def stopXterms( self ):
|
||||||
"Kill each xterm."
|
"Kill each xterm."
|
||||||
@@ -342,28 +351,24 @@ class Mininet( object ):
|
|||||||
def setMacs( self ):
|
def setMacs( self ):
|
||||||
"""Set MAC addrs to correspond to datapath IDs on hosts.
|
"""Set MAC addrs to correspond to datapath IDs on hosts.
|
||||||
Assume that the host only has one interface."""
|
Assume that the host only has one interface."""
|
||||||
for dpid in self.topo.hosts():
|
for host in self.hosts:
|
||||||
hostNode = self.nodes[ dpid ]
|
host.setMAC( host.intfs[ 0 ], host.defaultMac )
|
||||||
hostNode.setMAC( hostNode.intfs[ 0 ], dpid )
|
|
||||||
|
|
||||||
def staticArp( self ):
|
def staticArp( self ):
|
||||||
"Add all-pairs ARP entries to remove the need to handle broadcast."
|
"Add all-pairs ARP entries to remove the need to handle broadcast."
|
||||||
for src in self.topo.hosts():
|
for src in self.hosts:
|
||||||
srcNode = self.nodes[ src ]
|
for dst in self.hosts:
|
||||||
for dst in self.topo.hosts():
|
|
||||||
if src != dst:
|
if src != dst:
|
||||||
srcNode.setARP( dst, dst )
|
src.setARP( ip=dst.IP(), mac=dst.defaultMac )
|
||||||
|
|
||||||
def start( self ):
|
def start( self ):
|
||||||
"Start controller and switches"
|
"Start controller and switches"
|
||||||
info( '*** Starting controller\n' )
|
info( '*** Starting controller\n' )
|
||||||
for cnode in self.controllers.values():
|
for controller in self.controllers:
|
||||||
cnode.start()
|
controller.start()
|
||||||
info( '*** Starting %s switches\n' % len( self.topo.switches() ) )
|
info( '*** Starting %s switches\n' % len( self.switches ) )
|
||||||
for switchDpid in self.topo.switches():
|
for switch in self.switches:
|
||||||
switch = self.nodes[ switchDpid ]
|
info( switch.name )
|
||||||
#info( 'switch = %s' % switch )
|
|
||||||
info( '0x%x ' % switchDpid )
|
|
||||||
switch.start( self.controllers )
|
switch.start( self.controllers )
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
@@ -372,21 +377,19 @@ class Mininet( object ):
|
|||||||
if self.terms:
|
if self.terms:
|
||||||
info( '*** Stopping %i terms\n' % len( self.terms ) )
|
info( '*** Stopping %i terms\n' % len( self.terms ) )
|
||||||
self.stopXterms()
|
self.stopXterms()
|
||||||
info( '*** Stopping %i hosts\n' % len( self.topo.hosts() ) )
|
info( '*** Stopping %i hosts\n' % len( self.hosts ) )
|
||||||
for hostDpid in self.topo.hosts():
|
for host in self.hosts:
|
||||||
host = self.nodes[ hostDpid ]
|
|
||||||
info( '%s ' % host.name )
|
info( '%s ' % host.name )
|
||||||
host.terminate()
|
host.terminate()
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
info( '*** Stopping %i switches\n' % len( self.topo.switches() ) )
|
info( '*** Stopping %i switches\n' % len( self.switches ) )
|
||||||
for switchDpid in self.topo.switches():
|
for switch in self.switches:
|
||||||
switch = self.nodes[ switchDpid ]
|
|
||||||
info( '%s ' % switch.name )
|
info( '%s ' % switch.name )
|
||||||
switch.stop()
|
switch.stop()
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
info( '*** Stopping controller\n' )
|
info( '*** Stopping %i controllers\n' % len( self.controllers ) )
|
||||||
for cnode in self.controllers.values():
|
for controller in self.controllers:
|
||||||
cnode.stop()
|
controller.stop()
|
||||||
info( '*** Test complete\n' )
|
info( '*** Test complete\n' )
|
||||||
|
|
||||||
def run( self, test, **params ):
|
def run( self, test, **params ):
|
||||||
@@ -411,7 +414,7 @@ class Mininet( object ):
|
|||||||
|
|
||||||
def ping( self, hosts=None ):
|
def ping( self, hosts=None ):
|
||||||
"""Ping between all specified hosts.
|
"""Ping between all specified hosts.
|
||||||
hosts: list of host DPIDs
|
hosts: list of hosts
|
||||||
returns: ploss packet loss percentage"""
|
returns: ploss packet loss percentage"""
|
||||||
#self.start()
|
#self.start()
|
||||||
# check if running - only then, start?
|
# check if running - only then, start?
|
||||||
@@ -419,13 +422,11 @@ class Mininet( object ):
|
|||||||
lost = 0
|
lost = 0
|
||||||
ploss = None
|
ploss = None
|
||||||
if not hosts:
|
if not hosts:
|
||||||
hosts = self.topo.hosts()
|
hosts = self.hosts
|
||||||
info( '*** Ping: testing ping reachability\n' )
|
info( '*** Ping: testing ping reachability\n' )
|
||||||
for nodeDpid in hosts:
|
for node in hosts:
|
||||||
node = self.nodes[ nodeDpid ]
|
|
||||||
info( '%s -> ' % node.name )
|
info( '%s -> ' % node.name )
|
||||||
for destDpid in hosts:
|
for dest in hosts:
|
||||||
dest = self.nodes[ destDpid ]
|
|
||||||
if node != dest:
|
if node != dest:
|
||||||
result = node.cmd( 'ping -c1 ' + dest.IP() )
|
result = node.cmd( 'ping -c1 ' + dest.IP() )
|
||||||
sent, received = self._parsePing( result )
|
sent, received = self._parsePing( result )
|
||||||
@@ -451,8 +452,7 @@ class Mininet( object ):
|
|||||||
def pingPair( self ):
|
def pingPair( self ):
|
||||||
"""Ping between first two hosts, useful for testing.
|
"""Ping between first two hosts, useful for testing.
|
||||||
returns: ploss packet loss percentage"""
|
returns: ploss packet loss percentage"""
|
||||||
hostsSorted = sorted( self.topo.hosts() )
|
hosts = [ self.hosts[ 0 ], self.hosts[ 1 ] ]
|
||||||
hosts = [ hostsSorted[ 0 ], hostsSorted[ 1 ] ]
|
|
||||||
return self.ping( hosts=hosts )
|
return self.ping( hosts=hosts )
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -470,17 +470,15 @@ class Mininet( object ):
|
|||||||
def iperf( self, hosts=None, l4Type='TCP', udpBw='10M',
|
def iperf( self, hosts=None, l4Type='TCP', udpBw='10M',
|
||||||
verbose=False ):
|
verbose=False ):
|
||||||
"""Run iperf between two hosts.
|
"""Run iperf between two hosts.
|
||||||
hosts: list of host DPIDs; if None, uses opposite hosts
|
hosts: list of hosts; if None, uses opposite hosts
|
||||||
l4Type: string, one of [ TCP, UDP ]
|
l4Type: string, one of [ TCP, UDP ]
|
||||||
verbose: verbose printing
|
verbose: verbose printing
|
||||||
returns: results two-element array of server and client speeds"""
|
returns: results two-element array of server and client speeds"""
|
||||||
if not hosts:
|
if not hosts:
|
||||||
hostsSorted = sorted( self.topo.hosts() )
|
hosts = [ self.hosts[ 0 ], self.hosts[ -1 ] ]
|
||||||
hosts = [ hostsSorted[ 0 ], hostsSorted[ -1 ] ]
|
|
||||||
else:
|
else:
|
||||||
assert len( hosts ) == 2
|
assert len( hosts ) == 2
|
||||||
host0 = self.nodes[ hosts[ 0 ] ]
|
host0, host1 = hosts
|
||||||
host1 = self.nodes[ hosts[ 1 ] ]
|
|
||||||
info( '*** Iperf: testing ' + l4Type + ' bandwidth between ' )
|
info( '*** Iperf: testing ' + l4Type + ' bandwidth between ' )
|
||||||
info( "%s and %s\n" % ( host0.name, host1.name ) )
|
info( "%s and %s\n" % ( host0.name, host1.name ) )
|
||||||
host0.cmd( 'killall -9 iperf' )
|
host0.cmd( 'killall -9 iperf' )
|
||||||
|
|||||||
+21
-25
@@ -41,7 +41,7 @@ import signal
|
|||||||
import select
|
import select
|
||||||
|
|
||||||
from mininet.log import info, error
|
from mininet.log import info, error
|
||||||
from mininet.util import quietRun, macColonHex, ipStr
|
from mininet.util import quietRun
|
||||||
|
|
||||||
|
|
||||||
class Node( object ):
|
class Node( object ):
|
||||||
@@ -191,19 +191,16 @@ class Node( object ):
|
|||||||
|
|
||||||
def setMAC( self, intf, mac ):
|
def setMAC( self, intf, mac ):
|
||||||
"""Set the MAC address for an interface.
|
"""Set the MAC address for an interface.
|
||||||
mac: MAC address as unsigned int"""
|
mac: MAC address as string"""
|
||||||
macStr = macColonHex( mac )
|
|
||||||
result = self.cmd( [ 'ifconfig', intf, 'down' ] )
|
result = self.cmd( [ 'ifconfig', intf, 'down' ] )
|
||||||
result += self.cmd( [ 'ifconfig', intf, 'hw', 'ether', macStr ] )
|
result += self.cmd( [ 'ifconfig', intf, 'hw', 'ether', mac ] )
|
||||||
result += self.cmd( [ 'ifconfig', intf, 'up' ] )
|
result += self.cmd( [ 'ifconfig', intf, 'up' ] )
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def setARP( self, ip, mac ):
|
def setARP( self, ip, mac ):
|
||||||
"""Add an ARP entry.
|
"""Add an ARP entry.
|
||||||
ip: IP address as unsigned int
|
ip: IP address as string
|
||||||
mac: MAC address as unsigned int"""
|
mac: MAC address as string"""
|
||||||
ip = ipStr( ip )
|
|
||||||
mac = macColonHex( mac )
|
|
||||||
result = self.cmd( [ 'arp', '-s', ip, mac ] )
|
result = self.cmd( [ 'arp', '-s', ip, mac ] )
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -286,9 +283,7 @@ class UserSwitch( Switch ):
|
|||||||
"""Start OpenFlow reference user datapath.
|
"""Start OpenFlow reference user datapath.
|
||||||
Log to /tmp/sN-{ofd,ofp}.log.
|
Log to /tmp/sN-{ofd,ofp}.log.
|
||||||
controllers: dict of controller names to objects"""
|
controllers: dict of controller names to objects"""
|
||||||
if 'c0' not in controllers:
|
controller = controllers[ 0 ]
|
||||||
raise Exception( 'User datapath start() requires controller c0' )
|
|
||||||
controller = controllers[ 'c0' ]
|
|
||||||
ofdlog = '/tmp/' + self.name + '-ofd.log'
|
ofdlog = '/tmp/' + self.name + '-ofd.log'
|
||||||
ofplog = '/tmp/' + self.name + '-ofp.log'
|
ofplog = '/tmp/' + self.name + '-ofp.log'
|
||||||
self.cmd( 'ifconfig lo up' )
|
self.cmd( 'ifconfig lo up' )
|
||||||
@@ -311,14 +306,14 @@ class KernelSwitch( Switch ):
|
|||||||
"""Kernel-space switch.
|
"""Kernel-space switch.
|
||||||
Currently only works in the root namespace."""
|
Currently only works in the root namespace."""
|
||||||
|
|
||||||
def __init__( self, name, dp=None, dpid=None ):
|
def __init__( self, name, dp=None, defaultMac=None ):
|
||||||
"""Init.
|
"""Init.
|
||||||
name:
|
name:
|
||||||
dp: netlink id (0, 1, 2, ...)
|
dp: netlink id (0, 1, 2, ...)
|
||||||
dpid: datapath ID as unsigned int; random value if None"""
|
defaultMac: default MAC as string; random value if None"""
|
||||||
Switch.__init__( self, name, inNamespace=False )
|
Switch.__init__( self, name, inNamespace=False )
|
||||||
self.dp = dp
|
self.dp = dp
|
||||||
self.dpid = dpid
|
self.defaultMac = defaultMac
|
||||||
|
|
||||||
def start( self, controllers ):
|
def start( self, controllers ):
|
||||||
"Start up reference kernel datapath."
|
"Start up reference kernel datapath."
|
||||||
@@ -328,10 +323,9 @@ class KernelSwitch( Switch ):
|
|||||||
# then create a new one monitoring the given interfaces
|
# then create a new one monitoring the given interfaces
|
||||||
quietRun( 'dpctl deldp nl:%i' % self.dp )
|
quietRun( 'dpctl deldp nl:%i' % self.dp )
|
||||||
self.cmdPrint( 'dpctl adddp nl:%i' % self.dp )
|
self.cmdPrint( 'dpctl adddp nl:%i' % self.dp )
|
||||||
if self.dpid:
|
if self.defaultMac:
|
||||||
intf = 'of%i' % self.dp
|
intf = 'of%i' % self.dp
|
||||||
macStr = macColonHex( self.dpid )
|
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', self.defaultMac ] )
|
||||||
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', macStr ] )
|
|
||||||
|
|
||||||
if len( self.ports ) != max( self.ports.keys() ) + 1:
|
if len( self.ports ) != max( self.ports.keys() ) + 1:
|
||||||
raise Exception( 'only contiguous, zero-indexed port ranges'
|
raise Exception( 'only contiguous, zero-indexed port ranges'
|
||||||
@@ -340,9 +334,10 @@ class KernelSwitch( Switch ):
|
|||||||
self.cmdPrint( 'dpctl addif nl:' + str( self.dp ) + ' ' +
|
self.cmdPrint( 'dpctl addif nl:' + str( self.dp ) + ' ' +
|
||||||
' '.join( intfs ) )
|
' '.join( intfs ) )
|
||||||
# Run protocol daemon
|
# Run protocol daemon
|
||||||
|
controller = controllers[ 0 ]
|
||||||
self.cmdPrint( 'ofprotocol nl:' + str( self.dp ) + ' tcp:' +
|
self.cmdPrint( 'ofprotocol nl:' + str( self.dp ) + ' tcp:' +
|
||||||
controllers[ 'c0' ].IP() + ':' +
|
controller.IP() + ':' +
|
||||||
str( controllers[ 'c0' ].port ) +
|
str( controller.port ) +
|
||||||
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
||||||
self.execed = False
|
self.execed = False
|
||||||
|
|
||||||
@@ -363,14 +358,14 @@ class OVSKernelSwitch( Switch ):
|
|||||||
"""Open VSwitch kernel-space switch.
|
"""Open VSwitch kernel-space switch.
|
||||||
Currently only works in the root namespace."""
|
Currently only works in the root namespace."""
|
||||||
|
|
||||||
def __init__( self, name, dp=None, dpid=None ):
|
def __init__( self, name, dp=None, defaultMac=None ):
|
||||||
"""Init.
|
"""Init.
|
||||||
name:
|
name:
|
||||||
dp: netlink id (0, 1, 2, ...)
|
dp: netlink id (0, 1, 2, ...)
|
||||||
dpid: datapath ID as unsigned int; random value if None"""
|
dpid: datapath ID as unsigned int; random value if None"""
|
||||||
Switch.__init__( self, name, inNamespace=False )
|
Switch.__init__( self, name, inNamespace=False )
|
||||||
self.dp = dp
|
self.dp = dp
|
||||||
self.dpid = dpid
|
self.defaultMac = defaultMac
|
||||||
|
|
||||||
def start( self, controllers ):
|
def start( self, controllers ):
|
||||||
"Start up kernel datapath."
|
"Start up kernel datapath."
|
||||||
@@ -380,10 +375,10 @@ class OVSKernelSwitch( Switch ):
|
|||||||
# then create a new one monitoring the given interfaces
|
# then create a new one monitoring the given interfaces
|
||||||
quietRun( 'ovs-dpctl del-dp dp%i' % self.dp )
|
quietRun( 'ovs-dpctl del-dp dp%i' % self.dp )
|
||||||
self.cmdPrint( 'ovs-dpctl add-dp dp%i' % self.dp )
|
self.cmdPrint( 'ovs-dpctl add-dp dp%i' % self.dp )
|
||||||
if self.dpid:
|
if self.defaultMac:
|
||||||
intf = 'dp' % self.dp
|
intf = 'dp' % self.dp
|
||||||
macStr = macColonHex( self.dpid )
|
mac = self.defaultMac
|
||||||
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', macStr ] )
|
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', mac ] )
|
||||||
|
|
||||||
if len( self.ports ) != max( self.ports.keys() ) + 1:
|
if len( self.ports ) != max( self.ports.keys() ) + 1:
|
||||||
raise Exception( 'only contiguous, zero-indexed port ranges'
|
raise Exception( 'only contiguous, zero-indexed port ranges'
|
||||||
@@ -392,8 +387,9 @@ class OVSKernelSwitch( Switch ):
|
|||||||
self.cmdPrint( 'ovs-dpctl add-if dp' + str( self.dp ) + ' ' +
|
self.cmdPrint( 'ovs-dpctl add-if dp' + str( self.dp ) + ' ' +
|
||||||
' '.join( intfs ) )
|
' '.join( intfs ) )
|
||||||
# Run protocol daemon
|
# Run protocol daemon
|
||||||
|
controller = controllers[ 0 ]
|
||||||
self.cmdPrint( 'ovs-openflowd dp' + str( self.dp ) + ' tcp:' +
|
self.cmdPrint( 'ovs-openflowd dp' + str( self.dp ) + ' tcp:' +
|
||||||
controllers[ 'c0' ].IP() + ':' +
|
controller.IP() + ':' +
|
||||||
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
||||||
self.execed = False
|
self.execed = False
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user