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.
|
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:'):
|
def scratchNet( cname='controller', cargs='ptcp:'):
|
||||||
# Create Network
|
# Create Network
|
||||||
controller = Node( 'c0', inNamespace=False )
|
print "*** creating Nodes"
|
||||||
switch = Node( 's0', inNamespace=False )
|
controller = Node( 'c0', inNamespace=False )
|
||||||
h0 = Node( 'h0' )
|
switch = Node( 's0', inNamespace=False )
|
||||||
h1 = Node( 'h1' )
|
h0 = Node( 'h0' )
|
||||||
createLink( h0, switch )
|
h1 = Node( 'h1' )
|
||||||
createLink( h1, switch )
|
print "*** creating links"
|
||||||
# Configure hosts
|
createLink( node1=h0, port1=0, node2=switch, port2=0 )
|
||||||
h0.setIP( h0.intfs[ 0 ], '192.168.123.1', '/24' )
|
createLink( node1=h1, port1=0, node2=switch, port2=1 )
|
||||||
h1.setIP( h1.intfs[ 0 ], '192.168.123.2', '/24' )
|
# Configure hosts
|
||||||
# Start network using kernel datapath
|
print "*** configuring hosts"
|
||||||
controller.cmdPrint( cname + ' ' + cargs + '&' )
|
h0.setIP( h0.intfs[ 0 ], '192.168.123.1', '/24' )
|
||||||
switch.cmdPrint( 'dpctl deldp nl:0' )
|
h1.setIP( h1.intfs[ 0 ], '192.168.123.2', '/24' )
|
||||||
switch.cmdPrint( 'dpctl adddp nl:0' )
|
print h0
|
||||||
for intf in switch.intfs:
|
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( 'dpctl addif nl:0 ' + intf )
|
||||||
switch.cmdPrint( 'ofprotocol nl:0 tcp:localhost &')
|
switch.cmdPrint( 'ofprotocol nl:0 tcp:localhost &')
|
||||||
# Run test
|
# Run test
|
||||||
h0.cmdPrint( 'ping -c1 ' + h1.IP() )
|
print h0.cmd( 'ping -c1 ' + h1.IP() )
|
||||||
# Stop network
|
# Stop network
|
||||||
controller.cmdPrint( 'kill %' + cname)
|
controller.cmdPrint( 'kill %' + cname)
|
||||||
switch.cmdPrint( 'dpctl deldp nl:0' )
|
switch.cmdPrint( 'dpctl deldp nl:0' )
|
||||||
switch.cmdPrint( 'kill %ofprotocol' )
|
switch.cmdPrint( 'kill %ofprotocol' )
|
||||||
switch.stop()
|
switch.stop()
|
||||||
controller.stop()
|
controller.stop()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
init()
|
info( '*** Scratch network demo\n' )
|
||||||
scratchNet()
|
init()
|
||||||
|
scratchNet()
|
||||||
|
|||||||
+11
-40
@@ -81,10 +81,10 @@ import signal
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from mininet.cli import CLI
|
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.node import KernelSwitch, OVSKernelSwitch
|
||||||
from mininet.util import quietRun, fixLimits
|
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
|
from mininet.xterm import cleanUpScreens, makeXterms
|
||||||
|
|
||||||
DATAPATHS = [ 'kernel' ] #[ 'user', 'kernel' ]
|
DATAPATHS = [ 'kernel' ] #[ 'user', 'kernel' ]
|
||||||
@@ -150,8 +150,6 @@ class Mininet( object ):
|
|||||||
defaultIp: default IP address for intf 0
|
defaultIp: default IP address for intf 0
|
||||||
returns: added host"""
|
returns: added host"""
|
||||||
host = self.host( name )
|
host = self.host( name )
|
||||||
# for now, assume one interface per host.
|
|
||||||
host.intfs.append( name + '-eth0' )
|
|
||||||
self.hosts.append( host )
|
self.hosts.append( host )
|
||||||
self.nameToNode[ name ] = host
|
self.nameToNode[ name ] = host
|
||||||
# May wish to add this to actual object
|
# May wish to add this to actual object
|
||||||
@@ -175,31 +173,6 @@ class Mininet( object ):
|
|||||||
self.nameToNode[ name ] = sw
|
self.nameToNode[ name ] = sw
|
||||||
return 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 ):
|
def addController( self, controller ):
|
||||||
"""Add controller.
|
"""Add controller.
|
||||||
controller: Controller class"""
|
controller: Controller class"""
|
||||||
@@ -315,7 +288,7 @@ class Mininet( object ):
|
|||||||
for srcId, dstId in sorted( topo.edges() ):
|
for srcId, dstId in sorted( topo.edges() ):
|
||||||
src, dst = self.idToNode[ srcId ], self.idToNode[ dstId ]
|
src, dst = self.idToNode[ srcId ], self.idToNode[ dstId ]
|
||||||
srcPort, dstPort = topo.port( srcId, 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( '(%s, %s) ' % ( src.name, dst.name ) )
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
@@ -368,7 +341,7 @@ class Mininet( object ):
|
|||||||
controller.start()
|
controller.start()
|
||||||
info( '*** Starting %s switches\n' % len( self.switches ) )
|
info( '*** Starting %s switches\n' % len( self.switches ) )
|
||||||
for switch in self.switches:
|
for switch in self.switches:
|
||||||
info( switch.name )
|
info( switch.name + ' ')
|
||||||
switch.start( self.controllers )
|
switch.start( self.controllers )
|
||||||
info( '\n' )
|
info( '\n' )
|
||||||
|
|
||||||
@@ -474,13 +447,14 @@ class Mininet( object ):
|
|||||||
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"""
|
||||||
|
log = info if verbose else debug
|
||||||
if not hosts:
|
if not hosts:
|
||||||
hosts = [ self.hosts[ 0 ], self.hosts[ -1 ] ]
|
hosts = [ self.hosts[ 0 ], self.hosts[ -1 ] ]
|
||||||
else:
|
else:
|
||||||
assert len( hosts ) == 2
|
assert len( hosts ) == 2
|
||||||
host0, host1 = hosts
|
host0, host1 = hosts
|
||||||
info( '*** Iperf: testing ' + l4Type + ' bandwidth between ' )
|
log( '*** Iperf: testing ' + l4Type + ' bandwidth between ' )
|
||||||
info( "%s and %s\n" % ( host0.name, host1.name ) )
|
log( "%s and %s\n" % ( host0.name, host1.name ) )
|
||||||
host0.cmd( 'killall -9 iperf' )
|
host0.cmd( 'killall -9 iperf' )
|
||||||
iperfArgs = 'iperf '
|
iperfArgs = 'iperf '
|
||||||
bwArgs = ''
|
bwArgs = ''
|
||||||
@@ -490,19 +464,16 @@ class Mininet( object ):
|
|||||||
elif l4Type != 'TCP':
|
elif l4Type != 'TCP':
|
||||||
raise Exception( 'Unexpected l4 type: %s' % l4Type )
|
raise Exception( 'Unexpected l4 type: %s' % l4Type )
|
||||||
server = host0.cmd( iperfArgs + '-s &' )
|
server = host0.cmd( iperfArgs + '-s &' )
|
||||||
if verbose:
|
log( '%s\n' % server )
|
||||||
info( '%s\n' % server )
|
|
||||||
client = host1.cmd( iperfArgs + '-t 5 -c ' + host0.IP() + ' ' +
|
client = host1.cmd( iperfArgs + '-t 5 -c ' + host0.IP() + ' ' +
|
||||||
bwArgs )
|
bwArgs )
|
||||||
if verbose:
|
log( '%s\n' % client )
|
||||||
info( '%s\n' % client )
|
|
||||||
server = host0.cmd( 'killall -9 iperf' )
|
server = host0.cmd( 'killall -9 iperf' )
|
||||||
if verbose:
|
log( '%s\n' % server )
|
||||||
info( '%s\n' % server )
|
|
||||||
result = [ self._parseIperf( server ), self._parseIperf( client ) ]
|
result = [ self._parseIperf( server ), self._parseIperf( client ) ]
|
||||||
if l4Type == 'UDP':
|
if l4Type == 'UDP':
|
||||||
result.insert( 0, udpBw )
|
result.insert( 0, udpBw )
|
||||||
info( '*** Results: %s\n' % result )
|
log( '*** Results: %s\n' % result )
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def iperfUdp( self, udpBw='10M' ):
|
def iperfUdp( self, udpBw='10M' ):
|
||||||
|
|||||||
+71
-48
@@ -40,8 +40,8 @@ import os
|
|||||||
import signal
|
import signal
|
||||||
import select
|
import select
|
||||||
|
|
||||||
from mininet.log import info, error
|
from mininet.log import info, error, debug
|
||||||
from mininet.util import quietRun
|
from mininet.util import quietRun, moveIntf
|
||||||
|
|
||||||
|
|
||||||
class Node( object ):
|
class Node( object ):
|
||||||
@@ -72,13 +72,13 @@ class Node( object ):
|
|||||||
self.inToNode[ self.stdin.fileno() ] = self
|
self.inToNode[ self.stdin.fileno() ] = self
|
||||||
self.pid = self.shell.pid
|
self.pid = self.shell.pid
|
||||||
self.intfCount = 0
|
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.ips = {} # dict of interfaces to ip addresses as strings
|
||||||
self.connection = {} # remote node connected to each interface
|
self.connection = {} # remote node connected to each interface
|
||||||
self.waiting = False
|
self.waiting = False
|
||||||
self.execed = False
|
self.execed = False
|
||||||
self.ports = {} # dict of ints to interface strings
|
|
||||||
# replace with Port object, eventually
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fdToNode( cls, fd ):
|
def fdToNode( cls, fd ):
|
||||||
@@ -145,11 +145,13 @@ class Node( object ):
|
|||||||
"Send ^C, hopefully interrupting an interactive subprocess."
|
"Send ^C, hopefully interrupting an interactive subprocess."
|
||||||
self.write( chr( 3 ) )
|
self.write( chr( 3 ) )
|
||||||
|
|
||||||
def waitOutput( self ):
|
def waitOutput( self, verbose=False ):
|
||||||
"""Wait for a command to complete.
|
"""Wait for a command to complete.
|
||||||
Completion is signaled by a sentinel character, ASCII(127)
|
Completion is signaled by a sentinel character, ASCII(127)
|
||||||
appearing in the output stream. Wait for the sentinel and return
|
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
|
assert self.waiting
|
||||||
output = ''
|
output = ''
|
||||||
while True:
|
while True:
|
||||||
@@ -157,38 +159,60 @@ class Node( object ):
|
|||||||
data = self.read( 1024 )
|
data = self.read( 1024 )
|
||||||
if len( data ) > 0 and data[ -1 ] == chr( 0177 ):
|
if len( data ) > 0 and data[ -1 ] == chr( 0177 ):
|
||||||
output += data[ :-1 ]
|
output += data[ :-1 ]
|
||||||
|
log( output )
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
output += data
|
output += data
|
||||||
self.waiting = False
|
self.waiting = False
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def cmd( self, cmd ):
|
def cmd( self, cmd, verbose=False ):
|
||||||
"""Send a command, wait for output, and return it.
|
"""Send a command, wait for output, and return it.
|
||||||
cmd: string"""
|
cmd: string"""
|
||||||
|
log = info if verbose else debug
|
||||||
|
log( '*** %s : %s', self.name, cmd )
|
||||||
self.sendCmd( cmd )
|
self.sendCmd( cmd )
|
||||||
return self.waitOutput()
|
return self.waitOutput( verbose )
|
||||||
|
|
||||||
def cmdPrint( self, cmd ):
|
def cmdPrint( self, cmd ):
|
||||||
"""Call cmd and printing its output
|
"""Call cmd and printing its output
|
||||||
cmd: string"""
|
cmd: string"""
|
||||||
#info( '*** %s : %s', self.name, cmd )
|
return self.cmd( cmd, verbose=True )
|
||||||
result = self.cmd( cmd )
|
|
||||||
#info( '%s\n', result )
|
|
||||||
return result
|
|
||||||
|
|
||||||
# Interface management, configuration, and routing
|
# 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 ):
|
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 )
|
return self.name + '-eth' + repr( n )
|
||||||
|
|
||||||
def newIntf( self ):
|
def newIntf( self ):
|
||||||
"Reserve and return a new interface name."
|
"Reserve and return a new interface name."
|
||||||
intfName = self.intfName( self.intfCount )
|
intfName = self.intfName( self.intfCount )
|
||||||
self.intfCount += 1
|
self.intfCount += 1
|
||||||
self.intfs += [ intfName ]
|
|
||||||
return 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 ):
|
def setMAC( self, intf, mac ):
|
||||||
"""Set the MAC address for an interface.
|
"""Set the MAC address for an interface.
|
||||||
mac: MAC address as string"""
|
mac: MAC address as string"""
|
||||||
@@ -206,9 +230,9 @@ class Node( object ):
|
|||||||
|
|
||||||
def setIP( self, intf, ip, bits ):
|
def setIP( self, intf, ip, bits ):
|
||||||
"""Set the IP address for an interface.
|
"""Set the IP address for an interface.
|
||||||
intf: string, interface name
|
intf: interface name
|
||||||
ip: IP address as a string
|
ip: IP address as a string
|
||||||
bits:"""
|
bits: prefix length of form /24"""
|
||||||
result = self.cmd( [ 'ifconfig', intf, ip + bits, 'up' ] )
|
result = self.cmd( [ 'ifconfig', intf, ip + bits, 'up' ] )
|
||||||
self.ips[ intf ] = ip
|
self.ips[ intf ] = ip
|
||||||
return result
|
return result
|
||||||
@@ -226,20 +250,19 @@ class Node( object ):
|
|||||||
return self.cmd( 'route add default ' + intf )
|
return self.cmd( 'route add default ' + intf )
|
||||||
|
|
||||||
def IP( self ):
|
def IP( self ):
|
||||||
"Return IP address of first interface"
|
"Return IP address of interface 0"
|
||||||
if len( self.intfs ) > 0:
|
return self.ips.get( self.intfs.get( 0 , None ), None )
|
||||||
return self.ips.get( self.intfs[ 0 ], None )
|
|
||||||
|
|
||||||
def intfIsUp( self ):
|
def intfIsUp( self, port ):
|
||||||
"Check if one of our interfaces is up."
|
"""Check if interface for a given port number is up.
|
||||||
return 'UP' in self.cmd( 'ifconfig ' + self.intfs[ 0 ] )
|
port: port number"""
|
||||||
|
return 'UP' in self.cmd( 'ifconfig ' + self.intfs[ port ] )
|
||||||
|
|
||||||
# Other methods
|
# Other methods
|
||||||
def __str__( self ):
|
def __str__( self ):
|
||||||
result = self.name + ':'
|
result = self.name + ':'
|
||||||
if self.IP():
|
result += ' IP=' + repr( self.IP() )
|
||||||
result += ' IP=' + self.IP()
|
result += ' intfs=' + ','.join( sorted( self.intfs.values() ) )
|
||||||
result += ' intfs=' + ','.join( self.intfs )
|
|
||||||
result += ' waiting=' + repr( self.waiting )
|
result += ' waiting=' + repr( self.waiting )
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -282,17 +305,17 @@ class UserSwitch( Switch ):
|
|||||||
def start( self, controllers ):
|
def start( self, controllers ):
|
||||||
"""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: list of controller objects"""
|
||||||
controller = controllers[ 0 ]
|
controller = controllers[ 0 ]
|
||||||
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' )
|
||||||
intfs = self.intfs
|
intfs = sorted( self.intfs.values() )
|
||||||
|
|
||||||
self.cmdPrint( 'ofdatapath -i ' + ','.join( intfs ) +
|
self.cmd( 'ofdatapath -i ' + ','.join( intfs ) +
|
||||||
' punix:/tmp/' + self.name +
|
' punix:/tmp/' + self.name +
|
||||||
' 1> ' + ofdlog + ' 2> ' + ofdlog + ' &' )
|
' 1> ' + ofdlog + ' 2> ' + ofdlog + ' &' )
|
||||||
self.cmdPrint( 'ofprotocol unix:/tmp/' + self.name +
|
self.cmd( 'ofprotocol unix:/tmp/' + self.name +
|
||||||
' tcp:' + controller.IP() + ' --fail=closed' +
|
' tcp:' + controller.IP() + ' --fail=closed' +
|
||||||
' 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
' 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
||||||
|
|
||||||
@@ -322,20 +345,20 @@ class KernelSwitch( Switch ):
|
|||||||
# Delete local datapath if it exists;
|
# Delete local datapath if it exists;
|
||||||
# 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.cmd( 'dpctl adddp nl:%i' % self.dp )
|
||||||
if self.defaultMac:
|
if self.defaultMac:
|
||||||
intf = 'of%i' % self.dp
|
intf = 'of%i' % self.dp
|
||||||
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', self.defaultMac ] )
|
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'
|
raise Exception( 'only contiguous, zero-indexed port ranges'
|
||||||
'supported: %s' % self.ports )
|
'supported: %s' % self.intfs )
|
||||||
intfs = [ self.ports[ port ] for port in self.ports.keys() ]
|
intfs = [ self.intfs[ port ] for port in sorted( self.intfs.keys() ) ]
|
||||||
self.cmdPrint( 'dpctl addif nl:' + str( self.dp ) + ' ' +
|
self.cmd( 'dpctl addif nl:' + str( self.dp ) + ' ' +
|
||||||
' '.join( intfs ) )
|
' '.join( intfs ) )
|
||||||
# Run protocol daemon
|
# Run protocol daemon
|
||||||
controller = controllers[ 0 ]
|
controller = controllers[ 0 ]
|
||||||
self.cmdPrint( 'ofprotocol nl:' + str( self.dp ) + ' tcp:' +
|
self.cmd( 'ofprotocol nl:' + str( self.dp ) + ' tcp:' +
|
||||||
controller.IP() + ':' +
|
controller.IP() + ':' +
|
||||||
str( controller.port ) +
|
str( controller.port ) +
|
||||||
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
||||||
@@ -345,11 +368,11 @@ class KernelSwitch( Switch ):
|
|||||||
"Terminate kernel datapath."
|
"Terminate kernel datapath."
|
||||||
quietRun( 'dpctl deldp nl:%i' % self.dp )
|
quietRun( 'dpctl deldp nl:%i' % self.dp )
|
||||||
# In theory the interfaces should go away after we shut down.
|
# 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
|
# explicitly so that we won't get errors if we run before they
|
||||||
# have been removed by the kernel. Unfortunately this is very slow.
|
# have been removed by the kernel. Unfortunately this is very slow.
|
||||||
self.cmd( 'kill %ofprotocol' )
|
self.cmd( 'kill %ofprotocol' )
|
||||||
for intf in self.intfs:
|
for intf in self.intfs.values():
|
||||||
quietRun( 'ip link del ' + intf )
|
quietRun( 'ip link del ' + intf )
|
||||||
info( '.' )
|
info( '.' )
|
||||||
|
|
||||||
@@ -374,21 +397,21 @@ class OVSKernelSwitch( Switch ):
|
|||||||
# Delete local datapath if it exists;
|
# Delete local datapath if it exists;
|
||||||
# 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.cmd( 'ovs-dpctl add-dp dp%i' % self.dp )
|
||||||
if self.defaultMac:
|
if self.defaultMac:
|
||||||
intf = 'dp' % self.dp
|
intf = 'dp' % self.dp
|
||||||
mac = self.defaultMac
|
mac = self.defaultMac
|
||||||
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', mac ] )
|
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'
|
raise Exception( 'only contiguous, zero-indexed port ranges'
|
||||||
'supported: %s' % self.ports )
|
'supported: %s' % self.intfs )
|
||||||
intfs = [ self.ports[ port ] for port in self.ports.keys() ]
|
intfs = [ self.intfs[ port ] for port in sorted( self.intfs.keys() ) ]
|
||||||
self.cmdPrint( 'ovs-dpctl add-if dp' + str( self.dp ) + ' ' +
|
self.cmd( 'ovs-dpctl add-if dp' + str( self.dp ) + ' ' +
|
||||||
' '.join( intfs ) )
|
' '.join( intfs ) )
|
||||||
# Run protocol daemon
|
# Run protocol daemon
|
||||||
controller = controllers[ 0 ]
|
controller = controllers[ 0 ]
|
||||||
self.cmdPrint( 'ovs-openflowd dp' + str( self.dp ) + ' tcp:' +
|
self.cmd( 'ovs-openflowd dp' + str( self.dp ) + ' tcp:' +
|
||||||
controller.IP() + ':' +
|
controller.IP() + ':' +
|
||||||
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
' --fail=closed 1> ' + ofplog + ' 2>' + ofplog + ' &' )
|
||||||
self.execed = False
|
self.execed = False
|
||||||
@@ -397,11 +420,11 @@ class OVSKernelSwitch( Switch ):
|
|||||||
"Terminate kernel datapath."
|
"Terminate kernel datapath."
|
||||||
quietRun( 'ovs-dpctl del-dp dp%i' % self.dp )
|
quietRun( 'ovs-dpctl del-dp dp%i' % self.dp )
|
||||||
# In theory the interfaces should go away after we shut down.
|
# 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
|
# explicitly so that we won't get errors if we run before they
|
||||||
# have been removed by the kernel. Unfortunately this is very slow.
|
# have been removed by the kernel. Unfortunately this is very slow.
|
||||||
self.cmd( 'kill %ovs-openflowd' )
|
self.cmd( 'kill %ovs-openflowd' )
|
||||||
for intf in self.intfs:
|
for intf in self.intfs.values():
|
||||||
quietRun( 'ip link del ' + intf )
|
quietRun( 'ip link del ' + intf )
|
||||||
info( '.' )
|
info( '.' )
|
||||||
|
|
||||||
@@ -425,8 +448,8 @@ class Controller( Node ):
|
|||||||
Log to /tmp/cN.log"""
|
Log to /tmp/cN.log"""
|
||||||
cout = '/tmp/' + self.name + '.log'
|
cout = '/tmp/' + self.name + '.log'
|
||||||
if self.cdir is not None:
|
if self.cdir is not None:
|
||||||
self.cmdPrint( 'cd ' + self.cdir )
|
self.cmd( 'cd ' + self.cdir )
|
||||||
self.cmdPrint( self.controller + ' ' + self.cargs +
|
self.cmd( self.controller + ' ' + self.cargs +
|
||||||
' 1> ' + cout + ' 2> ' + cout + ' &' )
|
' 1> ' + cout + ' 2> ' + cout + ' &' )
|
||||||
self.execed = False
|
self.execed = False
|
||||||
|
|
||||||
|
|||||||
+15
-13
@@ -15,7 +15,7 @@ def run( cmd ):
|
|||||||
def checkRun( cmd ):
|
def checkRun( cmd ):
|
||||||
"""Simple interface to subprocess.check_call()
|
"""Simple interface to subprocess.check_call()
|
||||||
cmd: list of command params"""
|
cmd: list of command params"""
|
||||||
check_call( cmd.split( ' ' ) )
|
return check_call( cmd.split( ' ' ) )
|
||||||
|
|
||||||
def quietRun( cmd ):
|
def quietRun( cmd ):
|
||||||
"""Run a command, routing stderr to stdout, and return the output.
|
"""Run a command, routing stderr to stdout, and return the output.
|
||||||
@@ -63,7 +63,7 @@ def makeIntfPair( intf1, intf2 ):
|
|||||||
quietRun( 'ip link del ' + intf2 )
|
quietRun( 'ip link del ' + intf2 )
|
||||||
# Create new pair
|
# Create new pair
|
||||||
cmd = 'ip link add name ' + intf1 + ' type veth peer name ' + intf2
|
cmd = 'ip link add name ' + intf1 + ' type veth peer name ' + intf2
|
||||||
return checkRun( cmd )
|
return quietRun( cmd )
|
||||||
|
|
||||||
def retry( retries, delaySecs, fn, *args, **keywords ):
|
def retry( retries, delaySecs, fn, *args, **keywords ):
|
||||||
"""Try something several times before giving up.
|
"""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"""
|
printError: if true, print error"""
|
||||||
retry( retries, delaySecs, moveIntfNoRetry, intf, node, printError )
|
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.
|
"""Create a link between nodes, making an interface for each.
|
||||||
node1: Node object
|
node1: Node object
|
||||||
node2: Node object"""
|
port1: node1 port number
|
||||||
intf1 = node1.newIntf()
|
node2: Node object
|
||||||
intf2 = node2.newIntf()
|
port2: node2 port number
|
||||||
|
returns: intf1 name, intf2 name"""
|
||||||
|
intf1 = node1.intfName( port1 )
|
||||||
|
intf2 = node2.intfName( port2 )
|
||||||
makeIntfPair( intf1, intf2 )
|
makeIntfPair( intf1, intf2 )
|
||||||
if node1.inNamespace:
|
node1.addIntf( intf1, port1 )
|
||||||
retry( retries, delaySecs, moveIntf, intf1, node1 )
|
node2.addIntf( intf2, port2 )
|
||||||
if node2.inNamespace:
|
node1.connect( intf1, node2, intf2 )
|
||||||
retry( retries, delaySecs, moveIntf, intf2, node2 )
|
node2.connect( intf2, node1, intf1 )
|
||||||
node1.connection[ intf1 ] = ( node2, intf2 )
|
|
||||||
node2.connection[ intf2 ] = ( node1, intf1 )
|
|
||||||
return intf1, intf2
|
return intf1, intf2
|
||||||
|
|
||||||
def fixLimits():
|
def fixLimits():
|
||||||
@@ -141,7 +142,8 @@ def macColonHex( mac ):
|
|||||||
|
|
||||||
def ipStr( ip ):
|
def ipStr( ip ):
|
||||||
"""Generate IP address string
|
"""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
|
hi = ( ip & 0xff0000 ) >> 16
|
||||||
mid = ( ip & 0xff00 ) >> 8
|
mid = ( ip & 0xff00 ) >> 8
|
||||||
lo = ip & 0xff
|
lo = ip & 0xff
|
||||||
|
|||||||
Reference in New Issue
Block a user