diff --git a/bin/mn_run.py b/bin/mn_run.py index fc65bac..e7103c1 100755 --- a/bin/mn_run.py +++ b/bin/mn_run.py @@ -99,6 +99,10 @@ 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('--mac', action = 'store_true', + default = False, help = 'set host MACs equal to DPIDs') + opts.add_option('--arp', action = 'store_true', + default = False, help = 'set all-pairs ARP entries') opts.add_option('--verbosity', '-v', type = 'choice', choices = LEVELS.keys(), default = 'info', help = '[' + ' '.join(LEVELS.keys()) + ']') @@ -131,8 +135,11 @@ class MininetRunner(object): controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8 xterms = self.options.xterms + mac = self.options.mac + arp = self.options.arp mn = Mininet(topo, switch, host, controller, controller_params, - xterms = xterms) + xterms = xterms, auto_set_macs = mac, + auto_static_arp = arp) test = self.options.test if test != 'build': diff --git a/mininet/net.py b/mininet/net.py index d07acfb..fe7f631 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -79,7 +79,8 @@ class Mininet(object): def __init__(self, topo, switch, host, controller, cparams, build = True, xterms = False, cleanup = False, - in_namespace = False, switch_is_kernel = True): + in_namespace = False, switch_is_kernel = True, + auto_set_macs = False, auto_static_arp = False): '''Create Mininet object. @param topo Topo object @@ -91,6 +92,9 @@ class Mininet(object): @param xterms if build now, spawn xterms? @param cleanup if build now, cleanup before creating? @param in_namespace spawn switches and hosts in their own namespace? + @param switch_is_kernel is the switch kernel-based? + @param auto_set_macs set MAC addrs to DPIDs? + @param auto_static_arp set all-pairs static MAC addrs? ''' self.topo = topo self.switch = switch @@ -102,13 +106,17 @@ class Mininet(object): self.dps = 0 # number of created kernel datapaths self.in_namespace = in_namespace self.switch_is_kernel = switch_is_kernel + self.xterms = xterms + self.cleanup = cleanup + self.auto_set_macs = auto_set_macs + self.auto_static_arp = auto_static_arp self.terms = [] # list of spawned xterm processes self.kernel = True #temporary! if build: - self.build(xterms, cleanup) + self.build() def _add_host(self, dpid): '''Add host. @@ -249,15 +257,12 @@ class Mininet(object): lg.info('%s ', host.name) lg.info('\n') - def build(self, xterms, cleanup): + def build(self): '''Build mininet. At the end of this function, everything should be connected and up. - - @param xterms spawn xterms on build? - @param cleanup cleanup before creating? ''' - if cleanup: + if self.cleanup: pass # cleanup # validate topo? kernel = self.kernel @@ -289,8 +294,12 @@ class Mininet(object): lg.info('*** Configuring hosts\n') self._config_hosts() - if xterms: + if self.xterms: self.start_xterms() + if self.auto_set_macs: + self.set_macs() + if self.auto_static_arp: + self.static_arp() def switch_nodes(self): '''Return switch nodes.''' @@ -315,6 +324,23 @@ class Mininet(object): os.kill(term.pid, signal.SIGKILL) cleanUpScreens() + def set_macs(self): + '''Set MAC addrs to correspond to datapath IDs on hosts. + + Assume that the host only has one interface. + ''' + for dpid in self.topo.hosts(): + host_node = self.nodes[dpid] + host_node.setMAC(host_node.intfs[0], dpid) + + def static_arp(self): + '''Add all-pairs ARP entries to remove the need to handle broadcast.''' + for src in self.topo.hosts(): + src_node = self.nodes[src] + for dst in self.topo.hosts(): + if src != dst: + src_node.setARP(dst, dst) + def start(self): '''Start controller and switches\n''' lg.info('*** Starting controller\n') diff --git a/mininet/node.py b/mininet/node.py index dab98dd..da44927 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -6,7 +6,7 @@ import os, signal, sys, select flush = sys.stdout.flush from mininet.logging_mod import lg -from mininet.util import quietRun +from mininet.util import quietRun, macColonHex, ipStr class Node(object): '''A virtual network node is simply a shell in a network namespace. @@ -160,6 +160,28 @@ class Node(object): self.intfs += [intfName] return intfName + def setMAC(self, intf, mac): + '''Set the MAC address for an interface. + + @param mac MAC address as unsigned int + ''' + mac_str = macColonHex(mac) + result = self.cmd(['ifconfig', intf, 'down']) + result += self.cmd(['ifconfig', intf, 'hw', 'ether', mac_str]) + result += self.cmd(['ifconfig', intf, 'up']) + return result + + def setARP(self, ip, mac): + '''Add an ARP entry. + + @param ip IP address as unsigned int + @param mac MAC address as unsigned int + ''' + ip_str = ipStr(ip) + mac_str = macColonHex(mac) + result = self.cmd(['arp', '-s', ip_str, mac_str]) + return result + def setIP(self, intf, ip, bits): '''Set the IP address for an interface. diff --git a/mininet/util.py b/mininet/util.py index 08c7a24..2006114 100644 --- a/mininet/util.py +++ b/mininet/util.py @@ -175,4 +175,26 @@ def createLink(node1, node2): def fixLimits(): '''Fix ridiculously small resource limits.''' setrlimit( RLIMIT_NPROC, (4096, 8192)) - setrlimit( RLIMIT_NOFILE, (16384, 32768)) \ No newline at end of file + setrlimit( RLIMIT_NOFILE, (16384, 32768)) + +def macColonHex(mac): + '''Generate MAC colon-hex string from unsigned int. + + @param mac MAC address as unsigned int + @return mac_str MAC colon-hex string + ''' + mac_pieces = [] + for i in range (5, -1, -1): + mac_pieces.append('%02x' % (((0xff << (i * 8)) & mac) >> (i * 8))) + mac_str = ':'.join(mac_pieces) + return mac_str + +def ipStr(ip): + '''Generate IP address string + + @return ip addr string + ''' + hi = (ip & 0xff0000) >> 16 + mid = (ip & 0xff00) >> 8 + lo = ip & 0xff + return "10.%i.%i.%i" % (hi, mid, lo) \ No newline at end of file