netperf.py 25.7 KB
Newer Older
L
Lucas Meneghel Rodrigues 已提交
1 2 3 4 5 6
import logging
import os
import commands
import threading
import re
import time
7

8
from autotest.client import utils
L
Lucas Meneghel Rodrigues 已提交
9
from autotest.client.shared import error
10 11 12 13 14 15

from virttest import utils_test
from virttest import utils_misc
from virttest import utils_net
from virttest import remote
from virttest import data_dir
16 17


18 19 20
_netserver_started = False


A
Amos Kong 已提交
21
def format_result(result, base="12", fbase="5"):
22 23 24
    """
    Format the result to a fixed length string.

L
Lucas Meneghel Rodrigues 已提交
25 26 27
    :param result: result need to convert
    :param base: the length of converted string
    :param fbase: the decimal digit for float
28 29 30 31 32 33 34 35 36 37 38 39 40 41
    """
    if isinstance(result, str):
        value = "%" + base + "s"
    elif isinstance(result, int):
        value = "%" + base + "d"
    elif isinstance(result, float):
        value = "%" + base + "." + fbase + "f"
    return value % result


def netperf_record(results, filter_list, header=False, base="12", fbase="2"):
    """
    Record the results in a certain format.

L
Lucas Meneghel Rodrigues 已提交
42 43
    :param results: a dict include the results for the variables
    :param filter_list: variable list which is wanted to be shown in the
44
                        record file, also fix the order of variables
L
Lucas Meneghel Rodrigues 已提交
45 46 47
    :param header: if record the variables as a column name before the results
    :param base: the length of a variable
    :param fbase: the decimal digit for float
48 49 50
    """
    key_list = []
    for key in filter_list:
51
        if key in results:
52 53 54 55 56 57 58 59 60 61 62 63 64 65
            key_list.append(key)

    record = ""
    if header:
        for key in key_list:
            record += "%s|" % format_result(key, base=base, fbase=fbase)
        record = record.rstrip("|")
        record += "\n"
    for key in key_list:
        record += "%s|" % format_result(results[key], base=base, fbase=fbase)
    record = record.rstrip("|")
    return record, key_list


Y
Yunping Zheng 已提交
66 67 68 69 70 71 72 73 74
def start_netserver_win(session, start_cmd):
    check_reg = re.compile(r"NETSERVER.*EXE", re.I)
    if not check_reg.findall(session.cmd_output("tasklist")):
        session.sendline(start_cmd)
        if not utils_misc.wait_for(lambda: check_reg.findall(
                                   session.cmd_output("tasklist")),
                                   30, 5, 1, "Wait netserver start"):
            msg = "Can not start netserver with command %s" % start_cmd
            raise error.TestError(msg)
Y
Yiqiao Pu 已提交
75 76


77
@error.context_aware
78
def run(test, params, env):
79 80 81 82 83 84 85 86
    """
    Network stress test with netperf.

    1) Boot up VM(s), setup SSH authorization between host
       and guest(s)/external host
    2) Prepare the test environment in server/client/host
    3) Execute netperf tests, collect and analyze the results

L
Lucas Meneghel Rodrigues 已提交
87 88 89
    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
90
    """
91
    def env_setup(session, ip, user, port, password):
92
        error.context("Setup env for %s" % ip)
93 94
        ssh_cmd(session, "iptables -F", ignore_status=True)
        ssh_cmd(session, "service iptables stop", ignore_status=True)
95
        ssh_cmd(session, "echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore")
96

Y
Yunping Zheng 已提交
97 98 99 100 101
        download_link = params.get("netperf_download_link")
        download_dir = data_dir.get_download_dir()
        md5sum = params.get("pkg_md5sum")
        pkg = utils.unmap_url_cache(download_dir, download_link, md5sum)
        remote.scp_to_remote(ip, shell_port, username, password, pkg, "/tmp")
102
        ssh_cmd(session, params.get("setup_cmd"))
103

L
Lucas Meneghel Rodrigues 已提交
104
        agent_path = os.path.join(test.virtdir, "scripts/netperf_agent.py")
105
        remote.scp_to_remote(ip, shell_port, username, password,
Y
Yunping Zheng 已提交
106
                             agent_path, "/tmp")
107 108 109 110 111

    def _pin_vm_threads(vm, node):
        if node:
            if not isinstance(node, utils_misc.NumaNode):
                node = utils_misc.NumaNode(int(node))
112
            utils_test.qemu.pin_vm_threads(vm, node)
113 114 115

        return node

116 117 118
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    login_timeout = int(params.get("login_timeout", 360))
119

120
    session = vm.wait_for_login(timeout=login_timeout)
121 122 123
    queues = int(params.get("queues", 1))
    if queues > 1:
        if params.get("os_type") == "linux":
124 125
            ethname = utils_net.get_linux_ifname(session,
                                                 vm.get_mac_address(0))
126 127 128 129 130
            session.cmd_status_output("ethtool -L %s combined %s" %
                                      (ethname, queues))
        else:
            logging.info("FIXME: support to enable MQ for Windows guest!")

131 132 133 134 135 136 137 138 139 140 141 142
    config_cmds = params.get("config_cmds")
    if config_cmds:
        for config_cmd in config_cmds.split(","):
            cmd = params.get(config_cmd.strip())
            if cmd:
                s, o = session.cmd_status_output(cmd)
                if s:
                    msg = "Config command %s failed. Output: %s" % (cmd, o)
                    raise error.TestError(msg)
        if params.get("reboot_after_config", "yes") == "yes":
            session = vm.reboot(session=session, timeout=login_timeout)

143 144 145 146
    if params.get("rh_perf_envsetup_script"):
        utils_test.service_setup(vm, session, test.virtdir)
    session.close()

147
    server_ip = vm.wait_for_get_address(0, timeout=5)
148 149
    server_ctl = vm.wait_for_login(timeout=login_timeout)
    server_ctl_ip = server_ip
L
Lukáš Doktor 已提交
150 151
    if (params.get("os_type") == "windows" and
            params.get("use_cygwin") == "yes"):
Y
Yunping Zheng 已提交
152
        cygwin_prompt = params.get("cygwin_prompt", r"\$\s+$")
Y
Yiqiao Pu 已提交
153 154 155 156 157 158 159
        cygwin_start = params.get("cygwin_start")
        server_cyg = vm.wait_for_login(timeout=login_timeout)
        server_cyg.set_prompt(cygwin_prompt)
        server_cyg.cmd_output(cygwin_start)
    else:
        server_cyg = None

160
    if len(params.get("nics", "").split()) > 1:
Y
Yunping Zheng 已提交
161
        vm.wait_for_login(nic_index=1, timeout=login_timeout)
162
        server_ctl_ip = vm.wait_for_get_address(1, timeout=5)
163

164 165 166
    logging.debug(commands.getoutput("numactl --hardware"))
    logging.debug(commands.getoutput("numactl --show"))
    # pin guest vcpus/memory/vhost threads to last numa node of host by default
167 168
    numa_node = _pin_vm_threads(vm, params.get("numa_node"))

169 170 171
    host = params.get("host", "localhost")
    host_ip = host
    if host != "localhost":
L
Lucas Meneghel Rodrigues 已提交
172
        params_host = params.object_params("host")
173 174 175 176 177 178
        host = remote.wait_for_login(params_host.get("shell_client"),
                                     host_ip,
                                     params_host.get("shell_port"),
                                     params_host.get("username"),
                                     params_host.get("password"),
                                     params_host.get("shell_prompt"))
179

180
    client = params.get("client", "localhost")
181 182
    client_ip = client
    clients = []
183 184
    # client session 1 for control, session 2 for data communication
    for i in range(2):
Y
Yiqiao Pu 已提交
185
        if client in params.get("vms"):
186
            vm_client = env.get_vm(client)
Y
Yiqiao Pu 已提交
187
            tmp = vm_client.wait_for_login(timeout=login_timeout)
188
            client_ip = vm_client.wait_for_get_address(0, timeout=5)
Y
Yiqiao Pu 已提交
189
        elif client != "localhost":
190 191 192 193 194 195
            tmp = remote.wait_for_login(params.get("shell_client_client"),
                                        client_ip,
                                        params.get("shell_port_client"),
                                        params.get("username_client"),
                                        params.get("password_client"),
                                        params.get("shell_prompt_client"))
196 197 198 199 200
        else:
            tmp = "localhost"
        clients.append(tmp)
    client = clients[0]

201 202 203
    vms_list = params["vms"].split()
    if len(vms_list) > 1:
        vm2 = env.get_vm(vms_list[-1])
204 205 206 207
        vm2.verify_alive()
        session2 = vm2.wait_for_login(timeout=login_timeout)
        if params.get("rh_perf_envsetup_script"):
            utils_test.service_setup(vm2, session2, test.virtdir)
208 209
        client = vm2.wait_for_login(timeout=login_timeout)
        client_ip = vm2.get_address()
210
        session2.close()
211
        _pin_vm_threads(vm2, numa_node)
212

213
    error.context("Prepare env of server/client/host", logging.info)
Y
Yiqiao Pu 已提交
214 215 216 217 218 219
    prepare_list = set([server_ctl, client, host])
    tag_dict = {server_ctl: "server", client: "client", host: "host"}
    ip_dict = {server_ctl: server_ctl_ip, client: client_ip, host: host_ip}
    for i in prepare_list:
        params_tmp = params.object_params(tag_dict[i])
        if params_tmp.get("os_type") == "linux":
220 221 222
            shell_port = int(params_tmp["shell_port"])
            password = params_tmp["password"]
            username = params_tmp["username"]
Y
Yiqiao Pu 已提交
223
            env_setup(i, ip_dict[i], username, shell_port, password)
224

225
    env.stop_tcpdump()
226

227
    error.context("Start netperf testing", logging.info)
228
    start_test(server_ip, server_ctl, host, clients, test.resultsdir,
229 230 231 232 233 234 235
               l=int(params.get('l')),
               sessions_rr=params.get('sessions_rr'),
               sessions=params.get('sessions'),
               sizes_rr=params.get('sizes_rr'),
               sizes=params.get('sizes'),
               protocols=params.get('protocols'),
               ver_cmd=params.get('ver_cmd', "rpm -q qemu-kvm"),
236
               netserver_port=params.get('netserver_port', "12865"),
Y
Yiqiao Pu 已提交
237
               params=params, server_cyg=server_cyg, test=test)
238

239 240
    if params.get("log_hostinfo_script"):
        src = os.path.join(test.virtdir, params.get("log_hostinfo_script"))
241
        path = os.path.join(test.resultsdir, "systeminfo")
242 243 244 245
        utils.system_output("bash %s %s &> %s" % (src, test.resultsdir, path))

    if params.get("log_guestinfo_script") and params.get("log_guestinfo_exec"):
        src = os.path.join(test.virtdir, params.get("log_guestinfo_script"))
246
        path = os.path.join(test.resultsdir, "systeminfo")
247 248 249 250 251 252 253 254
        destpath = params.get("log_guestinfo_path", "/tmp/log_guestinfo.sh")
        vm.copy_files_to(src, destpath)
        logexec = params.get("log_guestinfo_exec", "bash")
        output = server_ctl.cmd_output("%s %s" % (logexec, destpath))
        logfile = open(path, "a+")
        logfile.write(output)
        logfile.close()

255

Y
Yiqiao Pu 已提交
256
@error.context_aware
A
Amos Kong 已提交
257
def start_test(server, server_ctl, host, clients, resultsdir, l=60,
258 259 260
               sessions_rr="50 100 250 500", sessions="1 2 4",
               sizes_rr="64 256 512 1024 2048",
               sizes="64 256 512 1024 2048 4096",
261
               protocols="TCP_STREAM TCP_MAERTS TCP_RR TCP_CRR", ver_cmd=None,
Y
Yiqiao Pu 已提交
262
               netserver_port=None, params={}, server_cyg=None, test=None):
263 264 265
    """
    Start to test with different kind of configurations

L
Lucas Meneghel Rodrigues 已提交
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
    :param server: netperf server ip for data connection
    :param server_ctl: ip to control netperf server
    :param host: localhost ip
    :param clients: netperf clients' ip
    :param resultsdir: directory to restore the results
    :param l: test duration
    :param sessions_rr: sessions number list for RR test
    :param sessions: sessions number list
    :param sizes_rr: request/response sizes (TCP_RR, UDP_RR)
    :param sizes: send size (TCP_STREAM, UDP_STREAM)
    :param protocols: test type
    :param ver_cmd: command to check kvm version
    :param netserver_port: netserver listen port
    :param params: Dictionary with the test parameters.
    :param server_cyg: shell session for cygwin in windows guest
281 282
    """

Y
Yiqiao Pu 已提交
283
    guest_ver_cmd = params.get("guest_ver_cmd", "uname -r")
284
    fd = open("%s/netperf-result.%s.RHS" % (resultsdir, time.time()), "w")
285

L
Lucas Meneghel Rodrigues 已提交
286 287 288 289 290
    test.write_test_keyval({'kvm-userspace-ver':
                            commands.getoutput(ver_cmd).strip()})
    test.write_test_keyval({'guest-kernel-ver': ssh_cmd(server_ctl,
                                                        guest_ver_cmd).strip()})
    test.write_test_keyval({'session-length': l})
291

L
Lucas Meneghel Rodrigues 已提交
292 293
    fd.write('### kvm-userspace-ver : %s\n' %
             commands.getoutput(ver_cmd).strip())
294
    fd.write('### guest-kernel-ver : %s\n' % ssh_cmd(server_ctl,
L
Lucas Meneghel Rodrigues 已提交
295 296 297
                                                     guest_ver_cmd).strip())
    fd.write('### kvm_version : %s\n' % os.uname()[2])
    fd.write('### session-length : %s\n' % l)
298 299 300

    record_list = ['size', 'sessions', 'throughput', 'trans.rate', 'CPU',
                   'thr_per_CPU', 'rx_pkts', 'tx_pkts', 'rx_byts', 'tx_byts',
301 302 303 304 305 306 307
                   're_pkts', 'irq_inj', 'io_exit', 'rpkt_per_irq', 'tpkt_per_exit']
    for i in range(int(params.get("queues", 0))):
        record_list.append('rx_intr_%s' % i)
    record_list.append('rx_intr_sum')
    for i in range(int(params.get("queues", 0))):
        record_list.append('tx_intr_%s' % i)
    record_list.append('tx_intr_sum')
308 309 310
    base = params.get("format_base", "12")
    fbase = params.get("format_fbase", "2")

311
    output = ssh_cmd(host, "mpstat 1 1 |grep CPU")
Y
Yunping Zheng 已提交
312
    mpstat_head = re.findall(r"CPU\s+.*", output)[0].split()
313 314 315 316 317 318
    mpstat_key = params.get("mpstat_key", "%idle")
    if mpstat_key in mpstat_head:
        mpstat_index = mpstat_head.index(mpstat_key) + 1
    else:
        mpstat_index = 0

319
    for protocol in protocols.split():
320
        error.context("Testing %s protocol" % protocol, logging.info)
321
        if protocol in ("TCP_RR", "TCP_CRR"):
322 323
            sessions_test = sessions_rr.split()
            sizes_test = sizes_rr.split()
Y
Yiqiao Pu 已提交
324
            protocol_log = protocol
325 326 327
        else:
            sessions_test = sessions.split()
            sizes_test = sizes.split()
Y
Yiqiao Pu 已提交
328 329 330 331
            if protocol == "TCP_STREAM":
                protocol_log = protocol + " (RX)"
            elif protocol == "TCP_MAERTS":
                protocol_log = protocol + " (TX)"
L
Lucas Meneghel Rodrigues 已提交
332
        fd.write("Category:" + protocol_log + "\n")
Y
Yiqiao Pu 已提交
333

334
        record_header = True
335 336
        for i in sizes_test:
            for j in sessions_test:
337
                if protocol in ("TCP_RR", "TCP_CRR"):
Y
Yunping Zheng 已提交
338 339 340
                    nf_args = "-t %s -v 1 -- -r %s,%s" % (protocol, i, i)
                elif (protocol == "TCP_MAERTS"):
                    nf_args = "-C -c -t %s -- -m ,%s" % (protocol, i)
341
                else:
Y
Yunping Zheng 已提交
342 343 344 345
                    nf_args = "-C -c -t %s -- -m %s" % (protocol, i)

                ret = launch_client(j, server, server_ctl, host, clients, l,
                                    nf_args, netserver_port, params, server_cyg)
A
Amos Kong 已提交
346 347

                thu = float(ret['thu'])
348
                cpu = 100 - float(ret['mpstat'].split()[mpstat_index])
349
                normal = thu / cpu
350
                if ret.get('rx_pkts') and ret.get('irq_inj'):
A
Amos Kong 已提交
351
                    ret['rpkt_per_irq'] = float(
L
Lucas Meneghel Rodrigues 已提交
352
                        ret['rx_pkts']) / float(ret['irq_inj'])
353
                if ret.get('tx_pkts') and ret.get('io_exit'):
A
Amos Kong 已提交
354
                    ret['tpkt_per_exit'] = float(
L
Lucas Meneghel Rodrigues 已提交
355
                        ret['tx_pkts']) / float(ret['io_exit'])
356 357
                ret['size'] = int(i)
                ret['sessions'] = int(j)
358
                if protocol in ("TCP_RR", "TCP_CRR"):
Y
Yiqiao Pu 已提交
359 360 361
                    ret['trans.rate'] = thu
                else:
                    ret['throughput'] = thu
362 363
                ret['CPU'] = cpu
                ret['thr_per_CPU'] = normal
L
Lucas Meneghel Rodrigues 已提交
364 365 366 367
                row, key_list = netperf_record(ret, record_list,
                                               header=record_header,
                                               base=base,
                                               fbase=fbase)
368 369 370 371
                if record_header:
                    record_header = False
                    category = row.split('\n')[0]

L
Lucas Meneghel Rodrigues 已提交
372
                test.write_test_keyval({'category': category})
373 374
                prefix = '%s--%s--%s' % (protocol, i, j)
                for key in key_list:
375
                    test.write_test_keyval(
L
Lucas Meneghel Rodrigues 已提交
376
                        {'%s--%s' % (prefix, key): ret[key]})
377

378 379 380 381
                logging.info(row)
                fd.write(row + "\n")

                fd.flush()
382

383
                logging.debug("Remove temporary files")
A
Amos Kong 已提交
384
                commands.getoutput("rm -f /tmp/netperf.%s.nf" % ret['pid'])
385
                logging.info("Netperf thread completed successfully")
386 387 388
    fd.close()


389
def ssh_cmd(session, cmd, timeout=120, ignore_status=False):
390 391 392
    """
    Execute remote command and return the output

L
Lucas Meneghel Rodrigues 已提交
393 394 395
    :param session: a remote shell session or tag for localhost
    :param cmd: executed command
    :param timeout: timeout for the command
396
    """
397
    if session == "localhost":
398 399
        o = utils.system_output(cmd, timeout=timeout,
                                ignore_status=ignore_status)
400
    else:
401 402
        o = session.cmd(cmd, timeout=timeout, ignore_all_errors=ignore_status)
    return o
403 404


405
@error.context_aware
A
Amos Kong 已提交
406
def launch_client(sessions, server, server_ctl, host, clients, l, nf_args,
Y
Yiqiao Pu 已提交
407
                  port, params, server_cyg):
408 409
    """ Launch netperf clients """

Y
Yunping Zheng 已提交
410 411 412
    netperf_version = params.get("netperf_version", "2.6.0")
    client_path = "/tmp/netperf-%s/src/netperf" % netperf_version
    server_path = "/tmp/netperf-%s/src/netserver" % netperf_version
413
    get_status_flag = params.get("get_status_in_guest", "no") == "yes"
414
    global _netserver_started
Y
Yiqiao Pu 已提交
415
    # Start netserver
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    if _netserver_started:
        logging.debug("Netserver already started.")
    else:
        error.context("Start Netserver on guest", logging.info)
        if params.get("os_type") == "windows":
            timeout = float(params.get("timeout", "240"))
            cdrom_drv = utils_misc.get_winutils_vol(server_ctl)
            if params.get("use_cygwin") == "yes":
                netserv_start_cmd = params.get("netserv_start_cmd")
                netperf_src = params.get("netperf_src") % cdrom_drv
                cygwin_root = params.get("cygwin_root")
                netserver_path = params.get("netserver_path")
                netperf_install_cmd = params.get("netperf_install_cmd")
                start_session = server_cyg
                logging.info("Start netserver with cygwin, cmd is: %s" %
                             netserv_start_cmd)
                if "netserver" not in server_ctl.cmd_output("tasklist"):
                    netperf_pack = "netperf-%s" % params.get("netperf_version")
                    s_check_cmd = "dir %s" % netserver_path
                    p_check_cmd = "dir %s" % cygwin_root
                    if not ("netserver.exe" in server_ctl.cmd(s_check_cmd) and
                            netperf_pack in server_ctl.cmd(p_check_cmd)):
                        error.context("Install netserver in Windows guest cygwin",
                                      logging.info)
                        cmd = "xcopy %s %s /S /I /Y" % (netperf_src, cygwin_root)
                        server_ctl.cmd(cmd)
                        server_cyg.cmd_output(netperf_install_cmd, timeout=timeout)
                        if "netserver.exe" not in server_ctl.cmd(s_check_cmd):
                            err_msg = "Install netserver cygwin failed"
                            raise error.TestNAError(err_msg)
                        logging.info("Install netserver in cygwin successfully")
            else:
                start_session = server_ctl
                netserv_start_cmd = params.get("netserv_start_cmd") % cdrom_drv
                logging.info("Start netserver without cygwin, cmd is: %s" %
                             netserv_start_cmd)

            error.context("Start netserver on windows guest", logging.info)
            start_netserver_win(start_session, netserv_start_cmd)
Y
Yunping Zheng 已提交
455

456
        else:
457 458 459 460
            logging.info("Netserver start cmd is '%s'" % server_path)
            ssh_cmd(server_ctl, "pidof netserver || %s" % server_path)
            ncpu = ssh_cmd(server_ctl, "cat /proc/cpuinfo |grep processor |wc -l")
            ncpu = re.findall(r"\d+", ncpu)[-1]
Y
Yiqiao Pu 已提交
461

462
        logging.info("Netserver start successfully")
463 464 465

    def count_interrupt(name):
        """
466 467 468
        Get a list of interrut number for each queue

        @param name: the name of interrupt, such as "virtio0-input"
469
        """
470 471
        sum = 0
        intr = []
472
        stat = ssh_cmd(server_ctl, "cat /proc/interrupts |grep %s" % name)
473 474 475 476 477
        for i in stat.strip().split("\n"):
            for cpu in range(int(ncpu)):
                sum += int(i.split()[cpu + 1])
            intr.append(sum)
            sum = 0
478 479 480 481 482
        return intr

    def get_state():
        for i in ssh_cmd(server_ctl, "ifconfig").split("\n\n"):
            if server in i:
Y
Yunping Zheng 已提交
483
                ifname = re.findall(r"(\w+\d+)[:\s]", i)[0]
484 485 486

        path = "find /sys/devices|grep net/%s/statistics" % ifname
        cmd = "%s/rx_packets|xargs cat;%s/tx_packets|xargs cat;" \
L
Lucas Meneghel Rodrigues 已提交
487 488
            "%s/rx_bytes|xargs cat;%s/tx_bytes|xargs cat" % (path,
                                                             path, path, path)
489
        output = ssh_cmd(server_ctl, cmd).split()[-4:]
490 491 492 493 494 495

        nrx = int(output[0])
        ntx = int(output[1])
        nrxb = int(output[2])
        ntxb = int(output[3])

496
        nre = int(ssh_cmd(server_ctl, "grep Tcp /proc/net/snmp|tail -1"
L
Lucas Meneghel Rodrigues 已提交
497
                          ).split()[12])
498 499 500 501 502
        state_list = ['rx_pkts', nrx, 'tx_pkts', ntx, 'rx_byts', nrxb,
                      'tx_byts', ntxb, 're_pkts', nre]
        try:
            nrx_intr = count_interrupt("virtio.-input")
            ntx_intr = count_interrupt("virtio.-output")
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
            sum = 0
            for i in range(len(nrx_intr)):
                state_list.append('rx_intr_%s' % i)
                state_list.append(nrx_intr[i])
                sum += nrx_intr[i]
            state_list.append('rx_intr_sum')
            state_list.append(sum)

            sum = 0
            for i in range(len(ntx_intr)):
                state_list.append('tx_intr_%s' % i)
                state_list.append(ntx_intr[i])
                sum += ntx_intr[i]
            state_list.append('tx_intr_sum')
            state_list.append(sum)

519 520 521 522 523
        except IndexError:
            ninit = count_interrupt("virtio.")
            state_list.append('intr')
            state_list.append(ninit)

524
        io_exit = int(ssh_cmd(host, "cat /sys/kernel/debug/kvm/io_exits"))
L
Lucas Meneghel Rodrigues 已提交
525 526
        irq_inj = int(
            ssh_cmd(host, "cat /sys/kernel/debug/kvm/irq_injections"))
527 528 529 530 531 532
        state_list.append('io_exit')
        state_list.append(io_exit)
        state_list.append('irq_inj')
        state_list.append(irq_inj)
        return state_list

Y
Yunping Zheng 已提交
533
    def netperf_thread(i, numa_enable, client_s, timeout):
534
        cmd = ""
A
Amos Kong 已提交
535
        fname = "/tmp/netperf.%s.nf" % pid
536 537
        if numa_enable:
            output = ssh_cmd(client_s, "numactl --hardware")
Y
Yunping Zheng 已提交
538
            n = int(re.findall(r"available: (\d+) nodes", output)[0]) - 1
539
            cmd += "numactl --cpunodebind=%s --membind=%s " % (n, n)
540
        cmd += "/tmp/netperf_agent.py %d %s -D 1 -H %s -l %s %s" % (i,
541
                                                                    client_path, server, int(l) * 1.5, nf_args)
A
Amos Kong 已提交
542
        cmd += " >> %s" % fname
543
        logging.info("Start netperf thread by cmd '%s'" % cmd)
544
        ssh_cmd(client_s, cmd)
A
Amos Kong 已提交
545

Y
Yunping Zheng 已提交
546 547 548 549 550 551 552 553 554 555
    def all_clients_up():
        try:
            content = ssh_cmd(clients[-1], "cat %s" % fname)
        except:
            content = ""
            return False
        if int(sessions) == len(re.findall("MIGRATE", content)):
            return True
        return False

A
Amos Kong 已提交
556 557 558 559 560
    def parse_demo_result(fname, sessions):
        """
        Process the demo result, remove the noise from head,
        and compute the final throughout.

L
Lucas Meneghel Rodrigues 已提交
561 562
        :param fname: result file name
        :param sessions: sessions' number
A
Amos Kong 已提交
563 564 565 566 567
        """
        fd = open(fname)
        lines = fd.readlines()
        fd.close()

L
Lucas Meneghel Rodrigues 已提交
568
        for i in range(1, len(lines) + 1):
A
Amos Kong 已提交
569 570 571 572 573 574 575 576 577 578
            if "AF_INET" in lines[-i]:
                break
        nresult = i - 1
        if nresult < int(sessions):
            raise error.TestError("We couldn't expect this parallism,"
                                  "expect %s get %s" % (sessions, nresult))

        niteration = nresult / sessions
        result = 0.0
        for this in lines[-sessions * niteration:]:
A
Amos Kong 已提交
579
            if "Interim" in this:
Y
Yunping Zheng 已提交
580
                result += float(re.findall(r"Interim result: *(\S+)", this)[0])
A
Amos Kong 已提交
581 582 583
        result = result / niteration
        logging.debug("niteration: %s" % niteration)
        return result
584

585
    error.context("Start netperf client threads", logging.info)
586
    pid = str(os.getpid())
A
Amos Kong 已提交
587 588
    fname = "/tmp/netperf.%s.nf" % pid
    ssh_cmd(clients[-1], "rm -f %s" % fname)
589
    numa_enable = params.get("netperf_with_numa", "yes") == "yes"
590
    timeout_netperf_start = int(l) * 0.5
591 592
    client_thread = threading.Thread(target=netperf_thread,
                                     kwargs={"i": int(sessions),
L
Lucas Meneghel Rodrigues 已提交
593
                                             "numa_enable": numa_enable,
Y
Yunping Zheng 已提交
594 595
                                             "client_s": clients[0],
                                             "timeout": timeout_netperf_start})
596 597
    client_thread.start()

598 599
    ret = {}
    ret['pid'] = pid
A
Amos Kong 已提交
600

601
    if utils_misc.wait_for(all_clients_up, timeout_netperf_start, 0.0, 0.2,
Y
Yunping Zheng 已提交
602 603 604 605
                           "Wait until all netperf clients start to work"):
        logging.debug("All netperf clients start to work.")
    else:
        raise error.TestNAError("Error, not all netperf clients at work")
A
Amos Kong 已提交
606 607 608 609

    # real & effective test starts
    if get_status_flag:
        start_state = get_state()
610
    ret['mpstat'] = ssh_cmd(host, "mpstat 1 %d |tail -n 1" % (l - 1))
A
Amos Kong 已提交
611
    finished_result = ssh_cmd(clients[-1], "cat %s" % fname)
612

613 614 615 616 617 618
    # stop netperf clients
    kill_cmd = "killall netperf"
    if params.get("os_type") == "windows":
        kill_cmd = "taskkill /F /IM netperf*"
    ssh_cmd(clients[-1], kill_cmd, ignore_status=True)

A
Amos Kong 已提交
619
    # real & effective test ends
Y
Yiqiao Pu 已提交
620 621
    if get_status_flag:
        end_state = get_state()
622 623 624 625 626 627 628
        if len(start_state) != len(end_state):
            msg = "Initial state not match end state:\n"
            msg += "  start state: %s\n" % start_state
            msg += "  end state: %s\n" % end_state
            logging.warn(msg)
        else:
            for i in range(len(end_state) / 2):
L
Lukáš Doktor 已提交
629 630
                ret[end_state[i * 2]] = (end_state[i * 2 + 1] -
                                         start_state[i * 2 + 1])
631 632

    client_thread.join()
A
Amos Kong 已提交
633

634
    error.context("Testing Results Treatment and Report", logging.info)
A
Amos Kong 已提交
635 636 637
    f = open(fname, "w")
    f.write(finished_result)
    f.close()
A
Amos Kong 已提交
638
    ret['thu'] = parse_demo_result(fname, int(sessions))
639
    return ret