diff --git a/INSTALL b/INSTALL index cf47bde08831139705fed44beb32df1be6dd3ba1..1542ee42bc187641ebf939e39d35c97e88e8e54d 100644 --- a/INSTALL +++ b/INSTALL @@ -59,31 +59,15 @@ Preliminary Mininet Installation/Configuration Notes upon, and an example provided, in the future.) - For scalable configurations, you might need to increase some of your - kernel limits. For example, you could add something like the following - to /etc/sysctl.conf (modified as necessary for your desired + kernel limits. Sample params are in sysctl_addon, which can be appended to + /etc/sysctl.conf (and modified as necessary for your desired configuration): - # Mininet: Increase open file limit - fs.file-max = 100000 - - # Mininet: increase network buffer space - net.core.wmem_max = 16777216 - net.core.rmem_max = 16777216 - net.ipv4.tcp_rmem = 10240 87380 16777216 - net.ipv4.tcp_rmem = 10240 87380 16777216 - net.core.netdev_max_backlog = 5000 - - # Mininet: increase arp cache size - net.ipv4.neigh.default.gc_thresh1 = 4096 - net.ipv4.neigh.default.gc_thresh2 = 8192 - net.ipv4.neigh.default.gc_thresh3 = 16384 - - # Mininet: increase routing table size - net.ipv4.route.max_size=32768 + sudo su -c "cat sysctl_addon >> /etc/sysctl.conf" To save the config change, run: - sysctl -p + sudo sysctl -p --- diff --git a/bin/mn b/bin/mn index d0b0b6b80b337d4c71ac5f75490495962e89e338..a8ae5a85b29ca8cefea5926d9aedda847cbbed8e 100755 --- a/bin/mn +++ b/bin/mn @@ -3,18 +3,19 @@ """ Mininet runner author: Brandon Heller (brandonh@stanford.edu) + +To see options: + sudo mn -h + +Example to pull custom params (topo, switch, etc.) from a file: + sudo mn --custom ~/mininet/custom/custom_example.py """ from optparse import OptionParser import os.path +import sys import time -try: - from ripcord.dctopo import TreeTopo, FatTreeTopo, VL2Topo - USERIPCORD = True -except ImportError: - USERIPCORD = False - from mininet.log import lg, LEVELS from mininet.net import Mininet, init from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX @@ -29,16 +30,6 @@ TOPOS = { 'minimal': ( lambda: SingleSwitchTopo( k=2 ) ), 'single100': ( lambda: SingleSwitchTopo( k=100 ) ), 'linear2': ( lambda: LinearTopo( k=2 ) ), 'linear100': ( lambda: LinearTopo( k=100 ) ) } -if USERIPCORD: - TOPOSRIPCORD = { - 'tree16': ( lambda: TreeTopo( depth=3, fanout=4 ) ), - 'tree64': ( lambda: TreeTopo( depth=4, fanout=4 ) ), - 'tree1024': ( lambda: TreeTopo( depth=3, fanout=32 ) ), - 'fattree4': ( lambda: FatTreeTopo( k=4 ) ), - 'fattree6': ( lambda: FatTreeTopo( k=6 ) ), - 'vl2': ( lambda: VL2Topo( da=4, di=4 ) ), - 'vl2reduced': ( lambda: VL2Topo( da=4, di=4, edgeDown=1 ) ) } - TOPOS.update( TOPOSRIPCORD ) SWITCHDEF = 'kernel' SWITCHES = { 'kernel': KernelSwitch, @@ -57,8 +48,7 @@ CONTROLLERS = { 'ref': Controller, 'none': lambda a, b: None } # optional tests to run -TESTS = [ 'cli', 'build', 'pingAll', 'pingPair', 'iperf', 'all', - 'iperfUdp' ] +TESTS = [ 'cli', 'build', 'pingAll', 'pingPair', 'iperf', 'all', 'iperfUdp' ] def addDictOption( opts, choicesDict, default, name, helpStr=None ): @@ -86,14 +76,37 @@ class MininetRunner( object ): def __init__( self ): "Init." self.options = None + self.validate = None self.parseArgs() self.setup() self.begin() + def parseCustomFile( self, custom ): + "Parse custom file and add params before parsing cmd-line options." + if os.path.isfile( custom ): + execfile( custom, globals(), globals() ) + if 'topos' in globals(): TOPOS.update( topos ) + if 'switches' in globals(): SWITCHES.update( switches ) + if 'hosts' in globals(): HOSTS.update( hosts ) + if 'controllers' in globals(): CONTROLLERS.update( controllers ) + if 'validate' in globals(): self.validate = validate + else: + raise Exception( 'could not find custom file: %s' % custom ) + def parseArgs( self ): """Parse command-line args and return options object. returns: opts parse options dict""" + if '--custom' in sys.argv: + print "custom in sys.argv" + index = sys.argv.index( '--custom' ) + if len( sys.argv ) > index + 1: + custom = sys.argv[ index + 1 ] + print "custom = %s" % custom + self.parseCustomFile( custom ) + else: + raise Exception( 'Custom file name not found' ) + opts = OptionParser() addDictOption( opts, TOPOS, TOPODEF, 'topo' ) addDictOption( opts, SWITCHES, SWITCHDEF, 'switch' ) @@ -101,7 +114,7 @@ class MininetRunner( object ): addDictOption( opts, CONTROLLERS, CONTROLLERDEF, 'controller' ) opts.add_option( '--custom', type='string', default=None, - help='read custom mininet from current dir' ) + help='read custom topo and node params from .py file' ) opts.add_option( '--test', type='choice', choices=TESTS, default=TESTS[ 0 ], help='[' + ' '.join( TESTS ) + ']' ) @@ -133,18 +146,6 @@ class MininetRunner( object ): # validate environment setup init() - # check for invalid combinations - if ( self.options.controller == 'ref' and - ( ( 'fattree' in self.options.topo ) or - ( 'vl2' in self.options.topo ) ) ): - raise Exception( 'multipath topos require multipath-capable ' - 'controller.' ) - - if self.options.custom: - if not os.path.isfile( self.options.custom ): - raise Exception( 'could not find custom file: %s' % - self.options.custom ) - def begin( self ): "Create and run mininet." @@ -159,25 +160,18 @@ class MininetRunner( object ): ipAddress=self.options.ip, port=self.options.port ) + if self.validate: + self.validate(self.options) + controllerParams = ControllerParams( 0x0a000000, 8 ) # 10.0.0.0/8 inNamespace = self.options.inNamespace xterms = self.options.xterms mac = self.options.mac arp = self.options.arp - mn = None - if not self.options.custom: - mn = Mininet( topo, switch, host, controller, controllerParams, - inNamespace=inNamespace, - xterms=xterms, autoSetMacs=mac, - autoStaticArp=arp ) - else: - globals_ = {} - locals_ = {} - execfile( self.options.custom, globals_, locals_ ) - if 'mn' not in locals_: - raise Exception( 'could not find mn var in custom file' ) - else: - mn = locals_[ 'mn' ] + mn = Mininet( topo, switch, host, controller, controllerParams, + inNamespace=inNamespace, + xterms=xterms, autoSetMacs=mac, + autoStaticArp=arp ) test = self.options.test if test != 'build': diff --git a/custom/custom_example.py b/custom/custom_example.py index 9670890f88e09d2904f3411cf662fb98638402a2..49e23942cd7bf89e31376e64ee783bb038f2a565 100644 --- a/custom/custom_example.py +++ b/custom/custom_example.py @@ -1,25 +1,45 @@ -'''Example of custom topo +"""Custom topology example -@author Brandon Heller (brandonh@stanford.edu) +author: Brandon Heller (brandonh@stanford.edu) -''' +Two directly connected switches plus a host for each switch: -from mininet.topo import SingleSwitchTopo -from mininet.net import Mininet -from mininet.node import KernelSwitch, Host, Controller, ControllerParams + host --- switch --- switch --- host -topo = SingleSwitchTopo(k = 2) # build topology object -switch = KernelSwitch -host = Host -controller = Controller -controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8 -in_namespace = False -xterms = False -mac = True -arp = True +Adding the 'topos' dict with a key/value pair to generate our newly defined +topology enables one to pass in '--topo=mytopo' from the command line. +""" -mn = Mininet(topo, switch, host, controller, controller_params, - in_namespace = in_namespace, - xterms = xterms, auto_set_macs = mac, - auto_static_arp = arp) +from mininet.topo import Topo, Node +class MyTopo( Topo ): + """Simple topology example.""" + + def __init__( self, enable_all = True ): + """Create custom topo.""" + + # Add default members to class. + super( MyTopo, self ).__init__() + + # Set Node IDs for hosts and switches + leftHost = 1 + leftSwitch = 2 + rightSwitch = 3 + rightHost = 4 + + # Add nodes + self._add_node( leftSwitch, Node( is_switch=True ) ) + self._add_node( rightSwitch, Node( is_switch=True ) ) + self._add_node( leftHost, Node( is_switch=False ) ) + self._add_node( rightHost, Node( is_switch=False ) ) + + # Add edges + self._add_edge( leftHost, leftSwitch ) + self._add_edge( leftSwitch, rightSwitch ) + self._add_edge( rightSwitch, rightHost ) + + # Consider all switches and hosts 'on' + self.enable_all() + + +topos = { 'mytopo': ( lambda: MyTopo() ) } \ No newline at end of file diff --git a/mininet/topo.py b/mininet/topo.py index 768c591739964b71dcb10171511a1f4285590079..3ff9cb87f7eaa924099f6a58e0cd75501a2f9789 100644 --- a/mininet/topo.py +++ b/mininet/topo.py @@ -107,7 +107,7 @@ def _add_node(self, dpid, node): self.g.add_node(dpid) self.node_info[dpid] = node - def _add_edge(self, src, dst, edge): + def _add_edge(self, src, dst, edge = None): '''Add edge (Node, Node) to graph. @param src src dpid @@ -116,6 +116,8 @@ def _add_edge(self, src, dst, edge): ''' src, dst = tuple(sorted([src, dst])) self.g.add_edge(src, dst) + if not edge: + edge = Edge() self.edge_info[(src, dst)] = edge self._add_port(src, dst) diff --git a/sysctl_addon b/sysctl_addon new file mode 100644 index 0000000000000000000000000000000000000000..e26eecc2222b93477b6af123e654e6b29706c90c --- /dev/null +++ b/sysctl_addon @@ -0,0 +1,17 @@ +# Mininet: Increase open file limit +fs.file-max = 100000 + +# Mininet: increase network buffer space +net.core.wmem_max = 16777216 +net.core.rmem_max = 16777216 +net.ipv4.tcp_rmem = 10240 87380 16777216 +net.ipv4.tcp_rmem = 10240 87380 16777216 +net.core.netdev_max_backlog = 5000 + +# Mininet: increase arp cache size +net.ipv4.neigh.default.gc_thresh1 = 4096 +net.ipv4.neigh.default.gc_thresh2 = 8192 +net.ipv4.neigh.default.gc_thresh3 = 16384 + +# Mininet: increase routing table size +net.ipv4.route.max_size=32768