netperf2.py revision 865ee82c4d530f88d8c41ca934920ad6d85bd019
1865ee82c4d530f88d8c41ca934920ad6d85bd019mblighimport os,time
29f8579202a07a123a3f73c1eb2211d8fe9553b11mblighfrom autotest_lib.client.bin import test, autotest_utils
39f8579202a07a123a3f73c1eb2211d8fe9553b11mblighfrom autotest_lib.client.common_lib import utils, error
49f8579202a07a123a3f73c1eb2211d8fe9553b11mbligh
556a91f076c57a1cfbbbcf9663af1a6e35d949ba4mbligh
656a91f076c57a1cfbbbcf9663af1a6e35d949ba4mblighclass netperf2(test.test):
7a5630a5382d4b04a02728684aebec3dce984e2bfmbligh    version = 2
80afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
9a5630a5382d4b04a02728684aebec3dce984e2bfmbligh    # ftp://ftp.netperf.org/netperf/netperf-2.4.4.tar.gz
10a5630a5382d4b04a02728684aebec3dce984e2bfmbligh    def setup(self, tarball = 'netperf-2.4.4.tar.gz'):
118b352856e457518fde6bab947d8fcdb3f53a39admbligh        tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
120afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        autotest_utils.extract_tarball_to_dir(tarball, self.srcdir)
130afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        os.chdir(self.srcdir)
140afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
150afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        utils.system('./configure')
160afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        utils.system('make')
170afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
180afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
190afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def initialize(self):
20a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        self.job.require_gcc()
21a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
22a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        self.server_path = '%s&' % os.path.join(self.srcdir,
23a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                                                'src/netserver')
24a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        # Add server_ip and arguments later
25a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        self.client_path = '%s %%s %%s' % os.path.join(self.srcdir,
26a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                                                       'src/netperf -H')
27a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
28b405b98fa552b9fc15b17ce11660f6b7034b11c1mbligh        self.valid_tests = ['TCP_STREAM', 'TCP_RR', 'TCP_CRR', 'TCP_SENDFILE',
2952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                            'UDP_STREAM', 'UDP_RR']
30a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        self.results = []
31865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh        self.actual_times = []
320afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
330afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
34a5630a5382d4b04a02728684aebec3dce984e2bfmbligh    def run_once(self, server_ip, client_ip, role, test='TCP_STREAM',
35a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                 test_time=10, stream_list=[1]):
36a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        if test not in self.valid_tests:
37a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            raise error.TestError('invalid test specified')
38a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        self.role = role
3952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        self.test = test
40865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh        self.test_time = test_time
4152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        self.stream_list = stream_list
42a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
430afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        server_tag = server_ip + '#netperf-server'
440afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        client_tag = client_ip + '#netperf-client'
450afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        all = [server_tag, client_tag]
46a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
47a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        for num_streams in stream_list:
48a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            if role == 'server':
49a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                self.server_start()
50a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                try:
5115b8a26d5ba95adacb523305f940ca010c191ef1mbligh                    # Wait up to ten minutes for the client to reach this
5252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                    # point.
5315b8a26d5ba95adacb523305f940ca010c191ef1mbligh                    self.job.barrier(server_tag, 'start_%d' % num_streams,
5415b8a26d5ba95adacb523305f940ca010c191ef1mbligh                                     600).rendevous(*all)
5515b8a26d5ba95adacb523305f940ca010c191ef1mbligh                    # Wait up to test_time + 5 minutes for the test to
5652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                    # complete
5715b8a26d5ba95adacb523305f940ca010c191ef1mbligh                    self.job.barrier(server_tag, 'stop_%d' % num_streams,
5815b8a26d5ba95adacb523305f940ca010c191ef1mbligh                                     test_time+300).rendevous(*all)
59a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                finally:
60a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                    self.server_stop()
61a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
62a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            elif role == 'client':
6315b8a26d5ba95adacb523305f940ca010c191ef1mbligh                # Wait up to ten minutes for the server to start
6415b8a26d5ba95adacb523305f940ca010c191ef1mbligh                self.job.barrier(client_tag, 'start_%d' % num_streams,
6515b8a26d5ba95adacb523305f940ca010c191ef1mbligh                                 600).rendevous(*all)
66a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                self.client(server_ip, test, test_time, num_streams)
6715b8a26d5ba95adacb523305f940ca010c191ef1mbligh                # Wait up to 5 minutes for the server to also reach this point
6815b8a26d5ba95adacb523305f940ca010c191ef1mbligh                self.job.barrier(client_tag, 'stop_%d' % num_streams,
6915b8a26d5ba95adacb523305f940ca010c191ef1mbligh                                 300).rendevous(*all)
70a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            else:
71a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                raise error.TestError('invalid role specified')
720afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
730afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
740afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def server_start(self):
7578be24a78e28a0352197593345d097a71f9e1e14mbligh        utils.system('killall netserver', ignore_status=True)
76a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        self.results.append(utils.system_output(self.server_path,
77a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                                                retain_output=True))
780afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
790afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
800afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def server_stop(self):
81a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        utils.system('killall netserver', ignore_status=True)
820afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
830afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
84a5630a5382d4b04a02728684aebec3dce984e2bfmbligh    def client(self, server_ip, test, test_time, num_streams):
85a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        args = '-t %s -l %d' % (test, test_time)
86a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        cmd = self.client_path % (server_ip, args)
87a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
88a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        try:
89865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh            t0 = time.time()
90a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            self.results.append(utils.get_cpu_percentage(
9152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                utils.system_output_parallel, [cmd]*num_streams,
9252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                timeout=test_time+60, retain_output=True))
93865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh            t1 = time.time()
94865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh
95865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh            self.actual_times.append(t1 - t0)
96865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh
97a5630a5382d4b04a02728684aebec3dce984e2bfmbligh        except error.CmdError, e:
98a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            """ Catch errors due to timeout, but raise others
99a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            The actual error string is:
100a5630a5382d4b04a02728684aebec3dce984e2bfmbligh              "Command did not complete within %d seconds"
101a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            called in function join_bg_job in the file common_lib/utils.py
102a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
103a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            Looking for 'within' is probably not the best way to do this but
104a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            works for now"""
105a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
10652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            if ('within' in e.additional_text
10752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                or 'non-zero' in e.additional_text):
108a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                print e.additional_text
10952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                # Results are cpu%, outputs
11052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                self.results.append((0, None))
111865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh                self.actual_times.append(1)
112a5630a5382d4b04a02728684aebec3dce984e2bfmbligh            else:
113a5630a5382d4b04a02728684aebec3dce984e2bfmbligh                raise
114a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
115a5630a5382d4b04a02728684aebec3dce984e2bfmbligh
116a5630a5382d4b04a02728684aebec3dce984e2bfmbligh    def postprocess(self):
11752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        if self.role == 'client':
11852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            if len(self.stream_list) != len(self.results):
11952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                raise error.TestError('Mismatched number of results')
12052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
12152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            function = None
12252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            keys = None
12352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
12452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            # Each of the functions return tuples in which the keys define
12552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            # what that item in the tuple represents
126b405b98fa552b9fc15b17ce11660f6b7034b11c1mbligh            if self.test in ['TCP_STREAM', 'TCP_SENDFILE']:
12752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                function = self.process_tcp_stream
12852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                keys = ('Throughput',)
12952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            elif self.test == 'UDP_STREAM':
13052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                function = self.process_udp_stream
13152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                keys = ('Throughput', 'Errors')
13252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            elif self.test in ['TCP_RR', 'TCP_CRR', 'UDP_RR']:
13352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                function = self.process_request_response
13452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                keys = ('Transfer_Rate',)
13552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            else:
13652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                raise error.TestError('Unhandled test')
13752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
13852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            # self.results is a list of tuples. The first element in each
13952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            # tuple is the cpu utilization for that run, and the second
14052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            # element is a list containing the output for each stream in that
14152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            # run.
14252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh            for i, streams in enumerate(self.stream_list):
14352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                attr = {'stream_count':streams}
14452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                keyval = {}
14552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                temp_vals = []
14652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                keyval['CPU'], outputs  = self.results[i]
147865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh                actual_time  = self.actual_times[i]
14852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
14952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                # Short circuit to handle errors due to client timeouts
15052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                if not outputs:
15152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                    self.write_iteration_keyval(attr, keyval)
15252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                    continue
15352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
15452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                for result in outputs:
15552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                    temp_vals.append(function(result))
15652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
1576d858fa16693074e41b51b8068aa0d5a670c6e56mbligh                # Compute the sum of elements returned from function which
15852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                # represent the string contained in keys
15952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                for j, key in enumerate(keys):
16052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                    vals = [x[j] for x in temp_vals]
161865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh                    # scale result by the actual time taken
162865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh                    keyval[key] = sum(vals)*self.test_time/actual_time
163865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh
164865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh                # record 'Efficiency' as perf/CPU
165865ee82c4d530f88d8c41ca934920ad6d85bd019mbligh                keyval['Efficieny'] = keyval[keys[0]]/keyval['CPU']
16652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
16752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh                self.write_iteration_keyval(attr, keyval)
16852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
16952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
17052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh    def process_tcp_stream(self, output):
171b405b98fa552b9fc15b17ce11660f6b7034b11c1mbligh        """Parses the following (works for both TCP_STREAM and TCP_SENDFILE)
172b405b98fa552b9fc15b17ce11660f6b7034b11c1mbligh        and returns a singleton containing throughput.
17352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
17452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to kcqz13.prod.google.com (10.75.222.13) port 0 AF_INET
17552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        Recv   Send    Send
17652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        Socket Socket  Message  Elapsed
17752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        Size   Size    Size     Time     Throughput
17852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        bytes  bytes   bytes    secs.    10^6bits/sec
17952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
18052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        87380  16384  16384    2.00      941.28
18152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        """
18252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
18352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        return float(output.splitlines()[6].split()[4]),
18452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
18552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
18652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh    def process_udp_stream(self, output):
18752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        """Parses the following and returns a touple containing throughput
18852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        and the number of errors.
18952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
19052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        UDP UNIDIRECTIONAL SEND TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to kcqz13.prod.google.com (10.75.222.13) port 0 AF_INET
19152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        Socket  Message  Elapsed      Messages
19252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        Size    Size     Time         Okay Errors   Throughput
19352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        bytes   bytes    secs            #      #   10^6bits/sec
19452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
19552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        129024   65507   2.00         3673      0     961.87
19652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        131072           2.00         3673            961.87
19752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        """
19852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
19952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        line_tokens = output.splitlines()[5].split()
20052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        return float(line_tokens[5]), int(line_tokens[4])
20152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
20252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
20352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh    def process_request_response(self, output):
20452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        """Parses the following which works for both rr (TCP and UDP) and crr
20552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        tests and returns a singleton containing transfer rate.
20652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
20752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to kcqz13.prod.google.com (10.75.222.13) port 0 AF_INET
20852fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        Local /Remote
20952fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        Socket Size   Request  Resp.   Elapsed  Trans.
21052fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        Send   Recv   Size     Size    Time     Rate
21152fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        bytes  Bytes  bytes    bytes   secs.    per sec
21252fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
21352fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        16384  87380  1        1       2.00     14118.53
21452fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        16384  87380
21552fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        """
21652fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh
21752fa69285dbeb9e9a0d49de4b1e12b52cda39fc6mbligh        return float(output.splitlines()[6].split()[5]),
218