| Index: server/site_wifitest.py
|
| diff --git a/server/site_wifitest.py b/server/site_wifitest.py
|
| index a7852954691b696dcab1bfa99f46e74b485326f0..44b2e71170b1f700d67e82a840e21dba403a486c 100644
|
| --- a/server/site_wifitest.py
|
| +++ b/server/site_wifitest.py
|
| @@ -119,7 +119,8 @@ class WiFiTest(object):
|
| self.server = hosts.create_host(server['addr'])
|
| self.server_at = autotest.Autotest(self.server)
|
| # if not specified assume the same as the control address
|
| - self.server_wifi_ip = getattr(server, 'wifi_addr', self.server.ip)
|
| + self.server_wifi_ip = server.get('wifi_addr', self.server.ip)
|
| + self.__server_discover_commands(server)
|
| else:
|
| self.server = None;
|
| # NB: wifi address must be set if not reachable from control
|
| @@ -130,9 +131,9 @@ class WiFiTest(object):
|
|
|
| # potential bg thread for client network monitoring
|
| self.client_netdump_thread = None
|
| - self.client_cmd_netdump = client.get('cmd_netdump', 'tshark')
|
| - self.client_cmd_ifconfig = client.get('cmd_ifconfig', 'ifconfig')
|
| - self.client_cmd_iw = client.get('cmd_iw', 'iw')
|
| + self.__client_discover_commands(client)
|
| + self.netperf_iter = 0
|
| + self.firewall_rules = []
|
|
|
|
|
| def cleanup(self, params):
|
| @@ -140,6 +141,30 @@ class WiFiTest(object):
|
| self.disconnect({})
|
| self.wifi.destroy({})
|
| self.client_netdump_stop({})
|
| + self.firewall_cleanup({})
|
| +
|
| +
|
| + def __client_discover_commands(self, client):
|
| + self.client_cmd_netdump = client.get('cmd_netdump', 'tshark')
|
| + self.client_cmd_ifconfig = client.get('cmd_ifconfig', 'ifconfig')
|
| + self.client_cmd_iw = client.get('cmd_iw', 'iw')
|
| + self.client_cmd_netperf = client.get('cmd_netperf_client',
|
| + '/usr/local/bin/netperf')
|
| + self.client_cmd_netserv = client.get('cmd_netperf_server',
|
| + '/usr/local/sbin/netserver')
|
| + self.client_cmd_iptables = '/sbin/iptables'
|
| +
|
| +
|
| + def __server_discover_commands(self, server):
|
| + self.server_cmd_netperf = server.get('cmd_netperf_client',
|
| + '/usr/bin/netperf')
|
| + self.server_cmd_netserv = server.get('cmd_netperf_server',
|
| + '/usr/bin/netserver')
|
| + # /usr/bin/ping is preferred, as it is likely to be iputils
|
| + if self.__is_installed(self.server, '/usr/bin/ping'):
|
| + self.server_ping_cmd = '/usr/bin/ping'
|
| + else:
|
| + self.server_ping_cmd = 'ping'
|
|
|
|
|
| def __get_defssid(self, ipaddr):
|
| @@ -384,7 +409,8 @@ class WiFiTest(object):
|
| stats['xmit'] = m.group(1)
|
| stats['recv'] = m.group(2)
|
| stats['loss'] = m.group(4)
|
| - m = re.search('(round-trip|rtt) min[^=]*= ([0-9.]*)/([0-9.]*)/([0-9.]*)', str)
|
| + m = re.search('(round-trip|rtt) min[^=]*= '
|
| + '([0-9.]*)/([0-9.]*)/([0-9.]*)', str)
|
| if m is not None:
|
| stats['min'] = m.group(2)
|
| stats['avg'] = m.group(3)
|
| @@ -398,6 +424,17 @@ class WiFiTest(object):
|
| stats['min'], stats['avg'], stats['max'])
|
|
|
|
|
| + def __ping_prefix(self, params):
|
| + if 'name' in params:
|
| + return params['name']
|
| +
|
| + args = []
|
| + for k, v in params.items():
|
| + if k != 'count':
|
| + args.append('%s_%s' % (k, v))
|
| + return '/'.join(args)
|
| +
|
| +
|
| def client_ping(self, params):
|
| """ Ping the server from the client """
|
| ping_ip = params.get('ping_ip', self.server_wifi_ip)
|
| @@ -407,8 +444,9 @@ class WiFiTest(object):
|
| (self.__ping_args(params), ping_ip), timeout=3*int(count))
|
|
|
| stats = self.__get_pingstats(result.stdout)
|
| + prefix = 'client_ping_%s_' % self.__ping_prefix(params)
|
| for k,v in stats.iteritems():
|
| - self.keyvals['client_ping_' + k] = v
|
| + self.keyvals[prefix + k] = v
|
| self.__print_pingstats("client_ping ", stats)
|
|
|
|
|
| @@ -435,10 +473,12 @@ class WiFiTest(object):
|
| ping_ip = params.get('ping_ip', self.client_wifi_ip)
|
| count = params.get('count', self.defpingcount)
|
| # set timeout for 3s / ping packet
|
| - result = self.server.run("ping %s %s" % \
|
| - (self.__ping_args(params), ping_ip), timeout=3*int(count))
|
| + result = self.server.run("%s %s %s" % \
|
| + (self.server_ping_cmd, self.__ping_args(params),
|
| + ping_ip), timeout=3*int(count))
|
|
|
| stats = self.__get_pingstats(result.stdout)
|
| + prefix = 'server_ping_' + self.__ping_prefix(params)
|
| for k,v in stats.iteritems():
|
| self.keyvals['server_ping_' + k] = v
|
| self.__print_pingstats("server_ping ", stats)
|
| @@ -520,59 +560,144 @@ class WiFiTest(object):
|
| self.__run_iperf(self.server_wifi_ip, self.client_wifi_ip, params)
|
|
|
|
|
| - def __run_netperf(self, client_ip, server_ip, params):
|
| - template = "job.run_test('"
|
| - if self.server is None:
|
| - template += "network_netperf2"
|
| - else:
|
| - template += "netperf2"
|
| - template += "', server_ip='%s', client_ip='%s', role='%s'"
|
| - if 'test' in params:
|
| - template += ", test='%s'" % params['test']
|
| - if 'bidir' in params:
|
| - template += ", bidi=True"
|
| - if 'time' in params:
|
| - template += ", test_time=%s" % params['time']
|
| - template += ", wait_time=%s" % params.get('wait_time', self.defwaittime)
|
| + def __is_installed(self, host, filename):
|
| + result = host.run("ls %s" % filename, ignore_status=True)
|
| + m = re.search(filename, result.stdout)
|
| + return m is not None
|
|
|
| - # add a tag to distinguish runs when multiple tests are run
|
| - if 'tag' in params:
|
| - template += ", tag='%s'" % params['tag']
|
| - elif 'test' in params:
|
| - template += ", tag='%s'" % params['test']
|
|
|
| - template += ")"
|
| + def __firewall_open(self, proto, src):
|
| + rule = 'INPUT -s %s/32 -p %s -m %s -j ACCEPT' % (src, proto, proto)
|
| + result = self.client.run('%s -S INPUT' % self.client_cmd_iptables)
|
| + if '-A %s ' % rule in result.stdout.splitlines():
|
| + return None
|
| + self.client.run('%s -A %s' % (self.client_cmd_iptables, rule))
|
| + self.firewall_rules.append(rule)
|
| + return rule
|
|
|
| - client_control_file = template % (server_ip, client_ip, 'client')
|
| - client_command = subcommand.subcommand(self.client_at.run,
|
| - [client_control_file, self.client.hostname])
|
| - cmds = [client_command]
|
|
|
| - if self.server is None:
|
| - logging.info("%s: netperf %s => (%s)",
|
| - self.name, client_ip, server_ip)
|
| - else:
|
| - server_control_file = template % (server_ip, client_ip, 'server')
|
| - server_command = subcommand.subcommand(self.server_at.run,
|
| - [server_control_file, self.server.hostname])
|
| - cmds.append(server_command)
|
| + def __firewall_close(self, rule):
|
| + if rule in self.firewall_rules:
|
| + self.client.run('%s -D %s' % (self.client_cmd_iptables, rule))
|
| + self.firewall_rules.remove(rule)
|
|
|
| - logging.info("%s: netperf %s => %s",
|
| - self.name, client_ip, server_ip)
|
| + def firewall_cleanup(self, params):
|
| + for rule in self.firewall_rules:
|
| + self.__firewall_close(rule)
|
|
|
| - subcommand.parallel(cmds)
|
| + def __run_netperf(self, mode, params):
|
| + np_rules = []
|
| + if mode == 'server':
|
| + server = { 'host': self.client, 'cmd': self.client_cmd_netserv }
|
| + client = { 'host': self.server, 'cmd': self.server_cmd_netperf,
|
| + 'target': self.client_wifi_ip }
|
| +
|
| + # Open up access from the server into our DUT
|
| + np_rules.append(self.__firewall_open('tcp', self.server_wifi_ip))
|
| + np_rules.append(self.__firewall_open('udp', self.server_wifi_ip))
|
| + else:
|
| + server = { 'host': self.server, 'cmd': self.server_cmd_netserv }
|
| + client = { 'host': self.client, 'cmd': self.client_cmd_netperf,
|
| + 'target': self.server_wifi_ip }
|
| +
|
| + # If appropriate apps are not installed, raise an error
|
| + if not self.__is_installed(client['host'], client['cmd']) or \
|
| + not self.__is_installed(server['host'], server['cmd']):
|
| + raise error.TestFail('Unable to find netperf on client or server')
|
| +
|
| + # There are legitimate ways this command can fail, eg. already running
|
| + server['host'].run(server['cmd'], ignore_status=True)
|
| +
|
| + # Assemble arguments for client command
|
| + test = params.get('test', 'TCP_STREAM')
|
| + netperf_args = '-H %s -t %s -l %d' % (client['target'], test,
|
| + params.get('test_time', 15))
|
| +
|
| + # Run netperf command and receive command results
|
| + t0 = time.time()
|
| + results = client['host'].run("%s %s" % (client['cmd'], netperf_args))
|
| + actual_time = time.time() - t0
|
| + logging.info('actual_time: %f', actual_time)
|
| +
|
| + # Close up whatever firewall rules we created for netperf
|
| + for rule in np_rules:
|
| + self.__firewall_close(rule)
|
| +
|
| + # Results are prefixed with the iteration or a caller-defined name
|
| + prefix = 'Netperf_%s_' % params.get('name', str(self.netperf_iter))
|
| + self.netperf_iter += 1
|
| +
|
| + self.keyvals[prefix + 'test'] = test
|
| + self.keyvals[prefix + 'mode'] = mode
|
| + self.keyvals[prefix + 'actual_time'] = actual_time
|
| +
|
| + logging.info(results)
|
| +
|
| + lines = results.stdout.splitlines()
|
| +
|
| + # Each test type has a different form of output
|
| + if test in ['TCP_STREAM', 'TCP_MAERTS', 'TCP_SENDFILE']:
|
| + """Parses the following (works for both TCP_STREAM, TCP_MAERTS and
|
| + TCP_SENDFILE) and returns a singleton containing throughput.
|
| +
|
| + TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to \
|
| + foo.bar.com (10.10.10.3) port 0 AF_INET
|
| + Recv Send Send
|
| + Socket Socket Message Elapsed
|
| + Size Size Size Time Throughput
|
| + bytes bytes bytes secs. 10^6bits/sec
|
| +
|
| + 87380 16384 16384 2.00 941.28
|
| + """
|
| + self.keyvals[prefix + 'Throughput'] = float(lines[6].split()[4])
|
| + elif test == 'UDP_STREAM':
|
| + """Parses the following and returns a touple containing throughput
|
| + and the number of errors.
|
| +
|
| + UDP UNIDIRECTIONAL SEND TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET \
|
| + to foo.bar.com (10.10.10.3) port 0 AF_INET
|
| + Socket Message Elapsed Messages
|
| + Size Size Time Okay Errors Throughput
|
| + bytes bytes secs # # 10^6bits/sec
|
| +
|
| + 129024 65507 2.00 3673 0 961.87
|
| + 131072 2.00 3673 961.87
|
| + """
|
| + udp_tokens = lines[5].split()
|
| + self.keyvals[prefix + 'Throughput'] = float(udp_tokens[5])
|
| + self.keyvals[prefix + 'Errors'] = float(udp_tokens[4])
|
| + elif test in ['TCP_RR', 'TCP_CRR', 'UDP_RR']:
|
| + """Parses the following which works for both rr (TCP and UDP)
|
| + and crr tests and returns a singleton containing transfer rate.
|
| +
|
| + TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET \
|
| + to foo.bar.com (10.10.10.3) port 0 AF_INET
|
| + Local /Remote
|
| + Socket Size Request Resp. Elapsed Trans.
|
| + Send Recv Size Size Time Rate
|
| + bytes Bytes bytes bytes secs. per sec
|
| +
|
| + 16384 87380 1 1 2.00 14118.53
|
| + 16384 87380
|
| + """
|
| + self.kevals[prefix + 'Trasnfer_Rate'] = float(lines[6].split()[5])
|
| + else:
|
| + raise error.TestError('Unhandled test')
|
| +
|
| + return True
|
|
|
|
|
| def client_netperf(self, params):
|
| """ Run netperf on the client against the server """
|
| - self.__run_netperf(self.client_wifi_ip, self.server_wifi_ip, params)
|
| + self.__run_netperf('client', params)
|
| +
|
|
|
| def server_netperf(self, params):
|
| """ Run netperf on the server against the client """
|
| if self.server is None:
|
| self.__unreachable("server_netperf")
|
| return
|
| - self.__run_netperf(self.server_wifi_ip, self.client_wifi_ip, params)
|
| + self.__run_netperf('server', params)
|
|
|
|
|
| def __create_netdump_dev(self, devname='mon0'):
|
| @@ -632,6 +757,7 @@ def __byfile(a, b):
|
| else:
|
| return 0
|
|
|
| +
|
| def read_tests(dir, *args):
|
| """
|
| Collect WiFi test tuples from files. File names are used to
|
|
|