netperf.py 25.2 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
from autotest.client import utils
L
Lucas Meneghel Rodrigues 已提交
8
from autotest.client.shared import error
9
from virttest import utils_test, utils_misc, utils_net, remote, data_dir
10 11


A
Amos Kong 已提交
12
def format_result(result, base="12", fbase="5"):
13 14 15
    """
    Format the result to a fixed length string.

L
Lucas Meneghel Rodrigues 已提交
16 17 18
    :param result: result need to convert
    :param base: the length of converted string
    :param fbase: the decimal digit for float
19 20 21 22 23 24 25 26 27 28 29 30 31 32
    """
    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 已提交
33 34
    :param results: a dict include the results for the variables
    :param filter_list: variable list which is wanted to be shown in the
35
                        record file, also fix the order of variables
L
Lucas Meneghel Rodrigues 已提交
36 37 38
    :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
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    """
    key_list = []
    for key in filter_list:
        if results.has_key(key):
            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 已提交
57 58 59 60 61 62 63 64 65
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 已提交
66 67


68
@error.context_aware
69
def run(test, params, env):
70 71 72 73 74 75 76 77
    """
    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 已提交
78 79 80
    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
81
    """
82
    def env_setup(session, ip, user, port, password):
83
        error.context("Setup env for %s" % ip)
Y
Yunping Zheng 已提交
84
        ssh_cmd(session, "iptables -F; true")
85
        ssh_cmd(session, "service iptables stop; true")
86
        ssh_cmd(session, "echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore")
87

Y
Yunping Zheng 已提交
88 89 90 91 92
        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")
93
        ssh_cmd(session, params.get("setup_cmd"))
94

L
Lucas Meneghel Rodrigues 已提交
95
        agent_path = os.path.join(test.virtdir, "scripts/netperf_agent.py")
96
        remote.scp_to_remote(ip, shell_port, username, password,
Y
Yunping Zheng 已提交
97
                             agent_path, "/tmp")
98 99 100 101 102

    def _pin_vm_threads(vm, node):
        if node:
            if not isinstance(node, utils_misc.NumaNode):
                node = utils_misc.NumaNode(int(node))
103
            utils_test.qemu.pin_vm_threads(vm, node)
104 105 106

        return node

107 108 109
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    login_timeout = int(params.get("login_timeout", 360))
110

111
    session = vm.wait_for_login(timeout=login_timeout)
112 113 114 115 116 117 118 119 120
    queues = int(params.get("queues", 1))
    if queues > 1:
        if params.get("os_type") == "linux":
            ethname = utils_net.get_linux_ifname(session, vm.get_mac_address(0))
            session.cmd_status_output("ethtool -L %s combined %s" %
                                      (ethname, queues))
        else:
            logging.info("FIXME: support to enable MQ for Windows guest!")

121 122 123 124 125 126 127 128 129 130 131 132
    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)

133 134 135 136
    if params.get("rh_perf_envsetup_script"):
        utils_test.service_setup(vm, session, test.virtdir)
    session.close()

137
    server_ip = vm.wait_for_get_address(0, timeout=5)
138 139
    server_ctl = vm.wait_for_login(timeout=login_timeout)
    server_ctl_ip = server_ip
140
    if (params.get("os_type") == "windows"
L
Lucas Meneghel Rodrigues 已提交
141
            and params.get("use_cygwin") == "yes"):
Y
Yunping Zheng 已提交
142
        cygwin_prompt = params.get("cygwin_prompt", r"\$\s+$")
Y
Yiqiao Pu 已提交
143 144 145 146 147 148 149
        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

150
    if len(params.get("nics", "").split()) > 1:
Y
Yunping Zheng 已提交
151
        vm.wait_for_login(nic_index=1, timeout=login_timeout)
152
        server_ctl_ip = vm.wait_for_get_address(1, timeout=5)
153

154 155 156
    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
157 158
    numa_node = _pin_vm_threads(vm, params.get("numa_node"))

159 160 161
    host = params.get("host", "localhost")
    host_ip = host
    if host != "localhost":
L
Lucas Meneghel Rodrigues 已提交
162
        params_host = params.object_params("host")
163 164 165 166 167 168
        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"))
169

170
    client = params.get("client", "localhost")
171 172
    client_ip = client
    clients = []
173 174
    # client session 1 for control, session 2 for data communication
    for i in range(2):
Y
Yiqiao Pu 已提交
175
        if client in params.get("vms"):
176
            vm_client = env.get_vm(client)
Y
Yiqiao Pu 已提交
177
            tmp = vm_client.wait_for_login(timeout=login_timeout)
178
            client_ip = vm_client.wait_for_get_address(0, timeout=5)
Y
Yiqiao Pu 已提交
179
        elif client != "localhost":
180 181 182 183 184 185
            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"))
186 187 188 189 190
        else:
            tmp = "localhost"
        clients.append(tmp)
    client = clients[0]

191 192 193
    vms_list = params["vms"].split()
    if len(vms_list) > 1:
        vm2 = env.get_vm(vms_list[-1])
194 195 196 197
        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)
198 199
        client = vm2.wait_for_login(timeout=login_timeout)
        client_ip = vm2.get_address()
200
        session2.close()
201
        _pin_vm_threads(vm2, numa_node)
202

203
    error.context("Prepare env of server/client/host", logging.info)
Y
Yiqiao Pu 已提交
204 205 206 207 208 209
    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":
210 211 212
            shell_port = int(params_tmp["shell_port"])
            password = params_tmp["password"]
            username = params_tmp["username"]
Y
Yiqiao Pu 已提交
213
            env_setup(i, ip_dict[i], username, shell_port, password)
214

215
    env.stop_tcpdump()
216

217
    error.context("Start netperf testing", logging.info)
218
    start_test(server_ip, server_ctl, host, clients, test.resultsdir,
219 220 221 222 223 224 225
               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"),
226
               netserver_port=params.get('netserver_port', "12865"),
Y
Yiqiao Pu 已提交
227
               params=params, server_cyg=server_cyg, test=test)
228

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    if params.get("log_hostinfo_script"):
        src = os.path.join(test.virtdir, params.get("log_hostinfo_script"))
        path = os.path.join(test.resultsdir, "sysinfo")
        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"))
        path = os.path.join(test.resultsdir, "sysinfo")
        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()

245

Y
Yiqiao Pu 已提交
246
@error.context_aware
A
Amos Kong 已提交
247
def start_test(server, server_ctl, host, clients, resultsdir, l=60,
248 249 250
               sessions_rr="50 100 250 500", sessions="1 2 4",
               sizes_rr="64 256 512 1024 2048",
               sizes="64 256 512 1024 2048 4096",
251
               protocols="TCP_STREAM TCP_MAERTS TCP_RR TCP_CRR", ver_cmd=None,
Y
Yiqiao Pu 已提交
252
               netserver_port=None, params={}, server_cyg=None, test=None):
253 254 255
    """
    Start to test with different kind of configurations

L
Lucas Meneghel Rodrigues 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    :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
271 272
    """

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

L
Lucas Meneghel Rodrigues 已提交
276 277 278 279 280
    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})
281

L
Lucas Meneghel Rodrigues 已提交
282 283
    fd.write('### kvm-userspace-ver : %s\n' %
             commands.getoutput(ver_cmd).strip())
284
    fd.write('### guest-kernel-ver : %s\n' % ssh_cmd(server_ctl,
L
Lucas Meneghel Rodrigues 已提交
285 286 287
                                                     guest_ver_cmd).strip())
    fd.write('### kvm_version : %s\n' % os.uname()[2])
    fd.write('### session-length : %s\n' % l)
288 289 290

    record_list = ['size', 'sessions', 'throughput', 'trans.rate', 'CPU',
                   'thr_per_CPU', 'rx_pkts', 'tx_pkts', 'rx_byts', 'tx_byts',
291 292 293 294 295 296 297
                   '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')
298 299 300
    base = params.get("format_base", "12")
    fbase = params.get("format_fbase", "2")

301
    output = ssh_cmd(host, "mpstat 1 1 |grep CPU")
Y
Yunping Zheng 已提交
302
    mpstat_head = re.findall(r"CPU\s+.*", output)[0].split()
303 304 305 306 307 308
    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

309
    for protocol in protocols.split():
310
        error.context("Testing %s protocol" % protocol, logging.info)
311
        if protocol in ("TCP_RR", "TCP_CRR"):
312 313
            sessions_test = sessions_rr.split()
            sizes_test = sizes_rr.split()
Y
Yiqiao Pu 已提交
314
            protocol_log = protocol
315 316 317
        else:
            sessions_test = sessions.split()
            sizes_test = sizes.split()
Y
Yiqiao Pu 已提交
318 319 320 321
            if protocol == "TCP_STREAM":
                protocol_log = protocol + " (RX)"
            elif protocol == "TCP_MAERTS":
                protocol_log = protocol + " (TX)"
L
Lucas Meneghel Rodrigues 已提交
322
        fd.write("Category:" + protocol_log + "\n")
Y
Yiqiao Pu 已提交
323

324
        record_header = True
325 326
        for i in sizes_test:
            for j in sessions_test:
327
                if protocol in ("TCP_RR", "TCP_CRR"):
Y
Yunping Zheng 已提交
328 329 330
                    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)
331
                else:
Y
Yunping Zheng 已提交
332 333 334 335
                    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 已提交
336 337

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

L
Lucas Meneghel Rodrigues 已提交
362
                test.write_test_keyval({'category': category})
363 364
                prefix = '%s--%s--%s' % (protocol, i, j)
                for key in key_list:
L
Lucas Meneghel Rodrigues 已提交
365 366
                    test.write_perf_keyval(
                        {'%s--%s' % (prefix, key): ret[key]})
367

368 369 370 371
                logging.info(row)
                fd.write(row + "\n")

                fd.flush()
372 373

                kill_cmd = "killall netperf"
374
                if params.get("os_type") == "windows":
375
                    kill_cmd = "taskkill /F /IM netperf*"
376
                ssh_cmd(clients[-1], kill_cmd, ignore_status=True)
377

378
                logging.debug("Remove temporary files")
A
Amos Kong 已提交
379
                commands.getoutput("rm -f /tmp/netperf.%s.nf" % ret['pid'])
380
                logging.info("Netperf thread completed successfully")
381 382 383
    fd.close()


384
def ssh_cmd(session, cmd, timeout=120, ignore_status=False):
385 386 387
    """
    Execute remote command and return the output

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


400
@error.context_aware
A
Amos Kong 已提交
401
def launch_client(sessions, server, server_ctl, host, clients, l, nf_args,
Y
Yiqiao Pu 已提交
402
                  port, params, server_cyg):
403 404
    """ Launch netperf clients """

Y
Yunping Zheng 已提交
405 406 407
    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
Y
Yiqiao Pu 已提交
408
    # Start netserver
409
    error.context("Start Netserver on guest", logging.info)
Y
Yiqiao Pu 已提交
410 411
    if params.get("os_type") == "windows":
        timeout = float(params.get("timeout", "240"))
Y
Yunping Zheng 已提交
412 413
        cdrom_drv = utils_misc.get_winutils_vol(server_ctl)
        get_status_flag = False
414
        if params.get("use_cygwin") == "yes":
Y
Yunping Zheng 已提交
415 416
            netserv_start_cmd = params.get("netserv_start_cmd")
            netperf_src = params.get("netperf_src") % cdrom_drv
417
            cygwin_root = params.get("cygwin_root")
Y
Yunping Zheng 已提交
418
            netserver_path = params.get("netserver_path")
419
            netperf_install_cmd = params.get("netperf_install_cmd")
Y
Yunping Zheng 已提交
420 421 422
            start_session = server_cyg
            logging.info("Start netserver with cygwin, cmd is: %s" %
                         netserv_start_cmd)
423
            if "netserver" not in server_ctl.cmd_output("tasklist"):
Y
Yunping Zheng 已提交
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
                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")

439
        else:
Y
Yunping Zheng 已提交
440 441 442 443 444 445 446
            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)
447

Y
Yiqiao Pu 已提交
448
    else:
449
        logging.info("Netserver start cmd is '%s'" % server_path)
Y
Yiqiao Pu 已提交
450 451 452
        ssh_cmd(server_ctl, "pidof netserver || %s" % server_path)
        get_status_flag = True
        ncpu = ssh_cmd(server_ctl, "cat /proc/cpuinfo |grep processor |wc -l")
Y
Yunping Zheng 已提交
453
        ncpu = re.findall(r"\d+", ncpu)[0]
Y
Yiqiao Pu 已提交
454

455
    logging.info("Netserver start successfully")
456 457 458

    def count_interrupt(name):
        """
459 460 461
        Get a list of interrut number for each queue

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

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

        path = "find /sys/devices|grep net/%s/statistics" % ifname
        cmd = "%s/rx_packets|xargs cat;%s/tx_packets|xargs cat;" \
L
Lucas Meneghel Rodrigues 已提交
480 481
            "%s/rx_bytes|xargs cat;%s/tx_bytes|xargs cat" % (path,
                                                             path, path, path)
482
        output = ssh_cmd(server_ctl, cmd).split()[-4:]
483 484 485 486 487 488

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

489
        nre = int(ssh_cmd(server_ctl, "grep Tcp /proc/net/snmp|tail -1"
L
Lucas Meneghel Rodrigues 已提交
490
                          ).split()[12])
491 492 493 494 495
        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")
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
            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)

512 513 514 515 516
        except IndexError:
            ninit = count_interrupt("virtio.")
            state_list.append('intr')
            state_list.append(ninit)

517
        io_exit = int(ssh_cmd(host, "cat /sys/kernel/debug/kvm/io_exits"))
L
Lucas Meneghel Rodrigues 已提交
518 519
        irq_inj = int(
            ssh_cmd(host, "cat /sys/kernel/debug/kvm/irq_injections"))
520 521 522 523 524 525
        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 已提交
526
    def netperf_thread(i, numa_enable, client_s, timeout):
527
        cmd = ""
A
Amos Kong 已提交
528
        fname = "/tmp/netperf.%s.nf" % pid
529 530
        if numa_enable:
            output = ssh_cmd(client_s, "numactl --hardware")
Y
Yunping Zheng 已提交
531
            n = int(re.findall(r"available: (\d+) nodes", output)[0]) - 1
532
            cmd += "numactl --cpunodebind=%s --membind=%s " % (n, n)
533
        cmd += "/tmp/netperf_agent.py %d %s -D 1 -H %s -l %s %s" % (i,
L
Lucas Meneghel Rodrigues 已提交
534
               client_path, server, int(l) * 1.5, nf_args)
A
Amos Kong 已提交
535
        cmd += " >> %s" % fname
536
        logging.info("Start netperf thread by cmd '%s'" % cmd)
537
        ssh_cmd(client_s, cmd)
A
Amos Kong 已提交
538

Y
Yunping Zheng 已提交
539 540 541 542 543 544 545 546 547 548
    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 已提交
549 550 551 552 553
    def parse_demo_result(fname, sessions):
        """
        Process the demo result, remove the noise from head,
        and compute the final throughout.

L
Lucas Meneghel Rodrigues 已提交
554 555
        :param fname: result file name
        :param sessions: sessions' number
A
Amos Kong 已提交
556 557 558 559 560
        """
        fd = open(fname)
        lines = fd.readlines()
        fd.close()

L
Lucas Meneghel Rodrigues 已提交
561
        for i in range(1, len(lines) + 1):
A
Amos Kong 已提交
562 563 564 565 566 567 568 569 570 571
            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 已提交
572
            if "Interim" in this:
Y
Yunping Zheng 已提交
573
                result += float(re.findall(r"Interim result: *(\S+)", this)[0])
A
Amos Kong 已提交
574 575 576
        result = result / niteration
        logging.debug("niteration: %s" % niteration)
        return result
577

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

591 592
    ret = {}
    ret['pid'] = pid
A
Amos Kong 已提交
593

594
    if utils_misc.wait_for(all_clients_up, timeout_netperf_start, 0.0, 0.2,
Y
Yunping Zheng 已提交
595 596 597 598
                           "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 已提交
599 600 601 602

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

A
Amos Kong 已提交
606
    # real & effective test ends
Y
Yiqiao Pu 已提交
607 608
    if get_status_flag:
        end_state = get_state()
609 610 611 612 613 614 615 616 617
        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):
                ret[end_state[i * 2]] = (end_state[i * 2 + 1]
                                         - start_state[i * 2 + 1])
618 619

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

621
    error.context("Testing Results Treatment and Report", logging.info)
A
Amos Kong 已提交
622 623 624
    f = open(fname, "w")
    f.write(finished_result)
    f.close()
A
Amos Kong 已提交
625
    ret['thu'] = parse_demo_result(fname, int(sessions))
626
    return ret