Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(850)

Side by Side Diff: server/site_wifitest.py

Issue 3275009: Add standalone netperf code directly within site_wifitest (Closed) Base URL: ssh://gitrw.chromium.org/autotest.git
Patch Set: Uncomment server intries in cros-* config files (note wrt client ip addr ymmv) Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « client/config/wifi_testbed_config.cros-5 ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import common, fnmatch, logging, os, re, string, threading, time 5 import common, fnmatch, logging, os, re, string, threading, time
6 6
7 from autotest_lib.server import autotest, hosts, subcommand 7 from autotest_lib.server import autotest, hosts, subcommand
8 from autotest_lib.server import site_bsd_router 8 from autotest_lib.server import site_bsd_router
9 from autotest_lib.server import site_linux_router 9 from autotest_lib.server import site_linux_router
10 from autotest_lib.server import site_host_attributes 10 from autotest_lib.server import site_host_attributes
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 # The server machine may be multi-homed or only on the wifi 112 # The server machine may be multi-homed or only on the wifi
113 # network. When only on the wifi net we suppress server_* 113 # network. When only on the wifi net we suppress server_*
114 # requests since we cannot initiate them from the control machine. 114 # requests since we cannot initiate them from the control machine.
115 # 115 #
116 server = config['server'] 116 server = config['server']
117 # NB: server may not be reachable on the control network 117 # NB: server may not be reachable on the control network
118 if 'addr' in server: 118 if 'addr' in server:
119 self.server = hosts.create_host(server['addr']) 119 self.server = hosts.create_host(server['addr'])
120 self.server_at = autotest.Autotest(self.server) 120 self.server_at = autotest.Autotest(self.server)
121 # if not specified assume the same as the control address 121 # if not specified assume the same as the control address
122 self.server_wifi_ip = getattr(server, 'wifi_addr', self.server.ip) 122 self.server_wifi_ip = server.get('wifi_addr', self.server.ip)
123 self.__server_discover_commands(server)
123 else: 124 else:
124 self.server = None; 125 self.server = None;
125 # NB: wifi address must be set if not reachable from control 126 # NB: wifi address must be set if not reachable from control
126 self.server_wifi_ip = server['wifi_addr'] 127 self.server_wifi_ip = server['wifi_addr']
127 128
128 # potential bg thread for ping untilstop 129 # potential bg thread for ping untilstop
129 self.ping_thread = None 130 self.ping_thread = None
130 131
131 # potential bg thread for client network monitoring 132 # potential bg thread for client network monitoring
132 self.client_netdump_thread = None 133 self.client_netdump_thread = None
133 self.client_cmd_netdump = client.get('cmd_netdump', 'tshark') 134 self.__client_discover_commands(client)
134 self.client_cmd_ifconfig = client.get('cmd_ifconfig', 'ifconfig') 135 self.netperf_iter = 0
135 self.client_cmd_iw = client.get('cmd_iw', 'iw') 136 self.firewall_rules = []
136 137
137 138
138 def cleanup(self, params): 139 def cleanup(self, params):
139 """ Cleanup state: disconnect client and destroy ap """ 140 """ Cleanup state: disconnect client and destroy ap """
140 self.disconnect({}) 141 self.disconnect({})
141 self.wifi.destroy({}) 142 self.wifi.destroy({})
142 self.client_netdump_stop({}) 143 self.client_netdump_stop({})
144 self.firewall_cleanup({})
145
146
147 def __client_discover_commands(self, client):
148 self.client_cmd_netdump = client.get('cmd_netdump', 'tshark')
149 self.client_cmd_ifconfig = client.get('cmd_ifconfig', 'ifconfig')
150 self.client_cmd_iw = client.get('cmd_iw', 'iw')
151 self.client_cmd_netperf = client.get('cmd_netperf_client',
152 '/usr/local/bin/netperf')
153 self.client_cmd_netserv = client.get('cmd_netperf_server',
154 '/usr/local/sbin/netserver')
155 self.client_cmd_iptables = '/sbin/iptables'
156
157
158 def __server_discover_commands(self, server):
159 self.server_cmd_netperf = server.get('cmd_netperf_client',
160 '/usr/bin/netperf')
161 self.server_cmd_netserv = server.get('cmd_netperf_server',
162 '/usr/bin/netserver')
163 # /usr/bin/ping is preferred, as it is likely to be iputils
164 if self.__is_installed(self.server, '/usr/bin/ping'):
165 self.server_ping_cmd = '/usr/bin/ping'
166 else:
167 self.server_ping_cmd = 'ping'
143 168
144 169
145 def __get_defssid(self, ipaddr): 170 def __get_defssid(self, ipaddr):
146 # 171 #
147 # Calculate ssid based on test name; this lets us track progress 172 # Calculate ssid based on test name; this lets us track progress
148 # by watching beacon frames. 173 # by watching beacon frames.
149 # 174 #
150 return re.sub('[^a-zA-Z0-9_]', '_', "%s_%s" % (self.name, ipaddr)) 175 return re.sub('[^a-zA-Z0-9_]', '_', "%s_%s" % (self.name, ipaddr))
151 176
152 177
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 def __get_pingstats(self, str): 402 def __get_pingstats(self, str):
378 stats = {} 403 stats = {}
379 for k in ('xmit', 'recv', 'loss', 'min', 'avg', 'max'): 404 for k in ('xmit', 'recv', 'loss', 'min', 'avg', 'max'):
380 stats[k] = '???' 405 stats[k] = '???'
381 m = re.search('([0-9]*) packets transmitted,[ ]*([0-9]*)[ ]' 406 m = re.search('([0-9]*) packets transmitted,[ ]*([0-9]*)[ ]'
382 '(packets |)received, ([0-9]*)', str) 407 '(packets |)received, ([0-9]*)', str)
383 if m is not None: 408 if m is not None:
384 stats['xmit'] = m.group(1) 409 stats['xmit'] = m.group(1)
385 stats['recv'] = m.group(2) 410 stats['recv'] = m.group(2)
386 stats['loss'] = m.group(4) 411 stats['loss'] = m.group(4)
387 m = re.search('(round-trip|rtt) min[^=]*= ([0-9.]*)/([0-9.]*)/([0-9.]*)' , str) 412 m = re.search('(round-trip|rtt) min[^=]*= '
413 '([0-9.]*)/([0-9.]*)/([0-9.]*)', str)
388 if m is not None: 414 if m is not None:
389 stats['min'] = m.group(2) 415 stats['min'] = m.group(2)
390 stats['avg'] = m.group(3) 416 stats['avg'] = m.group(3)
391 stats['max'] = m.group(4) 417 stats['max'] = m.group(4)
392 return stats 418 return stats
393 419
394 420
395 def __print_pingstats(self, label, stats): 421 def __print_pingstats(self, label, stats):
396 logging.info("%s: %s%s/%s, %s%% loss, rtt %s/%s/%s", 422 logging.info("%s: %s%s/%s, %s%% loss, rtt %s/%s/%s",
397 self.name, label, stats['xmit'], stats['recv'], stats['loss'], 423 self.name, label, stats['xmit'], stats['recv'], stats['loss'],
398 stats['min'], stats['avg'], stats['max']) 424 stats['min'], stats['avg'], stats['max'])
399 425
400 426
427 def __ping_prefix(self, params):
428 if 'name' in params:
429 return params['name']
430
431 args = []
432 for k, v in params.items():
433 if k != 'count':
434 args.append('%s_%s' % (k, v))
435 return '/'.join(args)
436
437
401 def client_ping(self, params): 438 def client_ping(self, params):
402 """ Ping the server from the client """ 439 """ Ping the server from the client """
403 ping_ip = params.get('ping_ip', self.server_wifi_ip) 440 ping_ip = params.get('ping_ip', self.server_wifi_ip)
404 count = params.get('count', self.defpingcount) 441 count = params.get('count', self.defpingcount)
405 # set timeout for 3s / ping packet 442 # set timeout for 3s / ping packet
406 result = self.client.run("ping %s %s" % \ 443 result = self.client.run("ping %s %s" % \
407 (self.__ping_args(params), ping_ip), timeout=3*int(count)) 444 (self.__ping_args(params), ping_ip), timeout=3*int(count))
408 445
409 stats = self.__get_pingstats(result.stdout) 446 stats = self.__get_pingstats(result.stdout)
447 prefix = 'client_ping_%s_' % self.__ping_prefix(params)
410 for k,v in stats.iteritems(): 448 for k,v in stats.iteritems():
411 self.keyvals['client_ping_' + k] = v 449 self.keyvals[prefix + k] = v
412 self.__print_pingstats("client_ping ", stats) 450 self.__print_pingstats("client_ping ", stats)
413 451
414 452
415 def client_ping_bg(self, params): 453 def client_ping_bg(self, params):
416 """ Ping the server from the client """ 454 """ Ping the server from the client """
417 ping_ip = params.get('ping_ip', self.server_wifi_ip) 455 ping_ip = params.get('ping_ip', self.server_wifi_ip)
418 cmd = "ping %s %s" % (self.__ping_args(params), ping_ip) 456 cmd = "ping %s %s" % (self.__ping_args(params), ping_ip)
419 self.ping_thread = HelperThread(self.client, cmd) 457 self.ping_thread = HelperThread(self.client, cmd)
420 self.ping_thread.start() 458 self.ping_thread.start()
421 459
422 460
423 def client_ping_bg_stop(self, params): 461 def client_ping_bg_stop(self, params):
424 if self.ping_thread is not None: 462 if self.ping_thread is not None:
425 self.client.run("pkill ping") 463 self.client.run("pkill ping")
426 self.ping_thread.join() 464 self.ping_thread.join()
427 self.ping_thread = None 465 self.ping_thread = None
428 466
429 467
430 def server_ping(self, params): 468 def server_ping(self, params):
431 """ Ping the client from the server """ 469 """ Ping the client from the server """
432 if self.server is None: 470 if self.server is None:
433 self.__unreachable("server_ping") 471 self.__unreachable("server_ping")
434 return 472 return
435 ping_ip = params.get('ping_ip', self.client_wifi_ip) 473 ping_ip = params.get('ping_ip', self.client_wifi_ip)
436 count = params.get('count', self.defpingcount) 474 count = params.get('count', self.defpingcount)
437 # set timeout for 3s / ping packet 475 # set timeout for 3s / ping packet
438 result = self.server.run("ping %s %s" % \ 476 result = self.server.run("%s %s %s" % \
439 (self.__ping_args(params), ping_ip), timeout=3*int(count)) 477 (self.server_ping_cmd, self.__ping_args(params),
478 ping_ip), timeout=3*int(count))
440 479
441 stats = self.__get_pingstats(result.stdout) 480 stats = self.__get_pingstats(result.stdout)
481 prefix = 'server_ping_' + self.__ping_prefix(params)
442 for k,v in stats.iteritems(): 482 for k,v in stats.iteritems():
443 self.keyvals['server_ping_' + k] = v 483 self.keyvals['server_ping_' + k] = v
444 self.__print_pingstats("server_ping ", stats) 484 self.__print_pingstats("server_ping ", stats)
445 485
446 486
447 def server_ping_bg(self, params): 487 def server_ping_bg(self, params):
448 """ Ping the client from the server """ 488 """ Ping the client from the server """
449 if self.server is None: 489 if self.server is None:
450 self.__unreachable("server_ping_bg") 490 self.__unreachable("server_ping_bg")
451 return 491 return
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 553
514 554
515 def server_iperf(self, params): 555 def server_iperf(self, params):
516 """ Run iperf on the server against the client """ 556 """ Run iperf on the server against the client """
517 if self.server is None: 557 if self.server is None:
518 self.__unreachable("server_iperf") 558 self.__unreachable("server_iperf")
519 return 559 return
520 self.__run_iperf(self.server_wifi_ip, self.client_wifi_ip, params) 560 self.__run_iperf(self.server_wifi_ip, self.client_wifi_ip, params)
521 561
522 562
523 def __run_netperf(self, client_ip, server_ip, params): 563 def __is_installed(self, host, filename):
524 template = "job.run_test('" 564 result = host.run("ls %s" % filename, ignore_status=True)
525 if self.server is None: 565 m = re.search(filename, result.stdout)
526 template += "network_netperf2" 566 return m is not None
567
568
569 def __firewall_open(self, proto, src):
570 rule = 'INPUT -s %s/32 -p %s -m %s -j ACCEPT' % (src, proto, proto)
571 result = self.client.run('%s -S INPUT' % self.client_cmd_iptables)
572 if '-A %s ' % rule in result.stdout.splitlines():
573 return None
574 self.client.run('%s -A %s' % (self.client_cmd_iptables, rule))
575 self.firewall_rules.append(rule)
576 return rule
577
578
579 def __firewall_close(self, rule):
580 if rule in self.firewall_rules:
581 self.client.run('%s -D %s' % (self.client_cmd_iptables, rule))
582 self.firewall_rules.remove(rule)
583
584 def firewall_cleanup(self, params):
585 for rule in self.firewall_rules:
586 self.__firewall_close(rule)
587
588 def __run_netperf(self, mode, params):
589 np_rules = []
590 if mode == 'server':
591 server = { 'host': self.client, 'cmd': self.client_cmd_netserv }
592 client = { 'host': self.server, 'cmd': self.server_cmd_netperf,
593 'target': self.client_wifi_ip }
594
595 # Open up access from the server into our DUT
596 np_rules.append(self.__firewall_open('tcp', self.server_wifi_ip))
597 np_rules.append(self.__firewall_open('udp', self.server_wifi_ip))
527 else: 598 else:
528 template += "netperf2" 599 server = { 'host': self.server, 'cmd': self.server_cmd_netserv }
529 template += "', server_ip='%s', client_ip='%s', role='%s'" 600 client = { 'host': self.client, 'cmd': self.client_cmd_netperf,
530 if 'test' in params: 601 'target': self.server_wifi_ip }
531 template += ", test='%s'" % params['test']
532 if 'bidir' in params:
533 template += ", bidi=True"
534 if 'time' in params:
535 template += ", test_time=%s" % params['time']
536 template += ", wait_time=%s" % params.get('wait_time', self.defwaittime)
537 602
538 # add a tag to distinguish runs when multiple tests are run 603 # If appropriate apps are not installed, raise an error
539 if 'tag' in params: 604 if not self.__is_installed(client['host'], client['cmd']) or \
540 template += ", tag='%s'" % params['tag'] 605 not self.__is_installed(server['host'], server['cmd']):
541 elif 'test' in params: 606 raise error.TestFail('Unable to find netperf on client or server')
542 template += ", tag='%s'" % params['test']
543 607
544 template += ")" 608 # There are legitimate ways this command can fail, eg. already running
609 server['host'].run(server['cmd'], ignore_status=True)
545 610
546 client_control_file = template % (server_ip, client_ip, 'client') 611 # Assemble arguments for client command
547 client_command = subcommand.subcommand(self.client_at.run, 612 test = params.get('test', 'TCP_STREAM')
548 [client_control_file, self.client.hostname]) 613 netperf_args = '-H %s -t %s -l %d' % (client['target'], test,
549 cmds = [client_command] 614 params.get('test_time', 15))
550 615
551 if self.server is None: 616 # Run netperf command and receive command results
552 logging.info("%s: netperf %s => (%s)", 617 t0 = time.time()
553 self.name, client_ip, server_ip) 618 results = client['host'].run("%s %s" % (client['cmd'], netperf_args))
619 actual_time = time.time() - t0
620 logging.info('actual_time: %f', actual_time)
621
622 # Close up whatever firewall rules we created for netperf
623 for rule in np_rules:
624 self.__firewall_close(rule)
625
626 # Results are prefixed with the iteration or a caller-defined name
627 prefix = 'Netperf_%s_' % params.get('name', str(self.netperf_iter))
628 self.netperf_iter += 1
629
630 self.keyvals[prefix + 'test'] = test
631 self.keyvals[prefix + 'mode'] = mode
632 self.keyvals[prefix + 'actual_time'] = actual_time
633
634 logging.info(results)
635
636 lines = results.stdout.splitlines()
637
638 # Each test type has a different form of output
639 if test in ['TCP_STREAM', 'TCP_MAERTS', 'TCP_SENDFILE']:
640 """Parses the following (works for both TCP_STREAM, TCP_MAERTS and
641 TCP_SENDFILE) and returns a singleton containing throughput.
642
643 TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to \
644 foo.bar.com (10.10.10.3) port 0 AF_INET
645 Recv Send Send
646 Socket Socket Message Elapsed
647 Size Size Size Time Throughput
648 bytes bytes bytes secs. 10^6bits/sec
649
650 87380 16384 16384 2.00 941.28
651 """
652 self.keyvals[prefix + 'Throughput'] = float(lines[6].split()[4])
653 elif test == 'UDP_STREAM':
654 """Parses the following and returns a touple containing throughput
655 and the number of errors.
656
657 UDP UNIDIRECTIONAL SEND TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET \
658 to foo.bar.com (10.10.10.3) port 0 AF_INET
659 Socket Message Elapsed Messages
660 Size Size Time Okay Errors Throughput
661 bytes bytes secs # # 10^6bits/sec
662
663 129024 65507 2.00 3673 0 961.87
664 131072 2.00 3673 961.87
665 """
666 udp_tokens = lines[5].split()
667 self.keyvals[prefix + 'Throughput'] = float(udp_tokens[5])
668 self.keyvals[prefix + 'Errors'] = float(udp_tokens[4])
669 elif test in ['TCP_RR', 'TCP_CRR', 'UDP_RR']:
670 """Parses the following which works for both rr (TCP and UDP)
671 and crr tests and returns a singleton containing transfer rate.
672
673 TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET \
674 to foo.bar.com (10.10.10.3) port 0 AF_INET
675 Local /Remote
676 Socket Size Request Resp. Elapsed Trans.
677 Send Recv Size Size Time Rate
678 bytes Bytes bytes bytes secs. per sec
679
680 16384 87380 1 1 2.00 14118.53
681 16384 87380
682 """
683 self.kevals[prefix + 'Trasnfer_Rate'] = float(lines[6].split()[5])
554 else: 684 else:
555 server_control_file = template % (server_ip, client_ip, 'server') 685 raise error.TestError('Unhandled test')
556 server_command = subcommand.subcommand(self.server_at.run,
557 [server_control_file, self.server.hostname])
558 cmds.append(server_command)
559 686
560 logging.info("%s: netperf %s => %s", 687 return True
561 self.name, client_ip, server_ip)
562
563 subcommand.parallel(cmds)
564 688
565 689
566 def client_netperf(self, params): 690 def client_netperf(self, params):
567 """ Run netperf on the client against the server """ 691 """ Run netperf on the client against the server """
568 self.__run_netperf(self.client_wifi_ip, self.server_wifi_ip, params) 692 self.__run_netperf('client', params)
693
569 694
570 def server_netperf(self, params): 695 def server_netperf(self, params):
571 """ Run netperf on the server against the client """ 696 """ Run netperf on the server against the client """
572 if self.server is None: 697 if self.server is None:
573 self.__unreachable("server_netperf") 698 self.__unreachable("server_netperf")
574 return 699 return
575 self.__run_netperf(self.server_wifi_ip, self.client_wifi_ip, params) 700 self.__run_netperf('server', params)
576 701
577 702
578 def __create_netdump_dev(self, devname='mon0'): 703 def __create_netdump_dev(self, devname='mon0'):
579 self.client.run("%s dev %s del || /bin/true" % (self.client_cmd_iw, 704 self.client.run("%s dev %s del || /bin/true" % (self.client_cmd_iw,
580 devname)) 705 devname))
581 self.client.run("%s dev %s interface add %s type monitor" % 706 self.client.run("%s dev %s interface add %s type monitor" %
582 (self.client_cmd_iw, self.client_wlanif, devname)) 707 (self.client_cmd_iw, self.client_wlanif, devname))
583 self.client.run("%s %s up" % (self.client_cmd_ifconfig, devname)) 708 self.client.run("%s %s up" % (self.client_cmd_ifconfig, devname))
584 return devname 709 return devname
585 710
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 750
626 751
627 def __byfile(a, b): 752 def __byfile(a, b):
628 if a['file'] < b['file']: 753 if a['file'] < b['file']:
629 return -1 754 return -1
630 elif a['file'] > b['file']: 755 elif a['file'] > b['file']:
631 return 1 756 return 1
632 else: 757 else:
633 return 0 758 return 0
634 759
760
635 def read_tests(dir, *args): 761 def read_tests(dir, *args):
636 """ 762 """
637 Collect WiFi test tuples from files. File names are used to 763 Collect WiFi test tuples from files. File names are used to
638 sort the test objects so the convention is to name them NNN<test> 764 sort the test objects so the convention is to name them NNN<test>
639 where NNN is a decimal number used to sort and <test> is an 765 where NNN is a decimal number used to sort and <test> is an
640 identifying name for the test; e.g. 000Check11b 766 identifying name for the test; e.g. 000Check11b
641 """ 767 """
642 tests = [] 768 tests = []
643 for file in os.listdir(dir): 769 for file in os.listdir(dir):
644 if any(fnmatch.fnmatch(file, pat) for pat in args): 770 if any(fnmatch.fnmatch(file, pat) for pat in args):
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 if server_addr is None and hasattr(client_attributes, 'server_addr'): 805 if server_addr is None and hasattr(client_attributes, 'server_addr'):
680 server_addr = client_attributes.server_addr 806 server_addr = client_attributes.server_addr
681 if server_addr is not None: 807 if server_addr is not None:
682 server['addr'] = server_addr; 808 server['addr'] = server_addr;
683 # TODO(sleffler) check for wifi_addr when no control address 809 # TODO(sleffler) check for wifi_addr when no control address
684 810
685 # tag jobs w/ the router's address on the control network 811 # tag jobs w/ the router's address on the control network
686 config['tagname'] = router['addr'] 812 config['tagname'] = router['addr']
687 813
688 return config 814 return config
OLDNEW
« no previous file with comments | « client/config/wifi_testbed_config.cros-5 ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698