Moved link creation into Node.addIntf() and fixed util:CreateLink().
Also tweaked cmd/cmdPrint to make them more beautiful and functional, and a few other minor changes, such as using a new idiom for verbose. These changes support reinstating the examples.
This commit is contained in:
+41
-27
@@ -6,35 +6,49 @@ This is more complicated than using the higher-level classes,
|
||||
but it exposes the configuration details and allows customization.
|
||||
"""
|
||||
|
||||
from mininet.mininet import init, Node, createLink
|
||||
import logging
|
||||
|
||||
from mininet.net import init
|
||||
from mininet.node import Node
|
||||
from mininet.util import createLink
|
||||
from mininet.log import info
|
||||
|
||||
# print out info() messages, including cmdPrint
|
||||
logging.LOGLEVELDEFAULT = logging.INFO
|
||||
|
||||
def scratchNet( cname='controller', cargs='ptcp:'):
|
||||
# Create Network
|
||||
controller = Node( 'c0', inNamespace=False )
|
||||
switch = Node( 's0', inNamespace=False )
|
||||
h0 = Node( 'h0' )
|
||||
h1 = Node( 'h1' )
|
||||
createLink( h0, switch )
|
||||
createLink( h1, switch )
|
||||
# Configure hosts
|
||||
h0.setIP( h0.intfs[ 0 ], '192.168.123.1', '/24' )
|
||||
h1.setIP( h1.intfs[ 0 ], '192.168.123.2', '/24' )
|
||||
# Start network using kernel datapath
|
||||
controller.cmdPrint( cname + ' ' + cargs + '&' )
|
||||
switch.cmdPrint( 'dpctl deldp nl:0' )
|
||||
switch.cmdPrint( 'dpctl adddp nl:0' )
|
||||
for intf in switch.intfs:
|
||||
# Create Network
|
||||
print "*** creating Nodes"
|
||||
controller = Node( 'c0', inNamespace=False )
|
||||
switch = Node( 's0', inNamespace=False )
|
||||
h0 = Node( 'h0' )
|
||||
h1 = Node( 'h1' )
|
||||
print "*** creating links"
|
||||
createLink( node1=h0, port1=0, node2=switch, port2=0 )
|
||||
createLink( node1=h1, port1=0, node2=switch, port2=1 )
|
||||
# Configure hosts
|
||||
print "*** configuring hosts"
|
||||
h0.setIP( h0.intfs[ 0 ], '192.168.123.1', '/24' )
|
||||
h1.setIP( h1.intfs[ 0 ], '192.168.123.2', '/24' )
|
||||
print h0
|
||||
print h1
|
||||
# Start network using kernel datapath
|
||||
controller.cmdPrint( cname + ' ' + cargs + '&' )
|
||||
switch.cmdPrint( 'dpctl deldp nl:0' )
|
||||
switch.cmdPrint( 'dpctl adddp nl:0' )
|
||||
for intf in switch.intfs.values():
|
||||
switch.cmdPrint( 'dpctl addif nl:0 ' + intf )
|
||||
switch.cmdPrint( 'ofprotocol nl:0 tcp:localhost &')
|
||||
# Run test
|
||||
h0.cmdPrint( 'ping -c1 ' + h1.IP() )
|
||||
# Stop network
|
||||
controller.cmdPrint( 'kill %' + cname)
|
||||
switch.cmdPrint( 'dpctl deldp nl:0' )
|
||||
switch.cmdPrint( 'kill %ofprotocol' )
|
||||
switch.stop()
|
||||
controller.stop()
|
||||
switch.cmdPrint( 'ofprotocol nl:0 tcp:localhost &')
|
||||
# Run test
|
||||
print h0.cmd( 'ping -c1 ' + h1.IP() )
|
||||
# Stop network
|
||||
controller.cmdPrint( 'kill %' + cname)
|
||||
switch.cmdPrint( 'dpctl deldp nl:0' )
|
||||
switch.cmdPrint( 'kill %ofprotocol' )
|
||||
switch.stop()
|
||||
controller.stop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
init()
|
||||
scratchNet()
|
||||
info( '*** Scratch network demo\n' )
|
||||
init()
|
||||
scratchNet()
|
||||
|
||||
+11
-40
@@ -81,10 +81,10 @@ import signal
|
||||
from time import sleep
|
||||
|
||||
from mininet.cli import CLI
|
||||
from mininet.log import info, error
|
||||
from mininet.log import info, error, debug
|
||||
from mininet.node import KernelSwitch, OVSKernelSwitch
|
||||
from mininet.util import quietRun, fixLimits
|
||||
from mininet.util import makeIntfPair, moveIntf, macColonHex
|
||||
from mininet.util import createLink, macColonHex
|
||||
from mininet.xterm import cleanUpScreens, makeXterms
|
||||
|
||||
DATAPATHS = [ 'kernel' ] #[ 'user', 'kernel' ]
|
||||
@@ -150,8 +150,6 @@ class Mininet( object ):
|
||||
defaultIp: default IP address for intf 0
|
||||
returns: added host"""
|
||||
host = self.host( name )
|
||||
# for now, assume one interface per host.
|
||||
host.intfs.append( name + '-eth0' )
|
||||
self.hosts.append( host )
|
||||
self.nameToNode[ name ] = host
|
||||
# May wish to add this to actual object
|
||||
@@ -175,31 +173,6 @@ class Mininet( object ):
|
||||
self.nameToNode[ name ] = sw
|
||||
return sw
|
||||
|
||||
def addLink( self, src, srcPort, dst, dstPort ):
|
||||
"""Add link.
|
||||
src: source Node
|
||||
srcPort: source port
|
||||
dst: destination Node
|
||||
dstPort: destination port"""
|
||||
srcIntf = src.intfName( srcPort )
|
||||
dstIntf = dst.intfName( dstPort )
|
||||
makeIntfPair( srcIntf, dstIntf )
|
||||
src.intfs.append( srcIntf )
|
||||
dst.intfs.append( dstIntf )
|
||||
src.ports[ srcPort ] = srcIntf
|
||||
dst.ports[ dstPort ] = dstIntf
|
||||
#info( '\n' )
|
||||
#info( 'added intf %s to src node %x\n' % ( srcIntf, src ) )
|
||||
#info( 'added intf %s to dst node %x\n' % ( dstIntf, dst ) )
|
||||
if src.inNamespace:
|
||||
#info( 'moving src w/inNamespace set\n' )
|
||||
moveIntf( srcIntf, src )
|
||||
if dst.inNamespace:
|
||||
#info( 'moving dst w/inNamespace set\n' )
|
||||
moveIntf( dstIntf, dst )
|
||||
src.connection[ srcIntf ] = ( dst, dstIntf )
|
||||
dst.connection[ dstIntf ] = ( src, srcIntf )
|
||||
|
||||
def addController( self, controller ):
|
||||
"""Add controller.
|
||||
controller: Controller class"""
|
||||
@@ -315,7 +288,7 @@ class Mininet( object ):
|
||||
for srcId, dstId in sorted( topo.edges() ):
|
||||
src, dst = self.idToNode[ srcId ], self.idToNode[ dstId ]
|
||||
srcPort, dstPort = topo.port( srcId, dstId )
|
||||
self.addLink( src, srcPort, dst, dstPort )
|
||||
createLink( src, srcPort, dst, dstPort )
|
||||
info( '(%s, %s) ' % ( src.name, dst.name ) )
|
||||
info( '\n' )
|
||||
|
||||
@@ -368,7 +341,7 @@ class Mininet( object ):
|
||||
controller.start()
|
||||
info( '*** Starting %s switches\n' % len( self.switches ) )
|
||||
for switch in self.switches:
|
||||
info( switch.name )
|
||||
info( switch.name + ' ')
|
||||
switch.start( self.controllers )
|
||||
info( '\n' )
|
||||
|
||||
@@ -474,13 +447,14 @@ class Mininet( object ):
|
||||
l4Type: string, one of [ TCP, UDP ]
|
||||
verbose: verbose printing
|
||||
returns: results two-element array of server and client speeds"""
|
||||
log = info if verbose else debug
|
||||
if not hosts:
|
||||
hosts = [ self.hosts[ 0 ], self.hosts[ -1 ] ]
|
||||
else:
|
||||
assert len( hosts ) == 2
|
||||
host0, host1 = hosts
|
||||
info( '*** Iperf: testing ' + l4Type + ' bandwidth between ' )
|
||||
info( "%s and %s\n" % ( host0.name, host1.name ) )
|
||||
log( '*** Iperf: testing ' + l4Type + ' bandwidth between ' )
|
||||
log( "%s and %s\n" % ( host0.name, host1.name ) )
|
||||
host0.cmd( 'killall -9 iperf' )
|
||||
iperfArgs = 'iperf '
|
||||
bwArgs = ''
|
||||
@@ -490,19 +464,16 @@ class Mininet( object ):
|
||||
elif l4Type != 'TCP':
|
||||
raise Exception( 'Unexpected l4 type: %s' % l4Type )
|
||||
server = host0.cmd( iperfArgs + '-s &' )
|
||||
if verbose:
|
||||
info( '%s\n' % server )
|
||||
log( '%s\n' % server )
|
||||
client = host1.cmd( iperfArgs + '-t 5 -c ' + host0.IP() + ' ' +
|
||||
bwArgs )
|
||||
if verbose:
|
||||
info( '%s\n' % client )
|
||||
log( '%s\n' % client )
|
||||
server = host0.cmd( 'killall -9 iperf' )
|
||||
if verbose:
|
||||
info( '%s\n' % server )
|
||||
log( '%s\n' % server )
|
||||
result = [ self._parseIperf( server ), self._parseIperf( client ) ]
|
||||
if l4Type == 'UDP':
|
||||
result.insert( 0, udpBw )
|
||||
info( '*** Results: %s\n' % result )
|
||||
log( '*** Results: %s\n' % result )
|
||||
return result
|
||||
|
||||
def iperfUdp( self, udpBw='10M' ):
|
||||
|
||||
+71
-48
@@ -40,8 +40,8 @@ import os
|
||||
import signal
|
||||
import select
|
||||
|
||||
from mininet.log import info, error
|
||||
from mininet.util import quietRun
|
||||
from mininet.log import info, error, debug
|
||||
from mininet.util import quietRun, moveIntf
|
||||
|
||||
|
||||
class Node( object ):
|
||||
@@ -72,13 +72,13 @@ class Node( object ):
|
||||
self.inToNode[ self.stdin.fileno() ] = self
|
||||
self.pid = self.shell.pid
|
||||
self.intfCount = 0
|
||||
self.intfs = [] # list of interface names, as strings
|
||||
self.intfs = {} # dict of port numbers to interface names
|
||||
self.ports = {} # dict of interface names to port numbers
|
||||
# replace with Port objects, eventually ?
|
||||
self.ips = {} # dict of interfaces to ip addresses as strings
|
||||
self.connection = {} # remote node connected to each interface
|
||||
self.waiting = False
|
||||
self.execed = False
|
||||
self.ports = {} # dict of ints to interface strings
|
||||
# replace with Port object, eventually
|
||||
|
||||
@classmethod
|
||||
def fdToNode( cls, fd ):
|
||||
@@ -145,11 +145,13 @@ class Node( object ):
|
||||
"Send ^C, hopefully interrupting an interactive subprocess."
|
||||
self.write( chr( 3 ) )
|
||||
|
||||
def waitOutput( self ):
|
||||
def waitOutput( self, verbose=False ):
|
||||
"""Wait for a command to complete.
|
||||
Completion is signaled by a sentinel character, ASCII(127)
|
||||
appearing in the output stream. Wait for the sentinel and return
|
||||
the output, including trailing newline."""
|
||||
the output, including trailing newline.
|
||||
verbose: print output interactively"""
|
||||
log = info if verbose else debug
|
||||
assert self.waiting
|
||||
output = ''
|
||||
while True:
|
||||
@@ -157,38 +159,60 @@ class Node( object ):
|
||||
data = self.read( 1024 )
|
||||
if len( data ) > 0 and data[ -1 ] == chr( 0177 ):
|
||||
output += data[ :-1 ]
|
||||
log( output )
|
||||
break
|
||||
else:
|
||||
output += data
|
||||
self.waiting = False
|
||||
return output
|
||||
|
||||
def cmd( self, cmd ):
|
||||
def cmd( self, cmd, verbose=False ):
|
||||
"""Send a command, wait for output, and return it.
|
||||
cmd: string"""
|
||||
log = info if verbose else debug
|
||||
log( '*** %s : %s', self.name, cmd )
|
||||
self.sendCmd( cmd )
|
||||
return self.waitOutput()
|
||||
return self.waitOutput( verbose )
|
||||
|
||||
def cmdPrint( self, cmd ):
|
||||
"""Call cmd and printing its output
|
||||
cmd: string"""
|
||||
#info( '*** %s : %s', self.name, cmd )
|
||||
result = self.cmd( cmd )
|
||||
#info( '%s\n', result )
|
||||
return result
|
||||
return self.cmd( cmd, verbose=True )
|
||||
|
||||
# Interface management, configuration, and routing
|
||||
|
||||
# BL notes: This might be a bit redundant or over-complicated.
|
||||
# However, it does allow a bit of specialization, including
|
||||
# changing the canonical interface names. It's also tricky since
|
||||
# the real interfaces are created as veth pairs, so we can't
|
||||
# make a single interface at a time.
|
||||
|
||||
def intfName( self, n ):
|
||||
"Construct a canonical interface name node-intf for interface N."
|
||||
"Construct a canonical interface name node-ethN for interface n."
|
||||
return self.name + '-eth' + repr( n )
|
||||
|
||||
def newIntf( self ):
|
||||
"Reserve and return a new interface name."
|
||||
intfName = self.intfName( self.intfCount )
|
||||
self.intfCount += 1
|
||||
self.intfs += [ intfName ]
|
||||
return intfName
|
||||
|
||||
def addIntf( self, intf, port ):
|
||||
"""Add an interface.
|
||||
intf: interface name (nodeN-ethM)
|
||||
port: port number (typically OpenFlow port number)"""
|
||||
self.intfs[ port ] = intf
|
||||
self.ports[ intf ] = port
|
||||
#info( '\n' )
|
||||
#info( 'added intf %s to node %x\n' % ( srcIntf, src ) )
|
||||
if self.inNamespace:
|
||||
#info( 'moving w/inNamespace set\n' )
|
||||
moveIntf( intf, self )
|
||||
|
||||
def connect( self, intf, dstNode, dstIntf ):
|
||||
"Register connection of intf to dstIntf on dstNode."
|
||||
self.connection[ intf ] = ( dstNode, dstIntf )
|
||||
|
||||
def setMAC( self, intf, mac ):
|
||||
"""Set the MAC address for an interface.
|
||||
mac: MAC address as string"""
|
||||
@@ -206,9 +230,9 @@ class Node( object ):
|
||||
|
||||
def setIP( self, intf, ip, bits ):
|
||||
"""Set the IP address for an interface.
|
||||
intf: string, interface name
|
||||
intf: interface name
|
||||
ip: IP address as a string
|
||||
bits:"""
|
||||
bits: prefix length of form /24"""
|
||||
result = self.cmd( [ 'ifconfig', intf, ip + bits, 'up' ] )
|
||||
self.ips[ intf ] = ip
|
||||
return result
|
||||
@@ -226,20 +250,19 @@ class Node( object ):
|
||||
return self.cmd( 'route add default ' + intf )
|
||||
|
||||
def IP( self ):
|
||||
"Return IP address of first interface"
|
||||
if len( self.intfs ) > 0:
|
||||
return self.ips.get( self.intfs[ 0 ], None )
|
||||
"Return IP address of interface 0"
|
||||
return self.ips.get( self.intfs.get( 0 , None ), None )
|
||||
|
||||
def intfIsUp( self ):
|
||||
"Check if one of our interfaces is up."
|
||||
return 'UP' in self.cmd( 'ifconfig ' + self.intfs[ 0 ] )
|
||||
def intfIsUp( self, port ):
|
||||
"""Check if interface for a given port number is up.
|
||||
port: port number"""
|
||||
return 'UP' in self.cmd( 'ifconfig ' + self.intfs[ port ] )
|
||||
|
||||
# Other methods
|
||||
def __str__( self ):
|
||||
result = self.name + ':'
|
||||
if self.IP():
|
||||
result += ' IP=' + self.IP()
|
||||
result += ' intfs=' + ','.join( self.intfs )
|
||||
result += ' IP=' + repr( self.IP() )
|
||||
result += ' intfs=' + ','.join( sorted( self.intfs.values() ) )
|
||||
result += ' waiting=' + repr( self.waiting )
|
||||
return result
|
||||
|
||||
@@ -282,17 +305,17 @@ class UserSwitch( Switch ):
|
||||
def start( self, controllers ):
|
||||
"""Start OpenFlow reference user datapath.
|
||||
Log to /tmp/sN-{ofd,ofp}.log.
|
||||
controllers: dict of controller names to objects"""
|
||||
controllers: list of controller objects"""
|
||||
controller = controllers[ 0 ]
|
||||
ofdlog = '/tmp/' + self.name + '-ofd.log'
|
||||
ofplog = '/tmp/' + self.name + '-ofp.log'
|
||||
self.cmd( 'ifconfig lo up' )
|
||||
intfs = self.intfs
|
||||
intfs = sorted( self.intfs.values() )
|
||||
|
||||
self.cmdPrint( 'ofdatapath -i ' + ','.join( intfs ) +
|
||||
self.cmd( 'ofdatapath -i ' + ','.join( intfs ) +
|
||||
' punix:/tmp/' + self.name +
|
||||
' 1> ' + ofdlog + ' 2> ' + ofdlog + ' &' )
|
||||
self.cmdPrint( 'ofprotocol unix:/tmp/' + self.name +
|
||||
self.cmd( 'ofprotocol unix:/tmp/' + self.name +
|
||||
' tcp:' + controller.IP() + ' --fail=closed' +
|
||||
' 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
||||
|
||||
@@ -322,20 +345,20 @@ class KernelSwitch( Switch ):
|
||||
# Delete local datapath if it exists;
|
||||
# then create a new one monitoring the given interfaces
|
||||
quietRun( 'dpctl deldp nl:%i' % self.dp )
|
||||
self.cmdPrint( 'dpctl adddp nl:%i' % self.dp )
|
||||
self.cmd( 'dpctl adddp nl:%i' % self.dp )
|
||||
if self.defaultMac:
|
||||
intf = 'of%i' % self.dp
|
||||
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', self.defaultMac ] )
|
||||
|
||||
if len( self.ports ) != max( self.ports.keys() ) + 1:
|
||||
if len( self.intfs ) != max( self.intfs ) + 1:
|
||||
raise Exception( 'only contiguous, zero-indexed port ranges'
|
||||
'supported: %s' % self.ports )
|
||||
intfs = [ self.ports[ port ] for port in self.ports.keys() ]
|
||||
self.cmdPrint( 'dpctl addif nl:' + str( self.dp ) + ' ' +
|
||||
'supported: %s' % self.intfs )
|
||||
intfs = [ self.intfs[ port ] for port in sorted( self.intfs.keys() ) ]
|
||||
self.cmd( 'dpctl addif nl:' + str( self.dp ) + ' ' +
|
||||
' '.join( intfs ) )
|
||||
# Run protocol daemon
|
||||
controller = controllers[ 0 ]
|
||||
self.cmdPrint( 'ofprotocol nl:' + str( self.dp ) + ' tcp:' +
|
||||
self.cmd( 'ofprotocol nl:' + str( self.dp ) + ' tcp:' +
|
||||
controller.IP() + ':' +
|
||||
str( controller.port ) +
|
||||
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
||||
@@ -345,11 +368,11 @@ class KernelSwitch( Switch ):
|
||||
"Terminate kernel datapath."
|
||||
quietRun( 'dpctl deldp nl:%i' % self.dp )
|
||||
# In theory the interfaces should go away after we shut down.
|
||||
# However, this takes time, so we're better off to remove them
|
||||
# However, this takes time, so we're better off removing them
|
||||
# explicitly so that we won't get errors if we run before they
|
||||
# have been removed by the kernel. Unfortunately this is very slow.
|
||||
self.cmd( 'kill %ofprotocol' )
|
||||
for intf in self.intfs:
|
||||
for intf in self.intfs.values():
|
||||
quietRun( 'ip link del ' + intf )
|
||||
info( '.' )
|
||||
|
||||
@@ -374,21 +397,21 @@ class OVSKernelSwitch( Switch ):
|
||||
# Delete local datapath if it exists;
|
||||
# then create a new one monitoring the given interfaces
|
||||
quietRun( 'ovs-dpctl del-dp dp%i' % self.dp )
|
||||
self.cmdPrint( 'ovs-dpctl add-dp dp%i' % self.dp )
|
||||
self.cmd( 'ovs-dpctl add-dp dp%i' % self.dp )
|
||||
if self.defaultMac:
|
||||
intf = 'dp' % self.dp
|
||||
mac = self.defaultMac
|
||||
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', mac ] )
|
||||
|
||||
if len( self.ports ) != max( self.ports.keys() ) + 1:
|
||||
if len( self.intfs ) != max( self.intfs ) + 1:
|
||||
raise Exception( 'only contiguous, zero-indexed port ranges'
|
||||
'supported: %s' % self.ports )
|
||||
intfs = [ self.ports[ port ] for port in self.ports.keys() ]
|
||||
self.cmdPrint( 'ovs-dpctl add-if dp' + str( self.dp ) + ' ' +
|
||||
'supported: %s' % self.intfs )
|
||||
intfs = [ self.intfs[ port ] for port in sorted( self.intfs.keys() ) ]
|
||||
self.cmd( 'ovs-dpctl add-if dp' + str( self.dp ) + ' ' +
|
||||
' '.join( intfs ) )
|
||||
# Run protocol daemon
|
||||
controller = controllers[ 0 ]
|
||||
self.cmdPrint( 'ovs-openflowd dp' + str( self.dp ) + ' tcp:' +
|
||||
self.cmd( 'ovs-openflowd dp' + str( self.dp ) + ' tcp:' +
|
||||
controller.IP() + ':' +
|
||||
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
||||
self.execed = False
|
||||
@@ -397,11 +420,11 @@ class OVSKernelSwitch( Switch ):
|
||||
"Terminate kernel datapath."
|
||||
quietRun( 'ovs-dpctl del-dp dp%i' % self.dp )
|
||||
# In theory the interfaces should go away after we shut down.
|
||||
# However, this takes time, so we're better off to remove them
|
||||
# However, this takes time, so we're better off removing them
|
||||
# explicitly so that we won't get errors if we run before they
|
||||
# have been removed by the kernel. Unfortunately this is very slow.
|
||||
self.cmd( 'kill %ovs-openflowd' )
|
||||
for intf in self.intfs:
|
||||
for intf in self.intfs.values():
|
||||
quietRun( 'ip link del ' + intf )
|
||||
info( '.' )
|
||||
|
||||
@@ -425,8 +448,8 @@ class Controller( Node ):
|
||||
Log to /tmp/cN.log"""
|
||||
cout = '/tmp/' + self.name + '.log'
|
||||
if self.cdir is not None:
|
||||
self.cmdPrint( 'cd ' + self.cdir )
|
||||
self.cmdPrint( self.controller + ' ' + self.cargs +
|
||||
self.cmd( 'cd ' + self.cdir )
|
||||
self.cmd( self.controller + ' ' + self.cargs +
|
||||
' 1> ' + cout + ' 2> ' + cout + ' &' )
|
||||
self.execed = False
|
||||
|
||||
|
||||
+15
-13
@@ -15,7 +15,7 @@ def run( cmd ):
|
||||
def checkRun( cmd ):
|
||||
"""Simple interface to subprocess.check_call()
|
||||
cmd: list of command params"""
|
||||
check_call( cmd.split( ' ' ) )
|
||||
return check_call( cmd.split( ' ' ) )
|
||||
|
||||
def quietRun( cmd ):
|
||||
"""Run a command, routing stderr to stdout, and return the output.
|
||||
@@ -63,7 +63,7 @@ def makeIntfPair( intf1, intf2 ):
|
||||
quietRun( 'ip link del ' + intf2 )
|
||||
# Create new pair
|
||||
cmd = 'ip link add name ' + intf1 + ' type veth peer name ' + intf2
|
||||
return checkRun( cmd )
|
||||
return quietRun( cmd )
|
||||
|
||||
def retry( retries, delaySecs, fn, *args, **keywords ):
|
||||
"""Try something several times before giving up.
|
||||
@@ -101,19 +101,20 @@ def moveIntf( intf, node, printError=False, retries=3, delaySecs=0.001 ):
|
||||
printError: if true, print error"""
|
||||
retry( retries, delaySecs, moveIntfNoRetry, intf, node, printError )
|
||||
|
||||
def createLink( node1, node2, retries=10, delaySecs=0.001 ):
|
||||
def createLink( node1, port1, node2, port2 ):
|
||||
"""Create a link between nodes, making an interface for each.
|
||||
node1: Node object
|
||||
node2: Node object"""
|
||||
intf1 = node1.newIntf()
|
||||
intf2 = node2.newIntf()
|
||||
port1: node1 port number
|
||||
node2: Node object
|
||||
port2: node2 port number
|
||||
returns: intf1 name, intf2 name"""
|
||||
intf1 = node1.intfName( port1 )
|
||||
intf2 = node2.intfName( port2 )
|
||||
makeIntfPair( intf1, intf2 )
|
||||
if node1.inNamespace:
|
||||
retry( retries, delaySecs, moveIntf, intf1, node1 )
|
||||
if node2.inNamespace:
|
||||
retry( retries, delaySecs, moveIntf, intf2, node2 )
|
||||
node1.connection[ intf1 ] = ( node2, intf2 )
|
||||
node2.connection[ intf2 ] = ( node1, intf1 )
|
||||
node1.addIntf( intf1, port1 )
|
||||
node2.addIntf( intf2, port2 )
|
||||
node1.connect( intf1, node2, intf2 )
|
||||
node2.connect( intf2, node1, intf1 )
|
||||
return intf1, intf2
|
||||
|
||||
def fixLimits():
|
||||
@@ -141,7 +142,8 @@ def macColonHex( mac ):
|
||||
|
||||
def ipStr( ip ):
|
||||
"""Generate IP address string
|
||||
returns: ip addr string"""
|
||||
ip: unsigned int of form x << 16 | y << 8 | z
|
||||
returns: ip address string 10.x.y.z """
|
||||
hi = ( ip & 0xff0000 ) >> 16
|
||||
mid = ( ip & 0xff00 ) >> 8
|
||||
lo = ip & 0xff
|
||||
|
||||
Reference in New Issue
Block a user