Changed setIP to accept numeric prefix len. Added Node.deleteIntfs().

This commit is contained in:
Bob Lantz
2010-03-04 16:53:39 -08:00
parent 48a8d297d1
commit 086ef80e8e
2 changed files with 70 additions and 69 deletions
+20 -24
View File
@@ -82,7 +82,8 @@ from time import sleep
from mininet.cli import CLI
from mininet.log import info, error, debug
from mininet.node import KernelSwitch, OVSKernelSwitch
from mininet.node import Host, KernelSwitch, OVSKernelSwitch, Controller
from mininet.node import ControllerParams
from mininet.util import quietRun, fixLimits
from mininet.util import createLink, macColonHex
from mininet.xterm import cleanUpScreens, makeXterms
@@ -105,7 +106,9 @@ def init():
class Mininet( object ):
"Network emulation with hosts spawned in network namespaces."
def __init__( self, topo, switch, host, controller, cparams,
def __init__( self, topo, switch=KernelSwitch, host=Host,
controller=Controller,
cparams=ControllerParams( '10.0.0.0', 8 ),
build=True, xterms=False, cleanup=False,
inNamespace=False,
autoSetMacs=False, autoStaticArp=False ):
@@ -143,29 +146,24 @@ class Mininet( object ):
if topo and build:
self.buildFromTopo( self.topo )
def addHost( self, name, defaultMac=None, defaultIp=None ):
def addHost( self, name, mac=None, ip=None ):
"""Add host.
name: name of host to add
defaultMac: default MAC address for intf 0
defaultIp: default IP address for intf 0
mac: default MAC address for intf 0
ip: default IP address for intf 0
returns: added host"""
host = self.host( name )
host = self.host( name, defaultMAC=mac, defaultIP=ip )
self.hosts.append( host )
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, name, defaultMac=None ):
def addSwitch( self, name, mac=None ):
"""Add switch.
name: name of switch to add
defaultMac: default MAC address for kernel/OVS switch intf 0
mac: default MAC address for kernel/OVS switch intf 0
returns: added switch"""
if self.switch is KernelSwitch or self.switch is OVSKernelSwitch:
sw = self.switch( name, dp=self.dps, defaultMac=defaultMac )
sw = self.switch( name, dp=self.dps, defaultMAC=mac )
self.dps += 1
else:
sw = self.switch( name )
@@ -225,9 +223,8 @@ class Mininet( object ):
'controller' %
switch.name )
exit( 1 )
controller.setIP( cintf, self.cparams.ip, '/' +
self.cparams.subnetSize )
switch.setIP( sintf, sip, '/' + self.cparams.subnetSize )
controller.setIP( cintf, self.cparams.ip, self.cparams.prefixLen )
switch.setIP( sintf, sip, self.cparams.prefixLen )
controller.setHostRoute( sip, cintf )
switch.setHostRoute( self.cparams.ip, sintf )
info( '\n' )
@@ -251,12 +248,11 @@ class Mininet( object ):
# params were: hosts, ips
for host in self.hosts:
hintf = host.intfs[ 0 ]
host.setIP( hintf, host.defaultIP,
'/' + str( self.cparams.subnetSize ) )
host.setIP( hintf, host.defaultIP, self.cparams.prefixLen )
host.setDefaultRoute( hintf )
# You're low priority, dude!
quietRun( 'renice +18 -p ' + repr( host.pid ) )
info( '%s ', host.name )
info( host.name + ' ' )
info( '\n' )
def buildFromTopo( self, topo ):
@@ -274,14 +270,14 @@ class Mininet( object ):
name = 'h' + topo.name( hostId )
mac = macColonHex( hostId ) if self.setMacs else None
ip = topo.ip( hostId )
host = self.addHost( name, defaultIp=ip, defaultMac=mac )
host = self.addHost( name, ip=ip, mac=mac )
self.idToNode[ hostId ] = host
info( name + ' ' )
info( '\n*** Adding switches:\n' )
for switchId in sorted( topo.switches() ):
name = 's' + topo.name( switchId )
mac = macColonHex( switchId) if self.setMacs else None
switch = self.addSwitch( name, defaultMac=mac )
switch = self.addSwitch( name, mac=mac )
self.idToNode[ switchId ] = switch
info( name + ' ' )
info( '\n*** Adding edges:\n' )
@@ -325,14 +321,14 @@ class Mininet( object ):
"""Set MAC addrs to correspond to datapath IDs on hosts.
Assume that the host only has one interface."""
for host in self.hosts:
host.setMAC( host.intfs[ 0 ], host.defaultMac )
host.setMAC( host.intfs[ 0 ], host.defaultMAC )
def staticArp( self ):
"Add all-pairs ARP entries to remove the need to handle broadcast."
for src in self.hosts:
for dst in self.hosts:
if src != dst:
src.setARP( ip=dst.IP(), mac=dst.defaultMac )
src.setARP( ip=dst.IP(), mac=dst.defaultMAC )
def start( self ):
"Start controller and switches"
+50 -45
View File
@@ -39,6 +39,7 @@ from subprocess import Popen, PIPE, STDOUT
import os
import signal
import select
from time import sleep
from mininet.log import info, error, debug
from mininet.util import quietRun, moveIntf
@@ -51,7 +52,12 @@ class Node( object ):
inToNode = {} # mapping of input fds to nodes
outToNode = {} # mapping of output fds to nodes
def __init__( self, name, inNamespace=True ):
def __init__( self, name, inNamespace=True,
defaultMAC=None, defaultIP=None ):
"""name: name of node
inNamespace: in network namespace?
defaultMAC: default MAC address for intf 0
defaultIP: default IP address for intf 0"""
self.name = name
closeFds = False # speed vs. memory use
# xpg_echo is needed so we can echo our sentinel in sendCmd
@@ -79,6 +85,8 @@ class Node( object ):
self.connection = {} # remote node connected to each interface
self.waiting = False
self.execed = False
self.defaultIP = defaultIP
self.defaultMAC = defaultMAC
@classmethod
def fdToNode( cls, fd ):
@@ -213,6 +221,19 @@ class Node( object ):
"Register connection of intf to dstIntf on dstNode."
self.connection[ intf ] = ( dstNode, dstIntf )
def deleteIntfs( self ):
"Delete all of our interfaces."
# In theory the interfaces should go away after we shut down.
# 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.values():
quietRun( 'ip link del ' + intf )
info( '.' )
# Does it help to sleep to let things run?
sleep( 0.001 )
def setMAC( self, intf, mac ):
"""Set the MAC address for an interface.
mac: MAC address as string"""
@@ -228,12 +249,13 @@ class Node( object ):
result = self.cmd( [ 'arp', '-s', ip, mac ] )
return result
def setIP( self, intf, ip, bits ):
def setIP( self, intf, ip, prefixLen ):
"""Set the IP address for an interface.
intf: interface name
ip: IP address as a string
bits: prefix length of form /24"""
result = self.cmd( [ 'ifconfig', intf, ip + bits, 'up' ] )
prefixLen: prefix length, e.g. 8 for /8 or 16M addrs"""
ipSub = '%s/%d' % ( ip, prefixLen )
result = self.cmd( [ 'ifconfig', intf, ipSub, 'up' ] )
self.ips[ intf ] = ip
return result
@@ -297,10 +319,10 @@ class UserSwitch( Switch ):
"""User-space switch.
Currently only works in the root namespace."""
def __init__( self, name ):
def __init__( self, name, *args, **kwargs ):
"""Init.
name: name for the switch"""
Switch.__init__( self, name, inNamespace=False )
Switch.__init__( self, name, inNamespace=False, **kwargs )
def start( self, controllers ):
"""Start OpenFlow reference user datapath.
@@ -323,20 +345,19 @@ class UserSwitch( Switch ):
"Stop OpenFlow reference user datapath."
self.cmd( 'kill %ofdatapath' )
self.cmd( 'kill %ofprotocol' )
self.deleteIntfs()
class KernelSwitch( Switch ):
"""Kernel-space switch.
Currently only works in the root namespace."""
def __init__( self, name, dp=None, defaultMac=None ):
def __init__( self, name, dp=None, **kwargs ):
"""Init.
name:
dp: netlink id (0, 1, 2, ...)
defaultMac: default MAC as string; random value if None"""
Switch.__init__( self, name, inNamespace=False )
defaultMAC: default MAC as string; random value if None"""
Switch.__init__( self, name, inNamespace=False, **kwargs )
self.dp = dp
self.defaultMac = defaultMac
def start( self, controllers ):
"Start up reference kernel datapath."
@@ -346,9 +367,9 @@ class KernelSwitch( Switch ):
# then create a new one monitoring the given interfaces
quietRun( 'dpctl deldp nl:%i' % self.dp )
self.cmd( 'dpctl adddp nl:%i' % self.dp )
if self.defaultMac:
if self.defaultMAC:
intf = 'of%i' % self.dp
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', self.defaultMac ] )
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', self.defaultMAC ] )
if len( self.intfs ) != max( self.intfs ) + 1:
raise Exception( 'only contiguous, zero-indexed port ranges'
@@ -367,28 +388,19 @@ class KernelSwitch( Switch ):
def stop( self ):
"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 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.values():
quietRun( 'ip link del ' + intf )
info( '.' )
self.deleteIntfs()
class OVSKernelSwitch( Switch ):
"""Open VSwitch kernel-space switch.
Currently only works in the root namespace."""
def __init__( self, name, dp=None, defaultMac=None ):
def __init__( self, name, dp=None, **kwargs ):
"""Init.
name:
dp: netlink id (0, 1, 2, ...)
dpid: datapath ID as unsigned int; random value if None"""
Switch.__init__( self, name, inNamespace=False )
Switch.__init__( self, name, inNamespace=False, **kwargs )
self.dp = dp
self.defaultMac = defaultMac
def start( self, controllers ):
"Start up kernel datapath."
@@ -398,9 +410,9 @@ class OVSKernelSwitch( Switch ):
# then create a new one monitoring the given interfaces
quietRun( 'ovs-dpctl del-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
mac = self.defaultMac
mac = self.defaultMAC
self.cmd( [ 'ifconfig', intf, 'hw', 'ether', mac ] )
if len( self.intfs ) != max( self.intfs ) + 1:
@@ -419,14 +431,7 @@ class OVSKernelSwitch( Switch ):
def stop( self ):
"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 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.values():
quietRun( 'ip link del ' + intf )
info( '.' )
self.deleteIntfs()
class Controller( Node ):
@@ -434,14 +439,14 @@ class Controller( Node ):
OpenFlow controller."""
def __init__( self, name, inNamespace=False, controller='controller',
cargs='-v ptcp:', cdir=None, ipAddress="127.0.0.1",
cargs='-v ptcp:', cdir=None, defaultIP="127.0.0.1",
port=6633 ):
self.controller = controller
self.cargs = cargs
self.cdir = cdir
self.ipAddress = ipAddress
self.port = port
Node.__init__( self, name, inNamespace=inNamespace )
Node.__init__( self, name, inNamespace=inNamespace,
defaultIP=defaultIP )
def start( self ):
"""Start <controller> <args> on controller.
@@ -460,18 +465,18 @@ class Controller( Node ):
def IP( self ):
"Return IP address of the Controller"
return self.ipAddress
return self.defaultIP
class ControllerParams( object ):
"Container for controller IP parameters."
def __init__( self, ip, subnetSize ):
def __init__( self, ip, prefixLen ):
"""Init.
ip: integer, controller IP
subnetSize: integer, ex 8 for slash-8, covering 17M"""
ip: string, controller IP address
prefixLen: prefix length, e.g. 8 for /8, covering 16M"""
self.ip = ip
self.subnetSize = subnetSize
self.prefixLen = prefixLen
class NOX( Controller ):
@@ -500,14 +505,14 @@ class NOX( Controller ):
class RemoteController( Controller ):
"Controller running outside of Mininet's control."
def __init__( self, name, inNamespace=False, ipAddress='127.0.0.1',
def __init__( self, name, inNamespace=False, defaultIP='127.0.0.1',
port=6633 ):
"""Init.
name: name to give controller
ipAddress: the IP address where the remote controller is
listening
port: the port where the remote controller is listening"""
Controller.__init__( self, name, ipAddress=ipAddress, port=port )
Controller.__init__( self, name, defaultIP=defaultIP, port=port )
def start( self ):
"Overridden to do nothing."