Changed setIP to accept numeric prefix len. Added Node.deleteIntfs().
This commit is contained in:
+20
-24
@@ -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
@@ -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."
|
||||
|
||||
Reference in New Issue
Block a user