Exemple #1
0
 def runCpuLimitTest(self, cpu, duration=5):
     """run CPU limit test with 'while true' processes.
     cpu: desired CPU fraction of each host
     duration: test duration in seconds
     returns a single list of measured CPU fractions as floats.
     """
     pct = cpu * 100
     info("*** Testing CPU %.0f%% bandwidth limit\n" % pct)
     hosts = self.hosts
     for h in hosts:
         h.cmd("while true; do a=1; done &")
     pids = [h.cmd("echo $!").strip() for h in hosts]
     pids_str = ",".join(["%s" % pid for pid in pids])
     cmd = "ps -p %s -o pid,%%cpu,args" % pids_str
     # It's a shame that this is what pylint prefers
     outputs = []
     for _ in range(duration):
         sleep(1)
         outputs.append(quietRun(cmd).strip())
     for h in hosts:
         h.cmd("kill $!")
     cpu_fractions = []
     for test_output in outputs:
         # Split by line.  Ignore first line, which looks like this:
         # PID %CPU COMMAND\n
         for line in test_output.split("\n")[1:]:
             r = r"\d+\s*(\d+\.\d+)"
             m = re.search(r, line)
             if m is None:
                 error("*** Error: could not extract CPU fraction: %s\n" % line)
                 return None
             cpu_fractions.append(float(m.group(1)))
     output("*** Results: %s\n" % cpu_fractions)
     return cpu_fractions
Exemple #2
0
    def default( self, line ):
        """Called on an input line when the command prefix is not recognized.
        Overridden to run shell commands when a node is the first CLI argument.
        Past the first CLI argument, node names are automatically replaced with
        corresponding IP addrs."""

        first, args, line = self.parseline( line )

        if first in self.mn:
            if not args:
                print "*** Enter a command for node: %s <cmd>" % first
                return
            node = self.mn[ first ]
            rest = args.split( ' ' )
            # Substitute IP addresses for node names in command
            # If updateIP() returns None, then use node name
            rest = [ self.mn[ arg ].defaultIntf().updateIP() or arg
                     if arg in self.mn else arg
                     for arg in rest ]
            rest = ' '.join( rest )
            # Run cmd on node:
            builtin = isShellBuiltin( first )
            node.sendCmd( rest, printPid=( not builtin ) )
            self.waitForNode( node )
        else:
            error( '*** Unknown command: %s\n' % line )
Exemple #3
0
 def _parsePingFull(pingOutput):
     "Parse ping output and return all data."
     errorTuple = (1, 0, 0, 0, 0, 0)
     # Check for downed link
     r = r"[uU]nreachable"
     m = re.search(r, pingOutput)
     if m is not None:
         return errorTuple
     r = r"(\d+) packets transmitted, (\d+) received"
     m = re.search(r, pingOutput)
     if m is None:
         error("*** Error: could not parse ping output: %s\n" % pingOutput)
         return errorTuple
     sent, received = int(m.group(1)), int(m.group(2))
     r = r"rtt min/avg/max/mdev = "
     r += r"(\d+\.\d+)/(\d+\.\d+)/(\d+\.\d+)/(\d+\.\d+) ms"
     m = re.search(r, pingOutput)
     if m is None:
         error("*** Error: could not parse ping output: %s\n" % pingOutput)
         return errorTuple
     rttmin = float(m.group(1))
     rttavg = float(m.group(2))
     rttmax = float(m.group(3))
     rttdev = float(m.group(4))
     return sent, received, rttmin, rttavg, rttmax, rttdev
Exemple #4
0
 def do_detach( self, line ):
     "Detach a host from a switch"
     args = line.split()
     if len(args) < 1 or len(args) > 2:
         error( 'invalid number of args: detach host [switch]\n' )
     else:
         self.mn.detachHost(*args)
Exemple #5
0
    def findTap(node, port, path=None):
        """utility function to parse through a sys.config
           file to find tap interfaces for a switch"""
        switch = False
        portLine = ""
        intfLines = []

        if path is None:
            path = "%s/rel/linc/releases/1.0/sys.config" % LINCSwitch.lincDir

        with open(path) as f:
            for line in f:
                if "tap" in line:
                    intfLines.append(line)
                if node.dpid in line.translate(None, ":"):
                    switch = True
                    continue
                if switch:
                    if "switch" in line:
                        switch = False
                    if "port_no,%s}" % port in line:
                        portLine = line
                        break

        if portLine:
            m = re.search("port,\d+", portLine)
            port = m.group(0).split(",")[1]
        else:
            error("***ERROR: Could not find any ports in sys.config\n")
            return

        for intfLine in intfLines:
            if "port,%s" % port in intfLine:
                return re.findall("tap\d+", intfLine)[0]
    def startShell( self ):
        if self.shell:
            error( "%s: shell is already running" )
            return
        subprocess.call(["docker stop "+self.name], shell=True, stdout=output)
        subprocess.call(["docker rm -f "+self.name], shell=True, stdout=output)

        cmd = ["docker","run","--privileged","-h",self.name ,"--name="+self.name,"-v", "/vagrant:/home/ubuntu"]
        if self.dargs is not None:
            cmd.extend([self.dargs])
        cmd.extend(["--net='none'",self.image, self.startString])

        self.shell = Popen( cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True )
        self.stdin = self.shell.stdin
        self.stdout = self.shell.stdout
        self.pid = self.shell.pid
        self.pollOut = select.poll()
        self.pollOut.register( self.stdout )
        self.outToNode[ self.stdout.fileno() ] = self
        self.inToNode[ self.stdin.fileno() ] = self
        self.execed = False
        self.lastCmd = None
        self.lastPid = None
        self.readbuf = ''
        self.waiting = False
        call("sleep 1", shell=True)
        pid_cmd = ["docker","inspect","--format='{{ .State.Pid }}'",""+self.name]
        pidp = Popen( pid_cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=False )
        ps_out = pidp.stdout.readlines()
        self.pid = int(ps_out[0])
Exemple #7
0
 def startShell( self ):
     "Start a shell process for running commands"
     if self.shell:
         error( "%s: shell is already running" )
         return
     # mnexec: (c)lose descriptors, (d)etach from tty,
     # (p)rint pid, and run in (n)amespace
     opts = '-cdp'
     if self.inNamespace:
         opts += 'n'
     # bash -m: enable job control
     cmd = [ 'mnexec', opts, 'bash', '-m' ]
     self.shell = Popen( cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT,
                         close_fds=True )
     self.stdin = self.shell.stdin
     self.stdout = self.shell.stdout
     self.pid = self.shell.pid
     self.pollOut = select.poll()
     self.pollOut.register( self.stdout )
     # Maintain mapping between file descriptors and nodes
     # This is useful for monitoring multiple nodes
     # using select.poll()
     self.outToNode[ self.stdout.fileno() ] = self
     self.inToNode[ self.stdin.fileno() ] = self
     self.execed = False
     self.lastCmd = None
     self.lastPid = None
     self.readbuf = ''
     self.waiting = False
    def default( self, line ):
        """Called on an input line when the command prefix is not recognized.
        Overridden to run shell commands when a component is the first CLI
        argument. Past the first CLI argument, component names are then
        automatically replaced with corresponding node IP addrs."""

        first, args, line = self.parseline( line )
        if not args:
            return
        if args and len(args) > 0 and args[ -1 ] == '\n':
            args = args[ :-1 ]
        rest = args.split( ' ' )

        if first in self.cn:
            comp = self.cn[ first ]
            # Substitute IP addresses for node names in command
            rest = [ self.cn[ arg ].node.defaultIntf().updateIP()
                     if arg in self.cn else arg
                     for arg in rest ]
            rest = ' '.join( rest )
            # Run cmd on node:
            builtin = isShellBuiltin( first )
            comp.node.sendCmd( rest, printPid=( not builtin ) )
            self.waitForNode( comp.node )
        else:
            error( '*** Unknown command: %s\n' % first )
Exemple #9
0
 def _configLinkIntfs(srcIntf, dstIntf, status):
     result = srcIntf.ifconfig( status )
     if result:
         error( 'link src status change failed: %s\n' % result )
     result = dstIntf.ifconfig( status )
     if result:
         error( 'link dst status change failed: %s\n' % result )
Exemple #10
0
 def configureRoutedControlNetwork( self, ip='192.168.123.1',
     prefixLen=16 ):
     """Configure a routed control network on controller and switches.
        For use with the user datapath only right now.
        """
     controller = self.controllers[ 0 ]
     info( controller.name + ' <->' )
     cip = ip
     snum = ipParse( ip )
     for switch in self.switches:
         info( ' ' + switch.name )
         sintf, cintf = createLink( switch, controller )
         snum += 1
         while snum & 0xff in [ 0, 255 ]:
             snum += 1
         sip = ipStr( snum )
         controller.setIP( cintf, cip, prefixLen )
         switch.setIP( sintf, sip, prefixLen )
         controller.setHostRoute( sip, cintf )
         switch.setHostRoute( cip, sintf )
     info( '\n' )
     info( '*** Testing control network\n' )
     while not controller.intfIsUp( cintf ):
         info( '*** Waiting for', cintf, 'to come up\n' )
         sleep( 1 )
     for switch in self.switches:
         while not switch.intfIsUp( sintf ):
             info( '*** Waiting for', sintf, 'to come up\n' )
             sleep( 1 )
         if self.ping( hosts=[ switch, controller ] ) != 0:
             error( '*** Error: control network test failed\n' )
             exit( 1 )
     info( '\n' )
Exemple #11
0
 def attachHost( self, hostName, switchName ):
     if hostName not in self.nameToNode:
         error( 'host not in network: %s\n' % hostName )
         return
         
     if switchName not in self.nameToNode:
         error( 'switch not in network: %s\n' % switchName )
         return
         
     host = self.nameToNode[hostName]
     if not isinstance(host, Host):
         error('%s is not a host' % hostName)
         return
         
     sw = self.nameToNode[switchName]
     if not isinstance(sw, Switch):
         error('%s is not a switch' % switchName)
         return
         
     if not isinstance(sw, OVSKernelSwitch) and not isinstance(sw, OVSKernelSwitchNew):
         error('attachHost only works with OVS kernel switches')
         return
         
     hostIntf, swIntf = host.linkTo(sw)
     
     host.setIP( hostIntf, host.defaultIP, self.cparams.prefixLen )
     host.setDefaultRoute( hostIntf )
     if self.autoSetMacs:
         host.setMAC( hostIntf, host.defaultMAC )
Exemple #12
0
	def get_if_index(self, in_if_name):
		output = self.cmd('ovs-vsctl --db=unix:%s/db.sock --no-wait find Interface name=%s' %(self.path_ovs, in_if_name))
		if output != None and output != "" :
			return re.search( r'ofport(.*): (\d*)', output).group(2)
		else:
			error("ERROR port not available\n")
			sys.exit(-2)
Exemple #13
0
	def translate_rule(self, rule):
		# ports reg exp
		out_port = re.compile('output:(.*?),')
		in_port = re.compile('in_port=(.*?),')
		out_port_end = ","
	
		#test if rule has in_port
		if 'in_port' in rule and not re.search(in_port, rule):
			error("ERROR wrong format for in_port\n")
			sys.exit(-2)	
		elif 'in_port' in rule and re.search(in_port, rule):
			in_if_name = in_port.search(rule).group(1)
			in_if_index = self.get_if_index(in_if_name)
			rule = re.sub(in_port, "in_port="+in_if_index+",", rule)

		#test if rule has output_port
		if 'output' in rule and not re.search(out_port, rule):
			#print "output: not followed by comma, retry.."
			out_port = re.compile('output:(.*?)\"(\Z)')
			out_port_end = "\""
			if not re.search(out_port, rule):
				error("ERROR wrong format for out_put port\n")
				sys.exit(-2)
			out_if_name = out_port.search(rule).group(1)
			out_if_index = self.get_if_index(out_if_name)	
			rule = re.sub(out_port, "output:"+out_if_index+out_port_end, rule)
		elif 'output' in rule and re.search(out_port, rule):	
			out_if_name = out_port.search(rule).group(1)
			out_if_index = self.get_if_index(out_if_name)
			rule = re.sub(out_port, "output:"+out_if_index+out_port_end, rule)

		return rule
Exemple #14
0
	def start( self, controllers = [], intfs_to_data = [],  coex={}):
		info("%s " % self.name)

		if len(controllers) == 0:
			info("WARNING %s Controllers\n" % len(controllers))

		if len(intfs_to_data) == 0:
			error("ERROR configuration is not possibile for %s\n" % self.name)
			sys.exit(-2)

		# Running SSHD
		self.cmd('chown root:root /var/run/sshd')
		self.cmd('chmod 711 /var/run/sshd')
		self.cmd('/usr/sbin/sshd -o UseDNS=no -u0')
		
		if coex == {}:
			error("ERROR coexistence is {}\n")
			sys.exit(-2)

		lo_data = {'intfname':'lo', 'ip':'%s' %(self.loopback), 'ingrtype':None, 'ingrdata':None, 'net':{ 'net':self.loopback, 'netbit':32, 'cost':1, 'hello':5, 'area':'0.0.0.0'}}

		self.initial_configuration(controllers)
		self.configure_ovs(intfs_to_data, coex)
		self.configure_quagga(intfs_to_data, lo_data, coex)
		self.final_configuration(intfs_to_data)
Exemple #15
0
	def start_pw( self, table, pws_data = []):
		
		if self.OF_V != "OpenFlow13" and len(pws_data) != 0:
			error("ERROR PW configuration is not possibile for %s - OpenFlow version != 1.3\n" % self.name)
			sys.exit(-2)	
	
		rules = []

		# TODO In futuro incapsularlo
		for pw_data in pws_data:

			eth = pw_data['eth']
			v_eth1 = pw_data['v_eth1']
			v_eth2 = pw_data['v_eth2']

			if eth:
				self.cmd("ifconfig %s 0" % eth)
			if v_eth1:
				self.cmd("ifconfig %s 0" % v_eth1)
			self.cmd("ifconfig %s 0" % v_eth2)
			if eth:
				self.cmd("ovs-vsctl --db=unix:%s/db.sock --no-wait add-port %s %s" %(self.path_ovs, self.name, eth))
			if v_eth1:			
				self.cmd("ovs-vsctl --db=unix:%s/db.sock --no-wait add-port %s %s" %(self.path_ovs, self.name, v_eth1))
			self.cmd("ovs-vsctl --db=unix:%s/db.sock --no-wait add-port %s %s" %(self.path_ovs, self.name, v_eth2))

			if eth and v_eth1:
				rules.append('ovs-ofctl -O %s add-flow %s "table=%s,hard_timeout=0,priority=%s,in_port=%s,action=output:%s"' %(self.OF_V, self.name,
				table, 32768, eth, v_eth1))
				rules.append('ovs-ofctl -O %s add-flow %s "table=%s,hard_timeout=0,priority=%s,in_port=%s,action=output:%s"' %(self.OF_V, self.name, 
				table, 32768, v_eth1, eth))
				for rule in rules:
					rule = self.translate_rule(rule)
					self.cmd(rule)
Exemple #16
0
	def checkSR(self):
		root = Node( 'root', inNamespace=False)
		sr = root.cmd('ls %s 2> /dev/null | wc -l' % self.SR_exec)
		if '1' not in sr:
			error( 'Cannot find required executable fpm-of.bin\nPlease make sure that fpm-of.bin is properly installed in ' + self.SR_path + '\n'
				   'Otherwise change sr_path variable according to your configuration\n' )
			exit( 1 )
Exemple #17
0
 def configureRoutedControlNetwork(self, ip="192.168.123.1", prefixLen=16):
     """Configure a routed control network on controller and switches.
        For use with the user datapath only right now."""
     controller = self.controllers[0]
     info(controller.name + " <->")
     cip = ip
     snum = ipParse(ip)
     for switch in self.switches:
         info(" " + switch.name)
         link = self.link(switch, controller, port1=0)
         sintf, cintf = link.intf1, link.intf2
         switch.controlIntf = sintf
         snum += 1
         while snum & 0xFF in [0, 255]:
             snum += 1
         sip = ipStr(snum)
         cintf.setIP(cip, prefixLen)
         sintf.setIP(sip, prefixLen)
         controller.setHostRoute(sip, cintf)
         switch.setHostRoute(cip, sintf)
     info("\n")
     info("*** Testing control network\n")
     while not cintf.isUp():
         info("*** Waiting for", cintf, "to come up\n")
         sleep(1)
     for switch in self.switches:
         while not sintf.isUp():
             info("*** Waiting for", sintf, "to come up\n")
             sleep(1)
         if self.ping(hosts=[switch, controller]) != 0:
             error("*** Error: control network test failed\n")
             exit(1)
     info("\n")
Exemple #18
0
 def detachHost( self, hostName, switchName=None ):
     if hostName not in self.nameToNode:
         error( 'host not in network: %s\n' % hostName )
         return
         
     host = self.nameToNode[hostName]
     if not isinstance(host, Host):
         error('%s is not a host' % hostName)
         return
     
     if switchName:
         if switchName not in self.nameToNode:
             error( 'switch not in network: %s\n' % switchName )
             return
             
         sw = self.nameToNode[switchName]
         if not isinstance(sw, Switch):
             error('%s is not a switch' % switchName)
             return
             
         if not isinstance(sw, OVSKernelSwitch) and not isinstance(sw, OVSKernelSwitchNew):
             error('attachHost only works with OVS kernel switches')
             return
     else:
         sw = None
         
     host.unlinkFrom(sw)
    def do_add( self, line ):
        "Create a virtual machine image."
        args = line.split()
        vm_name = None
        vm_script = None      # TODO: Still working on extra options.
        vm_ip = None          # Current there is no point in these variables.
        vm_extra_params = {}

        if len(args) == 1:
            vm_name = args[0]
        elif len(args) == 2:
            vm_name = args[0]
            vm_script = args[1]
        elif len(args) == 3:
            vm_name = args[0]
            vm_script = args[1]
            vm_ip = args[2]
        else:
            error('invalid number of args: add vm_name [vm_script [vm_ip]]\n')
            return

        err = self._check_vm_name(vm_name, exp_exist=False, exp_running=None)
        
        if not err:
            self.cn.createVM(vm_name)
    def start(self, controllers):
        "Start up a new P4 switch"
        info("Starting P4 switch {}.\n".format(self.name))
        args = [self.sw_path]
        for port, intf in self.intfs.items():
            if not intf.IP():
                args.extend(['-i', str(port) + "@" + intf.name])
        if self.pcap_dump:
            args.append("--pcap")
            # args.append("--useFiles")
        if self.thrift_port:
            args.extend(['--thrift-port', str(self.thrift_port)])
        if self.nanomsg:
            args.extend(['--nanolog', self.nanomsg])
        args.extend(['--device-id', str(self.device_id)])
        P4Switch.device_id += 1
        args.append(self.json_path)
        if self.enable_debugger:
            args.append("--debugger")
        if self.log_console:
            args.append("--log-console")
        logfile = "/tmp/p4s.{}.log".format(self.name)
        info(' '.join(args) + "\n")

        pid = None
        with tempfile.NamedTemporaryFile() as f:
            # self.cmd(' '.join(args) + ' > /dev/null 2>&1 &')
            self.cmd(' '.join(args) + ' >' + logfile + ' 2>&1 & echo $! >> ' + f.name)
            pid = int(f.read())
        debug("P4 switch {} PID is {}.\n".format(self.name, pid))
        if not self.check_switch_started(pid):
            error("P4 switch {} did not start correctly.\n".format(self.name))
            exit(1)
        info("P4 switch {} has been started.\n".format(self.name))
Exemple #21
0
    def ping( self, hosts=None, timeout=None ):
        """Ping between all specified hosts.
           hosts: list of hosts
           timeout: time to wait for a response, as string
           returns: ploss packet loss percentage"""
        # should we check if running?
        packets = 0
        lost = 0
        ploss = None
	if not hosts:
            hosts = self.hosts[1:]
            output( '*** Ping: testing ping reachability\n' )
        for node in hosts:
            output( '%s -> ' % node.name )
            for dest in hosts:
                if node != dest:
                    opts = ''
                    if timeout:
                        opts = '-W %s' % timeout
		    result = node.cmd( 'ping -c1 %s %s' % (opts, dest.IP()) )
		    sent, received = self._parsePing( result )
                    packets += sent
                    if received > sent:
                        error( '*** Error: received too many packets' )
                        error( '%s' % result )
                        node.cmdPrint( 'route' )
                        exit( 1 )
                    lost += sent - received
                    output( ( '%s ' % dest.name ) if received else 'X ' )
            output( '\n' )
            ploss = 100 * lost / packets
        output( "*** Results: %i%% dropped (%d/%d lost)\n" %
                ( ploss, lost, packets ) )
        return ploss
 def __init__(self, name, sw_path = None, json_path = None,
              thrift_port = None,
              pcap_dump = False,
              log_console = False,
              verbose = False,
              device_id = None,
              enable_debugger = False,
              **kwargs):
     Switch.__init__(self, name, **kwargs)
     assert(sw_path)
     assert(json_path)
     # make sure that the provided sw_path is valid
     pathCheck(sw_path)
     # make sure that the provided JSON file exists
     if not os.path.isfile(json_path):
         error("Invalid JSON file.\n")
         exit(1)
     self.sw_path = sw_path
     self.json_path = json_path
     self.verbose = verbose
     logfile = "/tmp/p4s.{}.log".format(self.name)
     self.output = open(logfile, 'w')
     self.thrift_port = thrift_port
     self.pcap_dump = pcap_dump
     self.enable_debugger = enable_debugger
     self.log_console = log_console
     if device_id is not None:
         self.device_id = device_id
         P4Switch.device_id = max(P4Switch.device_id, device_id)
     else:
         self.device_id = P4Switch.device_id
         P4Switch.device_id += 1
     self.nanomsg = "ipc:///tmp/bm-{}-log.ipc".format(self.device_id)
Exemple #23
0
 def precheck( self ):
     """Pre-check to make sure connection works and that
        we can call sudo without a password"""
     result = 0
     info( '*** Checking servers\n' )
     for server in self.servers:
         ip = self.serverIP[ server ]
         if not server or server == 'localhost':
             continue
         info( server, '' )
         dest = '%s@%s' % ( self.user, ip )
         cmd = [ 'sudo', '-E', '-u', self.user ]
         cmd += self.sshcmd + [ '-n', dest, 'sudo true' ]
         debug( ' '.join( cmd ), '\n' )
         _out, _err, code = errRun( cmd )
         if code != 0:
             error( '\nstartConnection: server connection check failed '
                    'to %s using command:\n%s\n'
                     % ( server, ' '.join( cmd ) ) )
         result |= code
     if result:
         error( '*** Server precheck failed.\n'
                '*** Make sure that the above ssh command works'
                ' correctly.\n'
                '*** You may also need to run mn -c on all nodes, and/or\n'
                '*** use sudo -E.\n' )
         sys.exit( 1 )
     info( '\n' )
Exemple #24
0
 def do_info( self, line ):
     "Noise node info."
     args = line.split()
     if len(args) != 1:
         error( 'invalid number of args: info [device]\n' )
     else:
         self.mn.deviceInfo( *args )
Exemple #25
0
    def findTap(node, port, path=None):
        '''utility function to parse through a sys.config
           file to find tap interfaces for a switch'''
        switch = False
        portLine = ''
        intfLines = []

        if path is None:
            path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir

        with open(path) as f:
            for line in f:
                if 'tap' in line:
                    intfLines.append(line)
                if node.dpid in line.translate(None, ':'):
                    switch = True
                    continue
                if switch:
                    if 'switch' in line:
                        switch = False
                    if 'port_no,%s}' % port in line:
                        portLine = line
                        break

        if portLine:
            m = re.search('port,\d+', portLine)
            port = m.group(0).split(',')[ 1 ]
        else:
            error('***ERROR: Could not find any ports in sys.config\n')
            return

        for intfLine in intfLines:
            if 'port,%s' % port in intfLine:
                return re.findall('tap\d+', intfLine)[ 0 ]
Exemple #26
0
 def do_position( self, line ):
     "Position node info."
     args = line.split()
     if len(args) != 1:
         error( 'invalid number of args: position [sta ou ap]\n' )
     else:
         self.mn.getCurrentPosition( *args )
Exemple #27
0
    def default( self, line ):
        """Called on an input line when the command prefix is not recognized.
        Overridden to run shell commands when a node is the first CLI argument.
        Past the first CLI argument, node names are automatically replaced with
        corresponding IP addrs."""

        first, args, line = self.parseline( line )
        if args and len(args) > 0 and args[ -1 ] == '\n':
            args = args[ :-1 ]
        rest = args.split( ' ' )

        if first in self.nodemap:
            node = self.nodemap[ first ]
            # Substitute IP addresses for node names in command
            for index in range(len(rest)):
                arg = rest[index]
                if arg in self.nodemap:
                    ip = self.nodemap[arg].IP()
                    if not ip:
                        error('%s is an unreachable, detached host\n' % arg)
                        return
                    rest[index] = ip
            #rest = [ self.nodemap[ arg ].IP()
            #        if arg in self.nodemap else arg
            #        for arg in rest ]
            rest = ' '.join( rest )
            # Run cmd on node:
            builtin = isShellBuiltin( first )
            node.sendCmd( rest, printPid=( not builtin ) )
            self.waitForNode( node )
        else:
            error( '*** Unknown command: %s\n' % first )
Exemple #28
0
    def bwCmds( self, bw=None, speedup=0, use_hfsc=False, use_tbf=False):
        "Return tc commands to set bandwidth"
	#print "RED BURST: " + str(red_burst) + "XXXXXXXXXXXXXXXX"

        cmds, parent = [], ' root '

        if bw and ( bw < 0 or bw > 1000 ):
            error( 'Bandwidth', bw, 'is outside range 0..1000 Mbps\n' )

        elif bw is not None:
            # BL: this seems a bit brittle...
            if ( speedup > 0 and
                 self.node.name[0:1] == 's' ):
                bw = speedup
            # This may not be correct - we should look more closely
            # at the semantics of burst (and cburst) to make sure we
            # are specifying the correct sizes. For now I have used
            # the same settings we had in the mininet-hifi code.
            if use_hfsc:
                cmds += [ '%s qdisc add dev %s root handle 1:0 hfsc default 1',
                          '%s class add dev %s parent 1:0 classid 1:1 hfsc sc '
                          + 'rate %fMbit ul rate %fMbit' % ( bw, bw ) ]
            elif use_tbf:
                latency_us = 10 * 1500 * 8 / bw
                cmds += ['%s qdisc add dev %s root handle 1: tbf ' +
                        'rate %fMbit burst 15000 latency %fus' %
                         ( bw, latency_us ) ]
            else:
                cmds += [ '%s qdisc add dev %s root handle 1:0 htb default 1',
                         '%s class add dev %s parent 1:0 classid 1:1 htb ' +
                         'rate %fMbit burst 15k' % bw ]
            parent = ' parent 1:1 '

        return cmds, parent
Exemple #29
0
 def do_attach( self, line ):
     "Create new link between a host and a switch"
     args = line.split()
     if len(args) != 2:
         error( 'invalid number of args: attach host switch\n' )
     else:
         self.mn.attachHost(*args)
Exemple #30
0
def waitListening( client=None, server='127.0.0.1', port=80, timeout=None ):
    """Wait until server is listening on port.
       returns True if server is listening"""
    runCmd = ( client.cmd if client else
               partial( quietRun, shell=True ) )
    if not runCmd( 'which telnet' ):
        raise Exception('Could not find telnet' )
    # pylint: disable=maybe-no-member
    serverIP = server if isinstance( server, basestring ) else server.IP()
    cmd = ( 'echo A | telnet -e A %s %s' % ( serverIP, port ) )
    time = 0
    result = runCmd( cmd )
    while 'Connected' not in result:
        if 'No route' in result:
            rtable = runCmd( 'route' )
            error( 'no route to %s:\n%s' % ( server, rtable ) )
            return False
        if timeout and time >= timeout:
            error( 'could not connect to %s on port %d\n' % ( server, port ) )
            return False
        debug( 'waiting for', server, 'to listen on port', port, '\n' )
        info( '.' )
        sleep( .5 )
        time += .5
        result = runCmd( cmd )
    return True
Exemple #31
0
 def do_switch(self, line):
     "Starts or stops a switch"
     args = line.split()
     if len(args) != 2:
         error('invalid number of args: switch <switch name>'
               '{start, stop}\n')
         return
     sw = args[0]
     command = args[1]
     if sw not in self.mn or self.mn.get(sw) not in self.mn.switches:
         error('invalid switch: %s\n' % args[1])
     else:
         sw = args[0]
         command = args[1]
         if command == 'start':
             self.mn.get(sw).start(self.mn.controllers)
         elif command == 'stop':
             self.mn.get(sw).stop(deleteIntfs=False)
         else:
             error('invalid command: '
                   'switch <switch name> {start, stop}\n')
Exemple #32
0
 def __create_hwsim_mgmt_devices(cls, n_radios):
     # generate prefix
     phys = subprocess.check_output(
         "find /sys/kernel/debug/ieee80211 -name "
         "hwsim | cut -d/ -f 6 | sort",
         shell=True).split("\n")
     num = 0
     numokay = False
     cls.prefix = ""
     while not numokay:
         cls.prefix = "mn%02ds" % num
         numokay = True
         for phy in phys:
             if phy.startswith(cls.prefix):
                 num += 1
                 numokay = False
                 break
     try:
         for i in range(0, n_radios):
             p = subprocess.Popen(
                 ["hwsim_mgmt", "-c", "-n", cls.prefix + ("%02d" % i)],
                 stdin=subprocess.PIPE,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE,
                 bufsize=-1)
             output, err_out = p.communicate()
             if p.returncode == 0:
                 m = re.search("ID (\d+)", output)
                 debug("Created mac80211_hwsim device with ID %s\n" %
                       m.group(1))
                 cls.hwsim_ids.append(m.group(1))
             else:
                 error(
                     "\nError on creating mac80211_hwsim device with name %s"
                     % (cls.prefix + ("%02d" % i)))
                 error("\nOutput: %s" % output)
                 error("\nError: %s" % err_out)
     except:
         info("Warning! If you already had Mininet-WiFi installed "
              "please run util/install.sh -W and then sudo make install.\n")
    def do_host(self, line):
        args = line.split()
        if len(args) != 2:
            error('invalid number of args: host <host name> {up, down}\n')
            return

        host = args[0]
        command = args[1]
        if host not in self.mn or self.mn.get(host) not in self.mn.hosts:
            error('invalid host: %s\n' % args[1])
        else:
            if command == 'up':
                op = 'up'
            elif command == 'down':
                op = 'down'
            else:
                error('invalid command: host <host name> {up, down}\n')
                return

            for intf in self.mn.get(host).intfList():
                intf.link.intf1.ifconfig(op)
                intf.link.intf2.ifconfig(op)
Exemple #34
0
def delayCmds(parent, delay=None, jitter=None, loss=None, max_queue_size=None):
    "Internal method: return tc commands for delay and loss"
    cmds = []
    if delay and delay < 0:
        error('Negative delay', delay, '\n')
    elif jitter and jitter < 0:
        error('Negative jitter', jitter, '\n')
    elif loss and (loss < 0 or loss > 100):
        error('Bad loss percentage', loss, '%%\n')
    else:
        # Delay/jitter/loss/max queue size
        netemargs = '%s%s%s%s' % (
            'delay %s ' % delay if delay is not None else '',
            '%s ' % jitter if jitter is not None else '',
            'loss %0.4f ' % loss if loss is not None else '',  # The fix
            'limit %d' % max_queue_size if max_queue_size is not None else '')
        if netemargs:
            cmds = [
                '%s qdisc add dev %s ' + parent + ' handle 10: netem ' +
                netemargs
            ]
            parent = ' parent 10:1 '
    return cmds, parent
Exemple #35
0
    def create_hwsim(self, n):
        # generate prefix
        num = 0
        numokay = False
        self.prefix = ""
        cmd = 'find /sys/kernel/debug/ieee80211 -name hwsim | grep %05d | cut -d/ -f 6 | sort' % os.getpid(
        )  # grep on PID in devicelist
        phys = subprocess.check_output(cmd,
                                       shell=True).decode('utf-8').split("\n")

        while not numokay:
            self.prefix = "mn%05dp%02ds" % (os.getpid(), num
                                            )  # Add PID to mn-devicenames
            numokay = True
            for phy in phys:
                if phy.startswith(self.prefix):
                    num += 1
                    numokay = False
                    break

        p = subprocess.Popen(
            ["hwsim_mgmt", "-c", "-n", self.prefix + ("%02d" % n)],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            bufsize=-1)
        output, err_out = p.communicate()
        if p.returncode == 0:
            m = re.search("ID (\d+)", output.decode())
            debug("Created mac80211_hwsim device with ID %s\n" % m.group(1))
            Mac80211Hwsim.hwsim_ids.append(m.group(1))
        else:
            error("\nError on creating mac80211_hwsim device with name %s" %
                  (self.prefix + ("%02d" % n)))
            error("\nOutput: %s" % output)
            error("\nError: %s" % err_out)
Exemple #36
0
    
logging.basicConfig(filename=args.sync_event_log,level=logging.WARNING)

if args.kern:
    print('kernel switch used')
else:
    print('user switch detected')

if args.stp and args.onos:
    warn("stp and onos enabled")

if args.stp and args.onos:
    warn("rstp and onos enabled")

if args.stp and args.rstp:
    error("stp and rstp can not both be enabled")
    exit(1)

if args.stp:
    print('stp enabled')

elif args.rstp:
    print('rstp enabled')

elif args.onos:
    print('onos enabled')

else:
    print('custom controller')

if args.ovs_vt:
Exemple #37
0
    def bwCmds(self,
               bw=None,
               speedup=0,
               use_hfsc=False,
               use_tbf=False,
               latency_ms=None,
               enable_ecn=False,
               enable_red=False):
        "Return tc commands to set bandwidth"

        cmds, parent = [], ' root '

        if bw and (bw < 0 or bw > self.bwParamMax):
            error('Bandwidth limit', bw,
                  'is outside supported range 0..%d' % self.bwParamMax,
                  '- ignoring\n')
        elif bw is not None:
            # BL: this seems a bit brittle...
            if (speedup > 0 and self.node.name[0:1] == 's'):
                bw = speedup
            # This may not be correct - we should look more closely
            # at the semantics of burst (and cburst) to make sure we
            # are specifying the correct sizes. For now I have used
            # the same settings we had in the mininet-hifi code.
            if use_hfsc:
                cmds += [
                    '%s qdisc add dev %s root handle 5:0 hfsc default 1',
                    '%s class add dev %s parent 5:0 classid 5:1 hfsc sc ' +
                    'rate %fMbit ul rate %fMbit' % (bw, bw)
                ]
            elif use_tbf:
                if latency_ms is None:
                    latency_ms = 15 * 8 / bw
                cmds += [
                    '%s qdisc add dev %s root handle 5: tbf ' +
                    'rate %fMbit burst 15000 latency %fms' % (bw, latency_ms)
                ]
            else:
                cmds += [
                    '%s qdisc add dev %s root handle 5:0 htb default 1',
                    '%s class add dev %s parent 5:0 classid 5:1 htb ' +
                    'rate %fMbit burst 15k' % bw
                ]
            parent = ' parent 5:1 '

            # ECN or RED
            if enable_ecn:
                cmds += [
                    '%s qdisc add dev %s' + parent +
                    'handle 6: red limit 1000000 ' +
                    'min 30000 max 35000 avpkt 1500 ' + 'burst 20 ' +
                    'bandwidth %fmbit probability 1 ecn' % bw
                ]
                parent = ' parent 6: '
            elif enable_red:
                cmds += [
                    '%s qdisc add dev %s' + parent +
                    'handle 6: red limit 1000000 ' +
                    'min 30000 max 35000 avpkt 1500 ' + 'burst 20 ' +
                    'bandwidth %fmbit probability 1' % bw
                ]
                parent = ' parent 6: '
        return cmds, parent
Exemple #38
0
def end_to_end_test(cert_dir=CERT_DIR,
                    target=TARGET,
                    gnmi_addr=GNMI_ADDR,
                    gnmi_port=GNMI_PORT,
                    cfile=FAUCET.cfile,
                    prom_addr='http://localhost',
                    prom_port=9302,
                    nohup=False,
                    config_stat_reload=0):
    """Simple end-to-end test of FAUCET config agent
       cert_dir: directory to store fake certs
       target: hostname for certs and gnmi_* -target
       gnmi_addr: gNMI address that agent will listen on
       gnmi_port: gNMI port that agent will listen on
       prom_addr: FAUCET prometheus address (http://localhost)
       prom_port: FAUCET prometheus port (9302)
       nohup: send HUP to FAUCET to reload config? (False)
       config_stat_reload: tell FAUCET to automatically reload (0)"""

    info('\n* Generating certificates\n')
    make_certs(cert_dir=cert_dir)
    client_auth = (' -ca {cert_dir}/fakeca.crt -cert {cert_dir}/fakeclient.crt'
                   ' -key {cert_dir}/fakeclient.key'
                   ' -target_name {target}').format(**locals()).split()

    info('* Starting network\n')
    faucet = partial(FAUCET, config_stat_reload=config_stat_reload)
    net = Mininet(topo=TestTopo(), controller=faucet, autoSetMacs=True)
    net.start()

    info('* Shutting down any agents listening on %d\n' % GNMI_PORT)
    kill_server(port=gnmi_port)

    info('* Starting agent\n')
    agent_log = open('faucetagent.log', 'w')
    nohup = '--nohup' if nohup else ''
    agent_cmd = ('./faucetagent.py  --cert {cert_dir}/fakeserver.crt'
                 ' --key {cert_dir}/fakeserver.key'
                 ' --gnmiaddr {gnmi_addr}'
                 ' --gnmiport {gnmi_port}'
                 ' --configfile {cfile}'
                 ' --promaddr {prom_addr}'
                 ' --promport {prom_port}'
                 ' --dpwait 1.0'
                 ' {nohup}').format(**locals()).split()
    agent = Popen(agent_cmd, stdout=agent_log, stderr=agent_log)

    info('* Waiting for agent to start up\n')
    wait_server(port=gnmi_port)

    info('* Checking gNMI capabilities\n')
    result = run(['gnmi_capabilities'] + client_auth, stdout=PIPE, check=True)
    items = [
        'capabilitiesResponse:', 'name: "FAUCET"', 'organization: "faucet.nz"'
    ]
    capabilities = result.stdout.decode()
    for item in items:
        assert item in capabilities, ("missing capability field <%s>" % item)

    fail_count = 0

    for test_num, test_case in enumerate(TEST_CASES):

        # Get the test case configuration
        config = CONFIG.format(**test_case)

        info('* Sending test configuration to agent\n')
        cmd = ['gnmi_set'] + client_auth + ['-replace=/:' + config]
        result = run(cmd, stdout=PIPE, check=True)
        sent = string_val(result.stdout.decode())

        info('* Fetching configuration from agent\n')
        cmd = ['gnmi_get'] + client_auth + ['-xpath=/']
        result = run(cmd, stdout=PIPE, check=True)
        received = string_val(result.stdout.decode())

        info('* Verifying received configuration\n')
        if sent != received:
            error('ERROR: received config differs from sent config\n')

        # Assume state is good after all switches have some new flows
        info('* Waiting for VLAN flows\n')
        wait_for_flows(net.switches, ['dl_vlan=%d' % test_case['vid1']])
        info('* Sending gratuitous ARPs\n')
        send_arps(net.hosts)
        info('* Waiting for MAC learning\n')
        wait_for_flows(net.switches,
                       ['dl_dst=%s' % host.MAC() for host in net.hosts])

        groups = test_case['groups']
        info('* Verifying connectivity for', groups, '\n')
        host_groups = [net.get(*group) for group in groups]
        errors = check(hosts=net.hosts, groups=host_groups)
        info('Test Case #%d:' % test_num,
             'OK' if errors == 0 else 'FAIL (%d errors)' % errors, '\n')

        if errors:
            fail_count += 1

    info('* Stopping agent\n')
    agent.send_signal(SIGINT)
    agent.wait()
    agent_log.close()

    info('* Stopping network\n')
    net.stop()

    return fail_count
def runTopo(topoFile, simParams, hostOptions, checkLevel, controller, switch):
    topo = CustomTopo(topoFilePath=topoFile,
                      simParams=simParams,
                      hostOptions=hostOptions)
    if checkLevel > 1:
        topo.setNetOption('link', TCLink)
    # net = CustomMininet(topo = topo, controller = Beacon, autoSetMacs = True, **topo.getNetOptions())
    # net = CustomMininet(topo = topo, controller = Beacon, **topo.getNetOptions())
    net = CustomMininet(topo=topo,
                        controller=controller,
                        switch=switch,
                        **topo.getNetOptions())
    global netprobes
    netprobes = collections.OrderedDict()
    try:
        lg.output('Constructing virtual network..\n')
        start(net)
        check(net, checkLevel)
        lg.output("Starting hosts")
        lg.info(": ")
        for host in net.hosts:
            lg.info("%s " % host.name)
            if host.monitor_rules is not None:
                monitor.start(host, host.monitor_rules)
            if host.command is not None:
                lg.info("cmd ")
                host.command = host.command.format(
                    commandOpts=host.commandOpts,
                    name=host.name).format(name=host.name)
                if host.isXHost:
                    t = makeTerm(host, cmd=host.command)
                    if len(t) < 1:
                        lg.error(
                            "Error while starting terminal for host %s\n" %
                            host.name)
                        continue
                    if len(t) == 2:
                        tunnel, term = t
                    else:
                        term = t
                    try:
                        if term.poll() is not None:
                            lg.error(
                                "Terminal with command %s ended early for host %s : %s\n"
                                % (host.command, host.name,
                                   repr(term.communicate())))
                    except:
                        pass
                    netprobes[host.name] = term
                else:
                    netprobes[host.name] = runCommand(host)
                    # print(netprobes[host.name].communicate())
            else:
                if host.isXHost:
                    makeTerm(host)
                    lg.info("term ")
            lg.info("done ")
        lg.output("\n")
        EventsManager.startClock(net)
        interract(net)
        mon = False
        counter = monitor.Counter()
        for host in net.hosts:
            if host.monitor_rules is not None:
                monitor.collect(host, monitor_file, counter)
                monitor.stop(host, host.monitor_rules)
                mon = True
        for name, probe in netprobes.iteritems():
            lg.info("Send sigint to probe %s\n" % name)
            import signal

            try:
                probe.send_signal(signal.SIGINT)
                time.sleep(0.05)
            except OSError as e:
                lg.error("Failed to send SIGINT to %s : %s\n" % (name, e))
        if mon:
            monitor.writeSummary(monitor_file, counter)
    finally:
        stop(net)
        # cleanup !
        lg.info("Stopping remaining processes...\n")
        kill = 0
        for name, probe in netprobes.iteritems():
            if probe.poll() is None:
                kill += 1
        if kill > 0:
            lg.info("Found %s process(es) to kill\n" % kill)
            time.sleep(3)
            for name, probe in netprobes.iteritems():
                if probe.poll() is None:
                    try:
                        lg.info("Send terminate signal to %s\n" % name)
                        probe.terminate()
                        time.sleep(0.001)
                    except OSError as e:
                        lg.error("Failed to terminate %s : %s\n" % (name, e))
            time.sleep(3)
            for name, probe in netprobes.iteritems():
                if probe.poll() is None:
                    try:
                        lg.info("Send kill signal to %s\n" % name)
                        probe.kill()
                    except OSError as e:
                        lg.error("Failed to kill %s : %s\n" % (name, e))
        lg.output("\nAll done\n")
Exemple #40
0
def show_watch_dropped():
    print "显示 tc dropped 丢包情况"
    DROPPED = "dropped"
    show_class_watch_values(DROPPED)


def runner():
    #show_qdisc()
    #show_class()
    #show_qdisc_errors_once()
    show_watch_dropped()


if __name__ == "__main__":
    try:
        runner()
    except KeyboardInterrupt:
        info("\n\nKeyboard Interrupt. Shutting down and cleaning up...\n\n")
        #cleanup()
    except Exception:
        # Print exception
        type_, val_, trace_ = sys.exc_info()
        errorMsg = ("-" * 80 + "\n" + "Caught exception. Cleaning up...\n\n" +
                    "%s: %s\n" % (type_.__name__, val_) + "-" * 80 + "\n")
        error(errorMsg)
        # Print stack trace to debug log
        import traceback
        stackTrace = traceback.format_exc()
        debug(stackTrace + "\n")
        #cleanup()
Exemple #41
0
import os
import socket
import re
import json
import urllib2

from mininet.log import info, warn, error
from mininet.node import Switch

if 'ONOS_ROOT' not in os.environ:
    error("ERROR: environment var $ONOS_ROOT not set")
    exit()

BMV2_TARGET = 'simple_switch_grpc'
ONOS_ROOT = os.environ["ONOS_ROOT"]
CPU_PORT = 255


class ONOSBmv2Switch(Switch):
    """BMv2 software switch with gRPC server"""

    deviceId = 0
    instanceCount = 0

    def __init__(self, name, json=None, debugger=False, loglevel="warn", elogger=False,
                 persistent=False, grpcPort=None, thriftPort=None, netcfg=True, **kwargs):
        Switch.__init__(self, name, **kwargs)
        self.grpcPort = ONOSBmv2Switch.pickUnusedPort() if not grpcPort else grpcPort
        self.thriftPort = ONOSBmv2Switch.pickUnusedPort() if not thriftPort else thriftPort
        if self.dpid:
            self.deviceId = int(self.dpid, 0 if 'x' in self.dpid else 16)
Exemple #42
0
def resetTarget(target):
    try:
        target.reset()
    except Exception as e:
        error("Error while resetting event on %s : %s" % (target.name, e))
        error(traceback.format_exc())
Exemple #43
0
class LINCSwitch(OpticalSwitch):
    """
    LINCSwitch class
    """
    # FIXME:Sometimes LINC doesn't remove pipes and on restart increase the pipe
    # number from erlang.pipe.1.* to erlang.pipe.2.*, so should read and write
    # from latest pipe files. For now we are removing all the pipes before
    # starting LINC.
    ### User Name ###
    user = os.getlogin()
    ### pipes ###
    readPipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.r".format(user)
    writePipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.w".format(user)
    ### sys.config path ###
    sysConfig = "/home/{}/linc-oe/rel/linc/releases/1.0/sys.config".format(
        user)
    ### method, mapping dpid to LINC switchId ###
    @staticmethod
    def dpids_to_ids(sysConfig):
        '''
        return the dict containing switch dpids as key and LINC switch id as values
        '''
        dpids_to_ids = {}
        fd = None
        try:
            with open(sysConfig, 'r', 0) as fd:
                switch_id = 1
                for line in fd:
                    dpid = re.search(
                        r'([0-9A-Fa-f]{2}[:-]){7}([0-9A-Fa-f]{2})+', line,
                        re.I)
                    if dpid:
                        dpids_to_ids[dpid.group().replace(':', '')] = switch_id
                        switch_id += 1
            return dpids_to_ids
        except:
            print "Error working with {}\nError: {}\n".format(
                sysConfig, sys.exc_info())
            fd.close()
            return None

    ### dict of containing dpids as key and corresponding LINC switchId as values ###
    dpidsToLINCSwitchId = dpids_to_ids.__func__(sysConfig)

    @staticmethod
    def findDir(directory, userName):
        "finds and returns the path of any directory in the user's home directory"
        homeDir = '/home/' + userName
        Dir = quietRun('find %s -maxdepth 1 -name %s -type d' %
                       (homeDir, directory)).strip('\n')
        DirList = Dir.split('\n')
        if not Dir:
            return None
        elif len(DirList) > 1:
            warn('***WARNING: Found multiple instances of %s; using %s\n' %
                 (directory, DirList[0]))
            return DirList[0]
        else:
            return Dir

    ### ONOS Directory ###
    try:
        onosDir = os.environ['ONOS_ROOT']
    except:
        onosDir = findDir('onos', user)
        if not onosDir:
            error('Please set ONOS_ROOT environment variable!\n')
        else:
            os.environ['ONOS_ROOT'] = onosDir
    ### LINC-directory
    lincDir = findDir.__func__('linc-oe', user)
    if not lincDir:
        error("***ERROR: Could not find linc-oe in user's home directory\n")
    ### LINC config generator directory###
    configGen = findDir.__func__('LINC-config-generator', user)
    if not configGen:
        error(
            "***ERROR: Could not find LINC-config-generator in user's home directory\n"
        )
    # list of all the controllers
    controllers = None

    def __init__(self,
                 name,
                 dpid=None,
                 allowed=True,
                 switchType='ROADM',
                 topo=None,
                 annotations={},
                 controller=None,
                 **params):
        params['inNamespace'] = False
        Switch.__init__(self, name, dpid=dpid, **params)
        self.name = name
        self.annotations = annotations
        self.allowed = allowed
        self.switchType = switchType
        self.configDict = {
        }  # dictionary that holds all of the JSON configuration data
        self.crossConnects = []
        self.deletedCrossConnects = []
        self.controller = controller
        self.lincId = self._get_linc_id()  # use to communicate with LINC
        self.lincStarted = False

    def start(self, *opts, **params):
        '''Instead of starting a virtual switch, we build the JSON
           dictionary for the emulated optical switch'''
        # TODO:Once LINC has the ability to spawn network element dynamically
        # we need to use this method to spawn new logical LINC switch rather then
        # bulding JSON.
        # if LINC is started then we can start and stop logical switches else create JSON
        if self.lincStarted:
            return self.start_oe()
        self.configDict['uri'] = 'of:' + self.dpid
        self.configDict['annotations'] = self.annotations
        self.configDict['annotations'].setdefault('name', self.name)
        self.configDict['hw'] = 'LINC-OE'
        self.configDict['mfr'] = 'Linc'
        self.configDict['mac'] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1]
        self.configDict['type'] = self.switchType
        self.configDict['ports'] = []
        for port, intf in self.intfs.items():
            if intf.name == 'lo':
                continue
            else:
                self.configDict['ports'].append(intf.json())
        self.lincStarted = True

    def stop(self, deleteIntfs=False):
        '''
        stop the existing switch
        '''
        # TODO:Add support for deleteIntf
        self.stop_oe()

    def dpctl(self, *args):
        "Run dpctl command: ignore for now"
        pass

    def write_to_cli(self, command):
        '''
        send command to LINC
        '''
        fd = None
        try:
            fd = open(self.writePipe, 'w', 0)
            fd.write(command)
            fd.close()
        except:
            print "Error working with {}\nError: {}\n".format(
                self.writePipe, sys.exc_info())
            if fd:
                fd.close()

    def read_from_cli(self):
        '''
        read the output from the LINC CLI
        '''
        response = None
        fd = None
        try:
            fd = open(self.readPipe, 'r', 0)
            fcntl.fcntl(fd, fcntl.F_SETFL,
                        os.O_NONBLOCK)  # for non-blocking read
            # FIXME:Due to non-blocking read most for the time we read nothing
            response = fd.read()
            fd.close()
        except:
            # print "Error working with {}\nError: {}\n".format(self.readPipe, sys.exc_info())
            if fd:
                fd.close()
        return response

    def _get_linc_id(self):
        '''
        return the corresponding LINC switchId.
        '''
        return LINCSwitch.dpidsToLINCSwitchId.get(self.dpid)

    #--------------------------------------------------------------------------
    # LINC CLI commands
    #--------------------------------------------------------------------------
    def start_oe(self):
        '''
        start the existing LINC switch
        '''
        #starting Switch
        cmd = "linc:start_switch({}).\r\n".format(self.lincId)
        self.write_to_cli(cmd)
        #hanlding taps interfaces related to the switch
        crossConnectJSON = {}
        linkConfig = []
        for i in range(0, len(self.deletedCrossConnects)):
            crossConnect = self.deletedCrossConnects.pop()
            tap = None
            if isinstance(crossConnect.intf1.node, LINCSwitch):
                intf = crossConnect.intf2
                tapPort = crossConnect.intf1.port
            else:
                intf = crossConnect.intf1
                tapPort = crossConnect.intf2.port
            tap = LINCSwitch.findTap(self, tapPort)
            if tap:
                LINCSwitch.setupInts([tap])
                intf.node.attach(tap)
            self.crossConnects.append(crossConnect)
            linkConfig.append(crossConnect.json())
        #Sending crossConnect info to the ONOS.
        crossConnectJSON['links'] = linkConfig
        with open("crossConnect.json", 'w') as fd:
            json.dump(crossConnectJSON, fd, indent=4, separators=(',', ': '))
        info('*** Pushing crossConnect.json to ONOS\n')
        output = quietRun('%s/tools/test/bin/onos-topo-cfg %s\
         Topology.json' % (self.onosDir, self.controllers[0].ip),
                          shell=True)

    def stop_oe(self):
        '''
        stop the existing LINC switch
        '''
        cmd = "linc:stop_switch({}).\r\n".format(self.lincId)
        self.write_to_cli(cmd)
        #handling taps if any
        for i in range(0, len(self.crossConnects)):
            crossConnect = self.crossConnects.pop()
            if isinstance(crossConnect.intf1.node, LINCSwitch):
                intf = crossConnect.intf2
                tapPort = crossConnect.intf1.port
            else:
                intf = crossConnect.intf1
                tapPort = crossConnect.intf2.port
            intf.node.detach(LINCSwitch.findTap(self, tapPort))
            self.deletedCrossConnects.append(crossConnect)

    def w_port_up(self, port):
        '''
        port_up
        '''
        cmd = "linc:port_up({},{}).\r\n".format(self.lincId, port)
        self.write_to_cli(cmd)

    def w_port_down(self, port):
        '''
        port_down
        '''
        cmd = "linc:port_down({},{}).\r\n".format(self.lincId, port)
        self.write_to_cli(cmd)

    # helper functions
    @staticmethod
    def switchJSON(switch):
        "Returns the json configuration for a packet switch"
        configDict = {}
        configDict['uri'] = 'of:' + switch.dpid
        configDict['mac'] = quietRun('cat /sys/class/net/%s/address' %
                                     switch.name).strip('\n').translate(
                                         None, ':')
        configDict['hw'] = 'PK'  # FIXME what about OVS?
        configDict['mfr'] = 'Linc'  # FIXME what about OVS?
        configDict['type'] = 'SWITCH'  # FIXME what about OVS?
        annotations = switch.params.get('annotations', {})
        annotations.setdefault('name', switch.name)
        configDict['annotations'] = annotations
        ports = []
        for port, intf in switch.intfs.items():
            if intf.name == 'lo':
                continue
            portDict = {}
            portDict['port'] = port
            portDict['type'] = 'FIBER' if isinstance(intf.link,
                                                     LINCLink) else 'COPPER'
            intfList = [intf.link.intf1, intf.link.intf2]
            intfList.remove(intf)
            portDict['speed'] = intfList[0].speed if isinstance(
                intf.link, LINCLink) else 0
            ports.append(portDict)
        configDict['ports'] = ports
        return configDict

    @staticmethod
    def bootOE(net):
        "Start the LINC optical emulator within a mininet instance"
        opticalJSON = {}
        linkConfig = []
        devices = []
        #setting up the controllers for LINCSwitch class
        LINCSwitch.controllers = net.controllers

        for switch in net.switches:
            if isinstance(switch, OpticalSwitch):
                devices.append(switch.json())
            else:
                devices.append(LINCSwitch.switchJSON(switch))
        opticalJSON['devices'] = devices

        for link in net.links:
            if isinstance(link, LINCLink):
                linkConfig.append(link.json())
        opticalJSON['links'] = linkConfig

        info('*** Writing Topology.json file\n')
        with open('Topology.json', 'w') as outfile:
            json.dump(opticalJSON, outfile, indent=4, separators=(',', ': '))

        info(
            '*** Converting Topology.json to linc-oe format (TopoConfig.json) file\n'
        )
        output = quietRun(
            '%s/tools/test/bin/onos-oecfg ./Topology.json > TopoConfig.json' %
            LINCSwitch.onosDir,
            shell=True)
        if output:
            error('***ERROR: Error creating topology file: %s ' % output +
                  '\n')
            return False

        info('*** Creating sys.config...\n')
        output = quietRun(
            '%s/config_generator TopoConfig.json %s/sys.config.template %s %s'
            % (LINCSwitch.configGen, LINCSwitch.configGen,
               LINCSwitch.controllers[0].ip, LINCSwitch.controllers[0].port),
            shell=True)
        if output:
            error('***ERROR: Error creating sys.config file: %s\n' % output)
            return False

        info('*** Setting multiple controllers in sys.config...\n')
        searchStr = '\[{"Switch.*$'
        ctrlStr = ''
        for index in range(len(LINCSwitch.controllers)):
            ctrlStr += '{"Switch%d-Controller","%s",%d,tcp},' % (
                index, net.controllers[index].ip, net.controllers[index].port)
        replaceStr = '[%s]},' % ctrlStr[:-1]  # Cut off last comma
        sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr)
        output = quietRun(sedCmd, shell=True)

        info('*** Copying sys.config to linc-oe directory: ', output + '\n')
        output = quietRun('cp -v sys.config %s/rel/linc/releases/1.0/' %
                          LINCSwitch.lincDir,
                          shell=True).strip('\n')
        info(output + '\n')

        info('*** Adding taps and bringing them up...\n')
        LINCSwitch.setupInts(LINCSwitch.getTaps())

        info('*** removing pipes if any \n')
        quietRun('rm /tmp/home/%s/linc-oe/rel/linc/*' % LINCSwitch.user,
                 shell=True)

        info('*** Starting linc OE...\n')
        output = quietRun('%s/rel/linc/bin/linc start' % LINCSwitch.lincDir,
                          shell=True)
        if output:
            error('***ERROR: LINC-OE: %s' % output + '\n')
            quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir,
                     shell=True)
            return False

        info('*** Waiting for linc-oe to start...\n')
        LINCSwitch.waitStarted(net)

        info(
            '*** Adding cross-connect (tap) interfaces to packet switches...\n'
        )
        for link in net.links:
            if isinstance(link, LINCLink):
                if link.annotations['optical.type'] == 'cross-connect':
                    for intf in [link.intf1, link.intf2]:
                        if not isinstance(intf, LINCIntf):
                            intfList = [intf.link.intf1, intf.link.intf2]
                            intfList.remove(intf)
                            intf2 = intfList[0]
                            intf.node.attach(
                                LINCSwitch.findTap(intf2.node,
                                                   intf2.node.ports[intf2]))

        info('*** Waiting for all devices to be available in ONOS...\n')
        url = 'http://%s:8181/onos/v1/devices' % LINCSwitch.controllers[0].ip
        time = 0
        while True:
            response = json.load(urllib2.urlopen(url))
            devs = response.get('devices')

            # Wait for all devices to be registered
            if (len(devices) != len(devs)):
                continue

            # Wait for all devices to available
            available = True
            for d in devs:
                available &= d['available']
            if available:
                break

            if (time >= TIMEOUT):
                error(
                    '***ERROR: ONOS did not register devices within %s seconds\n'
                    % TIMEOUT)
                break

            time += SLEEP_TIME
            sleep(SLEEP_TIME)

        info('*** Pushing Topology.json to ONOS\n')
        for index in range(len(LINCSwitch.controllers)):
            output = quietRun(
                '%s/tools/test/bin/onos-topo-cfg %s Topology.json &' %
                (LINCSwitch.onosDir, LINCSwitch.controllers[index].ip),
                shell=True)
            # successful output contains the two characters '{}'
            # if there is more output than this, there is an issue
            if output.strip('{}'):
                warn('***WARNING: Could not push topology file to ONOS: %s\n' %
                     output)

    @staticmethod
    def waitStarted(net, timeout=TIMEOUT):
        "wait until all tap interfaces are available"
        tapCount = 0
        time = 0
        for link in net.links:
            if isinstance(link, LINCLink):
                if link.annotations['optical.type'] == 'cross-connect':
                    tapCount += 1

        while True:
            if str(tapCount) == quietRun('ip addr | grep tap | wc -l',
                                         shell=True).strip('\n'):
                return True
            if timeout:
                if time >= TIMEOUT:
                    error(
                        '***ERROR: LINC OE did not start within %s seconds\n' %
                        TIMEOUT)
                    return False
                time += SLEEP_TIME
            sleep(SLEEP_TIME)

    @staticmethod
    def shutdownOE():
        "stop the optical emulator"
        info('*** Stopping linc OE...\n')
        quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)

    @staticmethod
    def setupInts(intfs):
        '''
        add taps and bring them up.
        '''
        for i in intfs:
            quietRun('ip tuntap add dev %s mode tap' % i)
            quietRun('ip link set dev %s up' % i)
            info('*** Intf %s set\n' % i)

    @staticmethod
    def getTaps(path=None):
        '''
        return list of all the tops in sys.config
        '''
        if path is None:
            path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir
        fd = open(path, 'r', 0)
        sys_data = fd.read()
        taps = re.findall('tap\d+', sys_data)
        fd.close()
        return taps

    @staticmethod
    def findUser():
        "Try to return logged-in (usually non-root) user"
        try:
            # If we're running sudo
            return os.environ['SUDO_USER']
        except:
            try:
                # Logged-in user (if we have a tty)
                return quietRun('who am i').split()[0]
            except:
                # Give up and return effective user
                return quietRun('whoami')

    @staticmethod
    def findTap(node, port, path=None):
        '''utility function to parse through a sys.config
           file to find tap interfaces for a switch'''
        switch = False
        portLine = ''
        intfLines = []

        if path is None:
            path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir

        with open(path) as f:
            for line in f:
                if 'tap' in line:
                    intfLines.append(line)
                if node.dpid in line.translate(None, ':'):
                    switch = True
                    continue
                if switch:
                    if 'switch' in line:
                        switch = False
                    if 'port_no,%s}' % port in line:
                        portLine = line
                        break

        if portLine:
            m = re.search('port,\d+', portLine)
            port = m.group(0).split(',')[1]
        else:
            error('***ERROR: Could not find any ports in sys.config\n')
            return

        for intfLine in intfLines:
            if 'port,%s' % port in intfLine:
                return re.findall('tap\d+', intfLine)[0]

    def json(self):
        "return json configuration dictionary for switch"
        return self.configDict

    def terminate(self):
        pass
Exemple #44
0
 def intfsUp(self):
     """Bring all interfaces up"""
     for intf in self.intfs.values():
         cmdOutput = intf.ifconfig('up')
         if cmdOutput:
             error("Error setting %s up: %s " % (intf.name, cmdOutput))
Exemple #45
0
 def do_x(self, line):
     """Create an X11 tunnel to the given node,
        optionally starting a client.
        Usage: x node [cmd args]"""
     error("not supported")
Exemple #46
0
 def do_gterm(self, line):
     """Spawn gnome-terminal(s) for the given node(s).
        Usage: gterm node1 node2 ..."""
     error("not supported")
Exemple #47
0
 def do_xterm(self, line, term='xterm'):
     """Spawn xterm(s) for the given node(s).
        Usage: xterm node1 node2 ..."""
     error("not supported")
Exemple #48
0
 def add_fault(self, name):
     """
     Add a general/controller fault
     """
     error('FAULT: %s\n' % name)
     self.fault_list.append(name)
Exemple #49
0
    def add(self,
            Type=None,
            Longitude=None,
            Latitude=None,
            MAC=None,
            Idx=None,
            Name='',
            Region='',
            IP='',
            PMU_IDX='',
            Delay='',
            BW='',
            Loss='',
            Jitter='',
            From='',
            To='',
            **kwargs):

        if not self._name:
            log.error('Device name not initialized')
            return

        if Type != self._name:
            return

        mac = None if MAC == 'None' else MAC
        idx = self._name + '_' + str(self.n) if not Idx else Idx
        pmu_idx = None if PMU_IDX == 'None' else int(PMU_IDX)

        if idx in self.idx:
            log.error('PMU Idx <{i}> has conflict.\n'.format(i=idx))

        def to_type(var):
            """Helper function to convert field to a list or a None object """
            if var == 'None':
                out = None
            else:
                out = var
            return out

        delay = to_type(Delay)
        bw = to_type(BW)
        loss = to_type(Loss)
        jitter = to_type(Jitter)
        fr = to_type(From)
        to = to_type(To)

        lat = None if Latitude == 'None' else float(Latitude)
        lon = None if Longitude == 'None' else float(Longitude)

        self.name.append(Name)
        self.region.append(Region)
        self.coords.append((lat, lon))
        self.ip.append(IP)

        self.mac.append(mac)
        self.idx.append(idx)
        # self.connections.append(conn)

        self.pmu_idx.append(pmu_idx)
        self.delay.append(delay)
        self.bw.append(bw)
        self.loss.append(loss)
        self.jitter.append(jitter)
        self.fr.append(fr)
        self.to.append(to)

        self.n += 1
Exemple #50
0
    def __init__(self,
                 name,
                 sw_path=None,
                 json_path=None,
                 grpc_port=None,
                 thrift_port=None,
                 pcap_dump=False,
                 log_console=False,
                 verbose=False,
                 device_id=None,
                 enable_debugger=False,
                 log_file=None,
                 **kwargs):
        Switch.__init__(self, name, **kwargs)
        assert (sw_path)
        self.sw_path = sw_path
        # make sure that the provided sw_path is valid
        pathCheck(sw_path)

        if json_path is not None:
            # make sure that the provided JSON file exists
            if not os.path.isfile(json_path):
                error("Invalid JSON file.\n")
                exit(1)
            self.json_path = json_path
        else:
            self.json_path = None

        if grpc_port is not None:
            self.grpc_port = grpc_port
        else:
            self.grpc_port = P4RuntimeSwitch.next_grpc_port
            P4RuntimeSwitch.next_grpc_port += 1

        if thrift_port is not None:
            self.thrift_port = thrift_port
        else:
            self.thrift_port = P4RuntimeSwitch.next_thrift_port
            P4RuntimeSwitch.next_thrift_port += 1

        if check_listening_on_port(self.grpc_port):
            error(
                '%s cannot bind port %d because it is bound by another process\n'
                % (self.name, self.grpc_port))
            exit(1)

        self.verbose = verbose
        self.pcap_dump = pcap_dump
        self.enable_debugger = enable_debugger
        self.log_console = log_console
        if log_file is not None:
            self.log_file = log_file
        else:
            self.log_file = "/tmp/p4s.{}.log".format(self.name)
        self.output = open(self.log_file, 'w')

        if device_id is not None:
            self.device_id = device_id
            P4Switch.device_id = max(P4Switch.device_id, device_id)
        else:
            self.device_id = P4Switch.device_id
            P4Switch.device_id += 1

        self.nanomsg = "ipc:///tmp/bm-{}-log.ipc".format(self.device_id)
Exemple #51
0
    def bootOE(net):
        "Start the LINC optical emulator within a mininet instance"
        opticalJSON = {}
        linkConfig = []
        devices = []
        #setting up the controllers for LINCSwitch class
        LINCSwitch.controllers = net.controllers

        for switch in net.switches:
            if isinstance(switch, OpticalSwitch):
                devices.append(switch.json())
            else:
                devices.append(LINCSwitch.switchJSON(switch))
        opticalJSON['devices'] = devices

        for link in net.links:
            if isinstance(link, LINCLink):
                linkConfig.append(link.json())
        opticalJSON['links'] = linkConfig

        info('*** Writing Topology.json file\n')
        with open('Topology.json', 'w') as outfile:
            json.dump(opticalJSON, outfile, indent=4, separators=(',', ': '))

        info(
            '*** Converting Topology.json to linc-oe format (TopoConfig.json) file\n'
        )
        output = quietRun(
            '%s/tools/test/bin/onos-oecfg ./Topology.json > TopoConfig.json' %
            LINCSwitch.onosDir,
            shell=True)
        if output:
            error('***ERROR: Error creating topology file: %s ' % output +
                  '\n')
            return False

        info('*** Creating sys.config...\n')
        output = quietRun(
            '%s/config_generator TopoConfig.json %s/sys.config.template %s %s'
            % (LINCSwitch.configGen, LINCSwitch.configGen,
               LINCSwitch.controllers[0].ip, LINCSwitch.controllers[0].port),
            shell=True)
        if output:
            error('***ERROR: Error creating sys.config file: %s\n' % output)
            return False

        info('*** Setting multiple controllers in sys.config...\n')
        searchStr = '\[{"Switch.*$'
        ctrlStr = ''
        for index in range(len(LINCSwitch.controllers)):
            ctrlStr += '{"Switch%d-Controller","%s",%d,tcp},' % (
                index, net.controllers[index].ip, net.controllers[index].port)
        replaceStr = '[%s]},' % ctrlStr[:-1]  # Cut off last comma
        sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr)
        output = quietRun(sedCmd, shell=True)

        info('*** Copying sys.config to linc-oe directory: ', output + '\n')
        output = quietRun('cp -v sys.config %s/rel/linc/releases/1.0/' %
                          LINCSwitch.lincDir,
                          shell=True).strip('\n')
        info(output + '\n')

        info('*** Adding taps and bringing them up...\n')
        LINCSwitch.setupInts(LINCSwitch.getTaps())

        info('*** removing pipes if any \n')
        quietRun('rm /tmp/home/%s/linc-oe/rel/linc/*' % LINCSwitch.user,
                 shell=True)

        info('*** Starting linc OE...\n')
        output = quietRun('%s/rel/linc/bin/linc start' % LINCSwitch.lincDir,
                          shell=True)
        if output:
            error('***ERROR: LINC-OE: %s' % output + '\n')
            quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir,
                     shell=True)
            return False

        info('*** Waiting for linc-oe to start...\n')
        LINCSwitch.waitStarted(net)

        info(
            '*** Adding cross-connect (tap) interfaces to packet switches...\n'
        )
        for link in net.links:
            if isinstance(link, LINCLink):
                if link.annotations['optical.type'] == 'cross-connect':
                    for intf in [link.intf1, link.intf2]:
                        if not isinstance(intf, LINCIntf):
                            intfList = [intf.link.intf1, intf.link.intf2]
                            intfList.remove(intf)
                            intf2 = intfList[0]
                            intf.node.attach(
                                LINCSwitch.findTap(intf2.node,
                                                   intf2.node.ports[intf2]))

        info('*** Waiting for all devices to be available in ONOS...\n')
        url = 'http://%s:8181/onos/v1/devices' % LINCSwitch.controllers[0].ip
        time = 0
        while True:
            response = json.load(urllib2.urlopen(url))
            devs = response.get('devices')

            # Wait for all devices to be registered
            if (len(devices) != len(devs)):
                continue

            # Wait for all devices to available
            available = True
            for d in devs:
                available &= d['available']
            if available:
                break

            if (time >= TIMEOUT):
                error(
                    '***ERROR: ONOS did not register devices within %s seconds\n'
                    % TIMEOUT)
                break

            time += SLEEP_TIME
            sleep(SLEEP_TIME)

        info('*** Pushing Topology.json to ONOS\n')
        for index in range(len(LINCSwitch.controllers)):
            output = quietRun(
                '%s/tools/test/bin/onos-topo-cfg %s Topology.json &' %
                (LINCSwitch.onosDir, LINCSwitch.controllers[index].ip),
                shell=True)
            # successful output contains the two characters '{}'
            # if there is more output than this, there is an issue
            if output.strip('{}'):
                warn('***WARNING: Could not push topology file to ONOS: %s\n' %
                     output)
Exemple #52
0
def exampleCustomTags():
    """Simple example that exercises VLANStarTopo"""

    net = Mininet( topo=VLANStarTopo() )
    net.start()
    CLI( net )
    net.stop()

if __name__ == '__main__':
    import sys
    from functools import partial

    from mininet.net import Mininet
    from mininet.cli import CLI
    from mininet.topo import SingleSwitchTopo
    from mininet.log import setLogLevel

    setLogLevel( 'info' )

    if not quietRun( 'which vconfig' ):
        error( "Cannot find command 'vconfig'\nThe package",
               "'vlan' is required in Ubuntu or Debian,",
               "or 'vconfig' in Fedora\n" )
        exit()

    if len( sys.argv ) >= 2:
        exampleAllHosts( vlan=int( sys.argv[ 1 ] ) )
    else:
        exampleCustomTags()
Exemple #53
0
 def do_tcpall(self, line):
     if line != "":
         error("invalid number of arguments. tcpall doesn't take any ")
         return
     self.mn.tcptest()
Exemple #54
0
    def config(self,
               bw=None,
               delay=None,
               jitter=None,
               loss=None,
               gro=False,
               speedup=0,
               use_hfsc=False,
               use_tbf=False,
               latency_ms=None,
               enable_ecn=False,
               enable_red=False,
               max_queue_size=None,
               **params):
        """Configure the port and set its properties.
            bw: bandwidth in b/s (e.g. '10m')
            delay: transmit delay (e.g. '1ms' )
            jitter: jitter (e.g. '1ms')
            loss: loss (e.g. '1%' )
            gro: enable GRO (False)
            txo: enable transmit checksum offload (True)
            rxo: enable receive checksum offload (True)
            speedup: experimental switch-side bw option
            use_hfsc: use HFSC scheduling
            use_tbf: use TBF scheduling
            latency_ms: TBF latency parameter
            enable_ecn: enable ECN (False)
            enable_red: enable RED (False)
            max_queue_size: queue limit parameter for netem"""

        # Support old names for parameters
        gro = not params.pop('disable_gro', not gro)

        result = IntfWireless.config(self, **params)

        def on(isOn):
            "Helper method: bool -> 'on'/'off'"
            return 'on' if isOn else 'off'

        # Set offload parameters with ethool
        self.cmd('ethtool -K', self, 'gro', on(gro))

        # Optimization: return if nothing else to configure
        # Question: what happens if we want to reset things?
        if (bw is None and not delay and not loss and max_queue_size is None):
            return

        # Clear existing configuration
        tcoutput = self.tc('%s qdisc show dev %s')
        if "priomap" not in tcoutput and "noqueue" not in tcoutput:
            cmds = ['%s qdisc del dev %s root']
        else:
            cmds = []
        # Bandwidth limits via various methods
        bwcmds, parent = self.bwCmds(bw=bw,
                                     speedup=speedup,
                                     use_hfsc=use_hfsc,
                                     use_tbf=use_tbf,
                                     latency_ms=latency_ms,
                                     enable_ecn=enable_ecn,
                                     enable_red=enable_red)
        cmds += bwcmds

        # Delay/jitter/loss/max_queue_size using netem
        delaycmds, parent = self.delayCmds(delay=delay,
                                           jitter=jitter,
                                           loss=loss,
                                           max_queue_size=max_queue_size,
                                           parent=parent)
        cmds += delaycmds

        # Execute all the commands in our node
        debug("at map stage w/cmds: %s\n" % cmds)
        tcoutputs = [self.tc(cmd) for cmd in cmds]
        for output in tcoutputs:
            if output != '':
                error("*** Error: %s" % output)
        debug("cmds:", cmds, '\n')
        debug("outputs:", tcoutputs, '\n')
        result['tcoutputs'] = tcoutputs
        result['parent'] = parent

        return result
Exemple #55
0
    def config( self, bw=None, delay=None, jitter=None, loss=None,
                disable_gro=True, speedup=0, use_hfsc=False, use_tbf=False,
                latency_ms=None, enable_ecn=False, enable_red=False,
                max_queue_size=None, **params ):
        "Configure the port and set its properties."
        result = Intf.config( self, **params)

        # Disable GRO
        if disable_gro:
            self.cmd( 'ethtool -K %s gro off' % self )

        # Optimization: return if nothing else to configure
        # Question: what happens if we want to reset things?
        if ( bw is None and not delay and not loss
             and max_queue_size is None ):
            return

        # Clear existing configuration
        cmds = []
        tcoutput = self.tc( '%s qdisc show dev %s' )
        if "priomap" not in tcoutput:
            if self.node.type != 'station':
                cmds = [ '%s qdisc del dev %s root' ]
        else:
            cmds = []
        # Bandwidth limits via various methods
        bwcmds, parent = self.bwCmds( bw=bw, speedup=speedup,
                                      use_hfsc=use_hfsc, use_tbf=use_tbf,
                                      latency_ms=latency_ms,
                                      enable_ecn=enable_ecn,
                                      enable_red=enable_red )
        cmds += bwcmds

        # Delay/jitter/loss/max_queue_size using netem
        delaycmds, parent = self.delayCmds( delay=delay, jitter=jitter,
                                            loss=loss,
                                            max_queue_size=max_queue_size,
                                            parent=parent )
        cmds += delaycmds
        
        # Ugly but functional: display configuration info
        stuff = ( ( [ '%.2fMbit' % bw ] if bw is not None else [] ) +
                  ( [ '%s delay' % delay ] if delay is not None else [] ) +
                  ( [ '%s jitter' % jitter ] if jitter is not None else [] ) +
                  ( ['%d%% loss' % loss ] if loss is not None else [] ) +
                  ( [ 'ECN' ] if enable_ecn else [ 'RED' ]
                    if enable_red else [] ) )
        #Print bw info
        if self.node.type != 'station':
            info( '(' + ' '.join( stuff ) + ') ' )
        
        # Execute all the commands in our node
        debug("at map stage w/cmds: %s\n" % cmds)
        tcoutputs = [ self.tc(cmd) for cmd in cmds ]
        for output in tcoutputs:
            if output != '':
                error( "*** Error: %s" % output )
        debug( "cmds:", cmds, '\n' )
        debug( "outputs:", tcoutputs, '\n' )
        result[ 'tcoutputs'] = tcoutputs
        result[ 'parent' ] = parent
        
        return result
Exemple #56
0
        ARGS.ECMP = True
    if os.getuid() != 0:
        logging.error("You are NOT root")
        exit(1)
    if ARGS.nonblocking:
        test_non_block()
    elif ARGS.ECMP:
        test_fattree(controller=None)
    elif ARGS.hedera:
        test_hedera()
    elif ARGS.iroko:
        test_fattree(controller='Iroko')
    elif ARGS.dumbbell:
        test_dumbbell()
    else:
        error('Please specify either hedera, iroko, ecmp, or nonblocking!\n')
    clean()

# @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
# def port_stats_reply_handler(self, ev):
#     ports = []
#     for stat in ev.msg.body:
#         ports.append('port_no=%d '
#                      'rx_packets=%d tx_packets=%d '
#                      'rx_bytes=%d tx_bytes=%d '
#                      'rx_dropped=%d tx_dropped=%d '
#                      'rx_errors=%d tx_errors=%d '
#                      'rx_frame_err=%d rx_over_err=%d rx_crc_err=%d '
#                      'collisions=%d duration_sec=%d duration_nsec=%d' %
#                      (stat.port_no,
#                       stat.rx_packets, stat.tx_packets,
Exemple #57
0
    def twinning(self, aml_path):
        """Generates digital twins based on the specification provided via an AML artifact."""
        # Validate path
        if not os.path.isfile(aml_path):
            error("The AML file path '{}' is not valid!\n".format(aml_path))
            return

        if self.topo and self.build:
            error("Topology has already been built!\n")
            return

        # Invoke AML Parser
        parser = AmlParser(aml_path)
        aml_topo = {
            'switches': parser.switches,
            'plcs': parser.plcs,
            'hmis': parser.hmis,
            'aps': parser.aps,
            'mqttbrkrs': parser.mqttbrkrs,
            'rfidrs': parser.rfidrs,
            'iiotgws': parser.iiotgws
        }
        # Create topology
        self.topo = CpsTwinningTopo(aml_topo=aml_topo)
        # Start net
        self.start()

        for motor in parser.motors:
            self.physical_devices.append(
                Motor(motor['name'], motor['vars'],
                      self.get(motor['plc_name']), motor['plc_var_map']))
        # Add candy sensor
        self.physical_devices.append(
            CandySensor('CandySensor1', self.get('PLC1'),
                        {'EXTRACTORRUNNING': 1}, self.get('RFIDr1')))

        security_rules = {}

        for rule_type, rules in parser.security_rules.iteritems():
            if rule_type == RuleTypes().VARCONSTRAINT:
                constraints = []
                for rule in rules:
                    rule['plc'] = self.get(rule['plc_name'])
                    constraints.append(rule)
                security_rules[rule_type] = constraints
            elif rule_type == RuleTypes().VARLINKCONSTRAINT:
                constraints = []
                for rule in rules:
                    side = 'a'
                    for _ in range(2):
                        for key_ab in rule[side]:
                            ab = self.get(key_ab)
                            if isinstance(ab, Plc):
                                rule['plc'] = ab
                                rule['plc_var'] = rule[side][key_ab]
                            elif isinstance(ab, Hmi):
                                rule['hmi'] = ab
                                rule['hmi_var'] = rule[side][key_ab]
                            del rule[side]
                        side = 'b'
                    constraints.append(rule)
                security_rules[rule_type] = constraints

        self.security_manager = SecurityManager(security_rules)

        self.replication = Replication(self)
        self.viz = Viz(self, parser)
        self.state_logging = StateLogging(self)
Exemple #58
0
    def stop(self):
        """ Stop wireless Module """
        if glob.glob("*.apconf"):
            os.system('rm *.apconf')
        if glob.glob("*wifiDirect.conf"):
            os.system('rm *wifiDirect.conf')

        for hwsim_id in self.hwsim_ids:
            p = subprocess.Popen(["hwsim_mgmt", "-d", hwsim_id],
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 bufsize=-1)
            output, err_out = p.communicate()
            if p.returncode == 0:
                m = re.search("ID (\d+)", output)
                debug("\nDeleted mac80211_hwsim device with ID %s" %
                      m.group(1))
            else:
                error("\nError on deleting mac80211_hwsim device with ID %d" %
                      hwsim_id)
                error("\nOutput: %s" % output)
                error("\nError: %s" % err_out)

        if not self.externally_managed:
            try:
                subprocess.check_output("lsmod | grep mac80211_hwsim",
                                        shell=True)
                os.system('rmmod mac80211_hwsim')
            except:
                pass

        try:
            (subprocess.check_output("lsmod | grep ifb", shell=True))
            os.system('rmmod ifb')
        except:
            pass

        try:
            h = subprocess.check_output("ps -aux | grep -ic \'hostapd\'",
                                        shell=True)
            if h >= 2:
                os.system('pkill -f \'hostapd -B mn%d\'' % os.getpid())
        except:
            pass

        try:
            confnames = "mn%d_" % os.getpid()
            os.system('pkill -f \'wpa_supplicant -B -Dnl80211 -c%s\'' %
                      confnames)
        except:
            pass

        try:
            pidfiles = "mn%d_" % os.getpid()
            os.system('pkill -f \'wpa_supplicant -B -Dnl80211 -P %s\'' %
                      pidfiles)
        except:
            pass

        if not self.externally_managed:
            try:
                info("*** Killing wmediumd\n")
                os.system('pkill wmediumd')
            except:
                pass
Exemple #59
0
    def iperf(self, hosts=None, l4Type='TCP', udpBw='10M'):
        """Run iperf between two hosts.
           hosts: list of hosts; if None, uses opposite hosts
           l4Type: string, one of [ TCP, UDP ]
           returns: results two-element array of server and client speeds"""
        """
        Currently when the server side iperf service not reachable by the client, 
        the mininet console either hangs forever (not responsive to to any keys 
        Or continuously prints the message "waiting for iperf to startup"
        Actually there are two issues :
            1. when iperf session end point was created in mininet , if connectivity exists
            client will know in matter of secs . Per
            per current login client waits forever without yielding. default telnet wait 
            time of 60 secs is good enough. Therefore while loop is not necessary. If 
            statement is good enough.
            2. Since client to server connectivity can be verified within few secs, telnet with 60 sec 
            timeout is overkill. You get console full of msgs or console doesnt yield or 
            hangs till telnet timeout. We can accomplish the same verification . It is common 
            practice to use netcat(nc) to accomplish the same.
        Fix has been verified with iperf between hosts, between unreachable hosts, switches.
        """
        """ commented 
        if not quietRun( 'which telnet' ):
            error( 'Cannot find telnet in $PATH - required for iperf test' )
            return

        """

        if not quietRun('which nc'):
            error('Cannot find nc in $PATH - required for iperf test')
            return

        if not hosts:
            hosts = [self.hosts[0], self.hosts[-1]]
        else:
            assert len(hosts) == 2
        client, server = hosts
        output('*** Iperf: testing ' + l4Type + ' bandwidth between ')
        output("%s and %s\n" % (client.name, server.name))
        server.cmd('killall -9 iperf')
        iperfArgs = 'iperf '
        bwArgs = ''
        if l4Type == 'UDP':
            iperfArgs += '-u '
            bwArgs = '-b ' + udpBw + ' '
        elif l4Type != 'TCP':
            raise Exception('Unexpected l4 type: %s' % l4Type)
        server.sendCmd(iperfArgs + '-s', printPid=True)
        servout = ''
        while server.lastPid is None:
            servout += server.monitor()
        if l4Type == 'TCP':

            """
            While loop is replaced by if block

            while 'Connected' not in client.cmd(
                    'sh -c "echo A | telnet -e A %s 5001"' % server.IP()):
                output('waiting for iperf to start up...')
                sleep(.5)

            """
        if l4Type == 'TCP':
            sleep(0.5)
            ### Changed to handle a. hang issue when one of the hosts not reachable
            ### b. continuous waiting loop c. reduced waiting verification using Net cat vs telnet
            if ('succeeded'
                    not in client.cmd('nc -w 3 -v -z  %s 5001' % server.IP())):
                output('waiting for iperf to start up...\n')
                ## since session has failed, cleanup server end point and
                server.sendInt()
                servout += server.waitOutput()
                error(
                    "\niperf Error: Unable to reach the server %s on port 5001. iperf failed \n\n"
                    % server.IP())
                return

        cliout = client.cmd(iperfArgs + '-t 5 -c ' + server.IP() + ' ' +
                            bwArgs)
        debug('Client output: %s\n' % cliout)
        server.sendInt()
        servout += server.waitOutput()
        debug('Server output: %s\n' % servout)
        result = [self._parseIperf(servout), self._parseIperf(cliout)]
        if l4Type == 'UDP':
            result.insert(0, udpBw)
        output('*** Results: %s\n' % result)
        return result
Exemple #60
0
    def startShell(self):
        """Overrides the default shell start process to handle
           the addition of PID, UTS, and mount namespaces."""
        if self.shell:
            error("%s: shell is already running")
            return
        # mnexec: (c)lose descriptors, (d)etach from tty,
        # (p)rint pid, and run in (n)etwork namespace,
        # (m)ount namespace, p(i)d namespace, mount proc(f)s
        opts = '-cdp'
        if self.inNamespace:
            opts += 'n'
        if self.inMountNamespace:
            opts += 'm'
        if self.inPIDNamespace:
            opts += 'if'
        if self.inUTSNamespace:
            opts += 'u'
        # bash -m: enable job control
        # -s: pass $* to shell, and make process easy to find in ps
        cmd = [
            'mxexec', opts, 'env', 'PS1=' + chr(127), 'bash', '--norc',
            '--noediting', '-is', 'mininet:' + self.name
        ]

        # Spawn a shell subprocess in a pseudo-tty, to disable buffering
        # in the subprocess and insulate it from signals (e.g. SIGINT)
        # received by the parent
        self.master, self.slave = pty.openpty()
        self.shell = self._popen(cmd,
                                 stdin=self.slave,
                                 stdout=self.slave,
                                 stderr=self.slave,
                                 close_fds=False)
        # XXX BL: This doesn't seem right, and we should also probably
        # close our files when we exit...
        self.stdin = os.fdopen(self.master, 'r')
        self.stdout = self.stdin
        self.pid = self.shell.pid
        self.pollOut = select.poll()
        self.pollOut.register(self.stdout)
        # Maintain mapping between file descriptors and nodes
        # This is useful for monitoring multiple nodes
        # using select.poll()
        self.outToNode[self.stdout.fileno()] = self
        self.inToNode[self.stdin.fileno()] = self
        self.execed = False
        self.lastCmd = None
        self.lastPid = None
        self.readbuf = ''

        # If this node has a private PID space, grab the PID to attach to
        # Otherwise, we use the same PID as the shell's PID
        if self.inPIDNamespace:
            # monitor() will grab shell's true PID and put in self.lastPid
            self.monitor()
            if self.lastPid is None:
                raise Exception('Unable to determine shell\'s PID')
            self.pid = self.lastPid
            self.lastPid = None

        # Wait for prompt
        while True:
            data = self.read(1024)
            if data[-1] == chr(127):
                break
            self.pollOut.poll()
        self.waiting = False
        # +m: disable job control notification
        self.cmd('unset HISTFILE; stty -echo; set +m')