From 82f483f5591acd10c1def9d47489ab6494ccf2dc Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Fri, 9 Mar 2012 17:44:47 -0800 Subject: [PATCH] Add support for specifying host IP range with --ipbase. --- bin/mn | 4 ++++ mininet/net.py | 11 ++++++++--- mininet/topo.py | 31 ++++++++++++++++++++----------- mininet/util.py | 19 ++++++++++++++----- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/bin/mn b/bin/mn index 07bca4d..1768207 100755 --- a/bin/mn +++ b/bin/mn @@ -192,6 +192,8 @@ class MininetRunner( object ): help='|'.join( TESTS ) ) opts.add_option( '--xterms', '-x', action='store_true', default=False, help='spawn xterms for each node' ) + opts.add_option( '--ipbase', '-i', type='string', default='10.0.0.0/8', + help='base IP address for hosts' ) opts.add_option( '--mac', action='store_true', default=False, help='automatically set host MACs' ) opts.add_option( '--arp', action='store_true', @@ -248,6 +250,7 @@ class MininetRunner( object ): self.validate( self.options ) inNamespace = self.options.innamespace + ipBase = self.options.ipbase xterms = self.options.xterms mac = self.options.mac arp = self.options.arp @@ -257,6 +260,7 @@ class MininetRunner( object ): mn = Mininet( topo=topo, switch=switch, host=host, controller=controller, intf=intf, + ipBase=ipBase, inNamespace=inNamespace, xterms=xterms, autoSetMacs=mac, autoStaticArp=arp, listenPort=listenPort ) diff --git a/mininet/net.py b/mininet/net.py index 3fb2d3d..9e1e161 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -97,7 +97,7 @@ from mininet.log import info, error, debug, output from mininet.node import Host, OVSKernelSwitch, Controller from mininet.link import Link from mininet.util import quietRun, fixLimits -from mininet.util import macColonHex, ipStr, ipParse +from mininet.util import macColonHex, ipStr, ipParse, netParse from mininet.term import cleanUpScreens, makeTerms class Mininet( object ): @@ -105,7 +105,7 @@ class Mininet( object ): def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host, controller=Controller, link=Link, intf=None, - build=True, xterms=False, cleanup=False, + build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8', inNamespace=False, autoSetMacs=False, autoStaticArp=False, listenPort=None ): """Create Mininet object. @@ -130,6 +130,7 @@ class Mininet( object ): self.controller = controller self.link = link self.intf = intf + self.ipBase = ipBase self.inNamespace = inNamespace self.xterms = xterms self.cleanup = cleanup @@ -214,6 +215,8 @@ class Mininet( object ): At the end of this function, everything should be connected and up.""" + ipBaseNum, prefixLen = netParse( self.ipBase ) + if not topo: topo = self.topo() @@ -222,7 +225,9 @@ class Mininet( object ): name = prefix + topo.name( nodeId ) ni = topo.nodeInfo( nodeId ) # Default IP and MAC addresses - defaults = { 'ip': topo.ip( nodeId ) } + defaults = { 'ip': topo.ip( nodeId, + ipBaseNum=ipBaseNum, + prefixLen=prefixLen ) } if self.autoSetMacs: defaults[ 'mac'] = macColonHex( nodeId ) defaults.update( ni.params ) diff --git a/mininet/topo.py b/mininet/topo.py index 2cbfe7d..6b4e572 100644 --- a/mininet/topo.py +++ b/mininet/topo.py @@ -16,6 +16,7 @@ setup for testing, and can even be emulated with the Mininet package. # from networkx.classes.graph import Graph from networkx import Graph +from util import netParse, ipStr class NodeID(object): '''Topo node identifier.''' @@ -42,15 +43,22 @@ class NodeID(object): ''' return str(self.dpid) - def ip_str(self): + def ip_str(self, ipBase=None, prefixLen=8, ipBaseNum=0x0a000000): '''Name conversion. - + ipBase: optional base IP address string + prefixLen: optional IP prefix length + ipBaseNum: option base IP address as int @return ip ip as string ''' - hi = (self.dpid & 0xff0000) >> 16 - mid = (self.dpid & 0xff00) >> 8 - lo = self.dpid & 0xff - return "10.%i.%i.%i" % (hi, mid, lo) + if ipBase: + ipnum, prefixLen = netParse( ipBase ) + else: + ipBaseNum = ipBaseNum + # Ugly but functional + assert self.dpid < ( 1 << ( 32 - prefixLen ) ) + mask = 0xffffffff ^ ( ( 1 << prefixLen ) - 1 ) + ipnum = self.dpid + ( ipBaseNum & mask ) + return ipStr( ipnum ) class Node( object ): @@ -109,11 +117,12 @@ class Topo(object): per-topo classes per-network classes""" - def __init__(self, node=None, switch=None, link=None): + def __init__(self, node=None, switch=None, link=None ): """Create Topo object. node: default node/host class (optional) switch: default switch class (optional) - link: default link class (optional)""" + link: default link class (optional) + ipBase: default IP address base (optional)""" self.g = Graph() self.node_info = {} # dpids hash to Node objects self.edge_info = {} # (src_dpid, dst_dpid) tuples hash to Edge objects @@ -342,13 +351,13 @@ class Topo(object): ''' return self.id_gen(dpid = dpid).name_str() - def ip(self, dpid): + def ip(self, dpid, **params): '''Get IP dotted-decimal string of node ID. - @param dpid DPID of host or switch + @param params: params to pass to ip_str @return ip_str ''' - return self.id_gen(dpid = dpid).ip_str() + return self.id_gen(dpid = dpid).ip_str(**params) def nodeInfo( self, dpid ): "Return metadata for node" diff --git a/mininet/util.py b/mininet/util.py index 1a503e1..79b4a12 100644 --- a/mininet/util.py +++ b/mininet/util.py @@ -204,19 +204,19 @@ def macColonHex( mac ): returns: macStr MAC colon-hex string""" return _colonHex( mac, 6 ) -def ipStr( ip ): +def ipStr( ip, defaultNet=10 ): """Generate IP address string from an unsigned int. ip: unsigned int of form w << 24 | x << 16 | y << 8 | z returns: ip address string w.x.y.z, or 10.x.y.z if w==0""" - w = ( ip & 0xff000000 ) >> 24 + w = ( ip >> 24 ) & 0xff w = 10 if w == 0 else w - x = ( ip & 0xff0000 ) >> 16 - y = ( ip & 0xff00 ) >> 8 + x = ( ip >> 16 ) & 0xff + y = ( ip >> 8 ) & 0xff z = ip & 0xff return "%i.%i.%i.%i" % ( w, x, y, z ) def ipNum( w, x, y, z ): - """Generate unsigned int from components ofIP address + """Generate unsigned int from components of IP address returns: w << 24 | x << 16 | y << 8 | z""" return ( w << 24 ) | ( x << 16 ) | ( y << 8 ) | z @@ -225,6 +225,15 @@ def ipParse( ip ): args = [ int( arg ) for arg in ip.split( '.' ) ] return ipNum( *args ) +def netParse( ipstr ): + """Parse an IP network specification, returning + address and prefix len as unsigned ints""" + prefixLen = 0 + if '/' in ipstr: + ip, pf = ipstr.split( '/' ) + prefixLen = int( pf ) + return ipParse( ip ), prefixLen + def checkInt( s ): "Check if input string is an int" try: