From patchwork Thu May 6 23:13:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lucas Meneghel Rodrigues X-Patchwork-Id: 97464 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o46NDbbd004302 for ; Thu, 6 May 2010 23:13:37 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752110Ab0EFXNe (ORCPT ); Thu, 6 May 2010 19:13:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:3536 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751889Ab0EFXNe (ORCPT ); Thu, 6 May 2010 19:13:34 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o46NDWtZ002829 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 6 May 2010 19:13:32 -0400 Received: from localhost.localdomain (vpn-11-121.rdu.redhat.com [10.11.11.121]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o46NDU0h001718; Thu, 6 May 2010 19:13:31 -0400 From: Lucas Meneghel Rodrigues To: autotest@test.kernel.org Cc: kvm@vger.kernel.org, Jason Wang Subject: [PATCH] KVM test: Add a subtest iofuzz Date: Thu, 6 May 2010 20:13:28 -0300 Message-Id: <1273187608-27605-1-git-send-email-lmr@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 06 May 2010 23:13:40 +0000 (UTC) diff --git a/client/tests/kvm/tests/iofuzz.py b/client/tests/kvm/tests/iofuzz.py new file mode 100644 index 0000000..5bd1b8e --- /dev/null +++ b/client/tests/kvm/tests/iofuzz.py @@ -0,0 +1,138 @@ +import logging, time, re, random +from autotest_lib.client.common_lib import error +import kvm_subprocess, kvm_test_utils, kvm_utils + + +def run_iofuzz(test, params, env): + """ + KVM iofuzz test: + 1) Log into a guest + 2) Enumerate all IO port ranges through /proc/ioports + 3) On each port of the range: + * Read it + * Write 0 to it + * Write a random value to a random port on a random order + + If the guest SSH session hangs, the test detects the hang and the guest + is then rebooted. The test fails if we detect the qemu process to terminate + while executing the process. + + @param test: kvm test object + @param params: Dictionary with the test parameters + @param env: Dictionary with test environment. + """ + def outb(session, port, data): + """ + Write data to a given port. + + @param session: SSH session stablished to a VM + @param port: Port where we'll write the data + @param data: Integer value that will be written on the port. This + value will be converted to octal before its written. + """ + logging.debug("outb(0x%x, 0x%x)", port, data) + outb_cmd = ("echo -e '\\%s' | dd of=/dev/port seek=%d bs=1 count=1" % + (oct(data), port)) + s, o = session.get_command_status_output(outb_cmd) + if s is None: + logging.debug("Command did not return") + if s != 0: + logging.debug("Command returned status %s", s) + + + def inb(session, port): + """ + Read from a given port. + + @param session: SSH session stablished to a VM + @param port: Port where we'll read data + """ + logging.debug("inb(0x%x)", port) + inb_cmd = "dd if=/dev/port seek=%d of=/dev/null bs=1 count=1" % port + s, o = session.get_command_status_output(inb_cmd) + if s is None: + logging.debug("Command did not return") + if s != 0: + logging.debug("Command returned status %s", s) + + + def fuzz(session, inst_list): + """ + Executes a series of read/write/randwrite instructions. + + If the guest SSH session hangs, an attempt to relogin will be made. + If it fails, the guest will be reset. If during the process the VM + process abnormally ends, the test fails. + + @param inst_list: List of instructions that will be executed. + @raise error.TestFail: If the VM process dies in the middle of the + fuzzing procedure. + """ + for (op, operand) in inst_list: + if op == "read": + inb(session, operand[0]) + elif op =="write": + outb(session, operand[0], operand[1]) + else: + raise error.TestError("Unknown command %s" % op) + + if not session.is_responsive(): + logging.debug("Session is not responsive") + if vm.process.is_alive(): + logging.debug("VM is alive, try to re-login") + try: + session = kvm_test_utils.wait_for_login(vm, 0, 10, 0, 2) + except: + logging.debug("Could not re-login, reboot the guest") + session = kvm_test_utils.reboot(vm, session, + method = "system_reset") + else: + raise error.TestFail("VM has quit abnormally during %s", + (op, operand)) + + + boot_timeout = float(params.get("boot_timeout", 240)) + vm = kvm_test_utils.get_living_vm(env, params.get("main_vm")) + session = kvm_test_utils.wait_for_login(vm, 0, boot_timeout, 0, 2) + + try: + ports = {} + r = random.SystemRandom() + + logging.info("Enumerate guest devices through /proc/ioports") + ioports = session.get_command_output("cat /proc/ioports") + logging.debug(ioports) + devices = re.findall("(\w+)-(\w+)\ : (.*)", ioports) + + skip_devices = params.get("skip_devices","") + fuzz_count = int(params.get("fuzz_count", 10)) + + for (beg, end, name) in devices: + ports[(int(beg, base=16), int(end, base=16))] = name.strip() + + for (beg, end) in ports.keys(): + name = ports[(beg, end)] + if name in skip_devices: + logging.info("Skipping device %s", name) + continue + + logging.info("Fuzzing %s, port range 0x%x-0x%x", name, beg, end) + inst = [] + + # Read all ports of the range + for port in range(beg, end + 1): + inst.append(("read", [port])) + + # Write 0 to all ports of the range + for port in range(beg, end + 1): + inst.append(("write", [port, 0])) + + # Write random values to random ports of the range + for seq in range(fuzz_count * (end - beg + 1)): + inst.append(("write", + [r.randint(beg, end), r.randint(0,255)])) + + fuzz(session, inst) + + finally: + session.close() diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample index 2d56069..bb3646c 100644 --- a/client/tests/kvm/tests_base.cfg.sample +++ b/client/tests/kvm/tests_base.cfg.sample @@ -313,6 +313,8 @@ variants: ksm_mode = "serial" - ksm_parallel: ksm_mode = "parallel" + - iofuzz: + type = iofuzz # This unit test module is for older branches of KVM that use the # kvmctl test harness (such as the code shipped with RHEL 5.x)