def addIntf( self, intf, port=None ): """Add an interface. intf: interface name (e.g. nodeN-ethM) port: port number (optional, typically OpenFlow port number)""" if port is None: port = self.newPort() self.intfs[ port ] = intf self.ports[ intf ] = port #info( '\n' ) #info( 'added intf %s:%d to node %s\n' % ( intf,port, self.name ) ) if self.inNamespace: #info( 'moving w/inNamespace set\n' ) moveIntf( intf, self )
def moveIntfFrom( self, intf, intf_node, port=None ): """Move an interface. intf: interface intf_node: original node containing interface port: port number (optional, typically OpenFlow port number)""" if port is None: port = self.newPort() self.intfs[ port ] = intf self.ports[ intf ] = port self.nameToIntf[ intf.name ] = intf debug( '\nmoving intf %s:%d to node %s\n' % ( intf, port, self.name )) debug( 'moving', intf, 'into namespace for', self.name, '\n' ) moveIntf( intf.name, self, intf_node )
def moveIntfFrom(self, intf, intf_node, port=None): """Move an interface. intf: interface intf_node: original node containing interface port: port number (optional, typically OpenFlow port number)""" if port is None: port = self.newPort() self.intfs[port] = intf self.ports[intf] = port self.nameToIntf[intf.name] = intf debug('\nmoving intf %s:%d to node %s\n' % (intf, port, self.name)) debug('moving', intf, 'into namespace for', self.name, '\n') moveIntf(intf.name, self, intf_node)
def addIntf(self, intf, port=None): """Add an interface. intf: interface name (e.g. nodeN-ethM) port: port number (optional, typically OpenFlow port number)""" if port is None: port = self.newPort() self.intfs[port] = intf self.ports[intf] = port #info( '\n' ) #info( 'added intf %s:%d to node %s\n' % ( intf,port, self.name ) ) if self.inNamespace: #info( 'moving w/inNamespace set\n' ) moveIntf(intf, self)
def addIntf( self, intf, port=None ): """Add an interface. intf: interface port: port number (optional, typically OpenFlow port number)""" if port is None: port = self.newPort() self.intfs[ port ] = intf self.ports[ intf ] = port self.nameToIntf[ intf.name ] = intf debug( '\n' ) debug( 'added intf %s:%d to node %s\n' % ( intf, port, self.name ) ) if self.inNamespace: debug( 'moving', intf, 'into namespace for', self.name, '\n' ) moveIntf( intf.name, self )
def _makeIntfPair(intf1, intf2, addr1=None, addr2=None, node1=None, node2=None, deleteIntfs=True, runCmd=None): """Make a veth pair connnecting new interfaces intf1 and intf2 intf1: name for interface 1 intf2: name for interface 2 addr1: MAC address for interface 1 (optional) addr2: MAC address for interface 2 (optional) node1: home node for interface 1 (optional) node2: home node for interface 2 (optional) deleteIntfs: delete intfs before creating them runCmd: function to run shell commands (quietRun) raises Exception on failure Changes: The problem here is that we can not add a link to another netns within a Docker container since it does not know the other process (process not found error). So we have to do it different: We create the veth pair inside the default netns and move them into their netns (container) afterwards.""" if deleteIntfs: # Delete any old interfaces with the same names quietRun('ip link del ' + intf1, shell=True) quietRun('ip link del ' + intf2, shell=True) # first: create the veth pair in default namespace if addr1 is None and addr2 is None: cmdOutput = quietRun('ip link add name %s ' 'type veth peer name %s ' % (intf1, intf2), shell=True) else: cmdOutput = quietRun('ip link add name %s ' 'address %s ' 'type veth peer name %s ' 'address %s ' % (intf1, addr1, intf2, addr2), shell=True) if cmdOutput: raise Exception("Error creating interface pair (%s,%s): %s " % (intf1, intf2, cmdOutput)) # second: move both endpoints into the corresponding namespaces moveIntf(intf1, node1) moveIntf(intf2, node2)
def namespaceMove( self ): loops = 0 while not self.isConnected(): time.sleep( 0.01 ) loops += 1 if loops > 10: warn( "Cannot move TBIntf to mininet Node namespace: " "ns-3 has not connected yet to the TAP interface\n" ) return moveIntf( self.name, self.node ) self.inRightNamespace = True # IP address has been reset while moving to namespace, needs to be set again if self.ip is not None: self.setIP( self.ip, self.prefixLen ) # The same for 'up' self.isUp( True )
def namespaceMove(self): loops = 0 while not self.isConnected(): time.sleep(0.01) loops += 1 if loops > 10: warn("Cannot move TBIntf to mininet Node namespace: " "ns-3 has not connected yet to the TAP interface\n") return time.sleep(0.01) moveIntf(self.name, self.node) self.inRightNamespace = True # IP address has been reset while moving to namespace, needs to be set again if self.ip is not None: self.setIP(self.ip, self.prefixLen) # The same for 'up' self.isUp(True)
def configureLeafPacketECMP(self): # per-packet ECMP using bond device and RR. # Insert one bond device per leaf. bond = "bond%d" % self.switch_id # Move bond intf to each leaf. moveIntf(bond, self) # configure mac-address on bond interface mac = LeafMAC(self.switch_id) setMac(self, bond, mac) # enslave all links to spines intfs = [] for spine in xrange(self.num_spines): intf = "%s-eth%d" % (self.name, 1+spine+self.hosts_per_leaf) intfs.append(intf) cmd = "ifconfig %s up; ifenslave %s %s" % (bond, bond, ' '.join(intfs)) self.log(cmd) self.cmd(cmd) # configure routes to spines; in this case all spines have the # same IP address. spine_ip = SpineIP(0) cmd = "route add -host %s dev %s" % (spine_ip, bond) self.cmd(cmd) # configure routes to all other leaves for leaf in xrange(self.num_leafs): leaf += 1 if leaf == self.switch_id: continue net = LeafNet(leaf) sip = SpineIP(0) cmd = "ip route add %s nexthop via %s dev %s" % (net, sip, bond) self.cmd(cmd) # set spine mac address sip = SpineIP(0) mac = SpineMAC(0) cmd = "arp -s -i %s %s %s" % (bond, sip, mac) self.cmd(cmd) return
def namespaceMove(self): """Move tap Linux interface to the right namespace.""" loops = 0 # Wait until ns-3 process connects to the tap Linux interface. ns-3 process resides in the root # network namespace, so it must manage to connect to the interface before it is moved to the node # namespace. After interface move ns-3 process will not see the interface. while not self.isConnected(): time.sleep(0.01) loops += 1 if loops > 10: warn("Cannot move TBIntf to mininet Node namespace: " "ns-3 has not connected yet to the TAP interface\n") return # Wait a little more, just for be sure ns-3 process not miss that. time.sleep(0.01) # Move interface to the right namespace. moveIntf(self.name, self.node) self.inRightNamespace = True # IP address has been reset while moving to namespace, needs to be set again. if self.ip is not None: self.setIP(self.ip, self.prefixLen) # The same for 'up'. self.isUp(True)
def namespaceMove( self ): """Move tap Linux interface to the right namespace.""" loops = 0 # Wait until ns-3 process connects to the tap Linux interface. ns-3 process resides in the root # network namespace, so it must manage to connect to the interface before it is moved to the node # namespace. After interface move ns-3 process will not see the interface. while not self.isConnected(): time.sleep( 0.01 ) loops += 1 if loops > 10: warn( "Cannot move TBIntf to mininet Node namespace: " "ns-3 has not connected yet to the TAP interface\n" ) return # Wait a little more, just for be sure ns-3 process not miss that. time.sleep( 0.01 ) # Move interface to the right namespace. moveIntf( self.name, self.node ) self.inRightNamespace = True # IP address has been reset while moving to namespace, needs to be set again. if self.ip is not None: self.setIP( self.ip, self.prefixLen ) # The same for 'up'. self.isUp( True )
def _moveLink( self, node1, node2, intf1_name=None, intf2_name=None ): """ Move a host node to destination node in Mininet. node1: Moving node instance. node2: Destination node instance. intf1_name: Moving node interface name. Default if None. intf2_name: Destination node interface name. Default if None. """ if self.debug_flag1: args = (node1, node2, intf1_name, intf2_name) print "EXEC: moveLink(%s, %s, %s, %s):" % args # Part 0: Main assertions. assert isinstance(node1, Host) assert isinstance(node2, Switch) or isinstance(node2, Dummy) assert not intf1_name or intf1_name in node1.nameToIntf assert not intf2_name or intf2_name not in node2.nameToIntf # Part 1: Extracting intf1 information. intf1 = node1.intf(intf=intf1_name) # <- Uses defaultIntf if None. assert intf1 is not None intf1_name = intf1_name if intf1_name else intf1.name assert intf1.link != None assert intf1.link.intf1 == intf1 or intf1.link.intf2 == intf1 assert intf1.node == node1 intf1_other = None if intf1.link.intf1 == intf1: intf1_other = intf1.link.intf2 elif intf1.link.intf2 == intf1: intf1_other = intf1.link.intf1 node1_other = intf1_other.node intf1_name_other = intf1_other.name intf1_port_other = node1_other.ports[intf1_other] # Special case: Node already connected to other node. if node1_other == node2: if not intf2_name or intf2_name == intf1_name_other: warn('connection already established\n') return # Part 1.5: Call detach() on switch. if hasattr(node1_other, 'detach'): if self.debug_flag1: print "Detach %s from %s" % (intf1_other, node1_other) node1_other.detach(intf1_other) # Part 2: Exchange information between node1_other and node2. del node1_other.intfs[ intf1_port_other ] del node1_other.ports[ intf1_other ] del node1_other.nameToIntf[ intf1_name_other ] intf2_port = node2.newPort() # For now, just assign new port. intf2 = intf1_other if not intf2_name: intf2_name = "%s-eth%d" % (node2.name, intf2_port) intf2.rename(intf2_name) intf2.node = node2 node2.intfs[ intf2_port ] = intf2 node2.ports[ intf2 ] = intf2_port node2.nameToIntf[ intf2_name ] = intf2 # Part 3: Moving intf1_other to intf2 by namespace. debug( '\nmoving', intf2, 'into namespace for', node2, '\n' ) moveIntf( intf2_name, node2, srcNode=node1_other ) # Part 3.5: Call detach() on switch. if hasattr(node2, 'attach'): if self.debug_flag1: print "Attach %s to %s" % (intf2, node2) node2.attach(intf2)
def moveLink( self, node1, node2, intf1_name, intf2_name ): if self.debug_flag1: args = (node1, node2, intf1_name, intf2_name) print "EXEC: moveLink(%s, %s, %s, %s):" % args assert isinstance(node1, Host) #Node) assert isinstance(node2, Switch) or isinstance(node2, Dummy) #Node) assert intf1_name in node1.nameToIntf assert intf2_name in node2.nameToUnusedPorts if self.debug_flag2: #Make debug_flag false when not testing. intf1 = node1.nameToIntf[intf1_name] if intf1.link.intf1 == intf1: intf1_other = intf1.link.intf2 elif intf1.link.intf2 == intf2: intf1_other = intf1.link.intf1 node1_other = intf1_other.node intf1_name_other = intf1_other.name node1_other.nameToUnusedPorts[intf1_name_other] = None del node2.nameToUnusedPorts[intf2_name] return # TODO: Fix below~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`` # CODE HERE! if self.debug_flag3: node1_intf = node1.nameToIntf[intf1_name] if node1_intf.link.intf1==node1_intf: predest_intf=node1_intf.link.intf2 else: predest_intf=node1_intf.link.intf1 #TODO:Figure out the present switch-intf name and the port,move them to nameToUnunsedport # And move the intf object to node2 for name in predest_intf.node.nameToIntf: if predest_intf == predest_intf.node.nameToIntf[name]: predest_intf_name=name break predest_intf.node.nameToUnusedPorts[predest_intf_name]=predest_intf.node.ports[predest_intf] from mininet.util import moveIntf moveIntf(predest_intf, node2) #TODO:Put the intf previously moved to node2 in the dicts, that is, replace the dummy_intf node2.nameToIntf[intf2_name] = predest_intf return print "FFFFFFFFFFFFFFFFFFFF" intf1 = node1.nameToIntf[intf1_name] intf1_other = None assert intf1.link != None assert intf1.link.intf1 == intf1 or intf1.link.intf2 == intf1 assert intf1.node == node1 if intf1.link.intf1 == intf1: intf1_other = intf1.link.intf2 elif intf1.link.intf2 == intf1: intf1_other = intf1.link.intf1 node1_other = intf1_other.node intf1_name_other = intf1_other.name # These three must be saved. intf1_port_other = node1_other.ports[intf1_other] # Special case: Node already connected to other node. if node1_other == node2 and intf1_name_other == intf2_name: warn('connection already established\n') return del node1_other.intfs[ intf1_port_other ] del node1_other.ports[ intf1_other ] del node1_other.nameToIntf[ intf1_name_other ] node1_other.nameToUnusedPorts[ intf1_name_other ] = intf1_port_other intf2_port = node2.nameToUnusedPorts[ intf2_name ] intf2 = intf1_other intf2.rename(intf2_name) #intf2.node = node2 node2.moveIntfFrom(intf2, node1_other, intf2_port) intf2.node = node2 del node2.nameToUnusedPorts[ intf2_name ]