[PATCH] KVM test: Add a subtest iofuzz

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The design of iofuzz is simple: it just generate random I/O port
activity inside the virtual machine. The correctness of the device
emulation may be verified through this test.

As the instrcutions are randomly generated, guest may enter the wrong
state. The test solve this issue by detect the hang and restart the
virtual machine.

The test duration could also be adjusted through the "fuzz_count". And
the parameter "skip_devices" is used to specified the devices which
should not be used to do the fuzzing.

For current version, every activity were logged and the commnad was
sent through a seesion between host and guest. Through this method may
slow down the whole test but it works well. The enumeration was done
through /proc/ioports and the scenario of avtivity is not aggressive.

Suggestions are welcomed.

Signed-off-by: Jason Wang <jasowang@xxxxxxxxxx>
---
 client/tests/kvm/tests/iofuzz.py       |   97 ++++++++++++++++++++++++++++++++
 client/tests/kvm/tests_base.cfg.sample |    2 +
 2 files changed, 99 insertions(+), 0 deletions(-)
 create mode 100644 client/tests/kvm/tests/iofuzz.py

diff --git a/client/tests/kvm/tests/iofuzz.py b/client/tests/kvm/tests/iofuzz.py
new file mode 100644
index 0000000..c2f22af
--- /dev/null
+++ b/client/tests/kvm/tests/iofuzz.py
@@ -0,0 +1,97 @@
+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
+
+    @param test: kvm test object
+    @param params: Dictionary with the test parameters
+    @param env: Dictionary with test environment.
+    """
+    vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
+    session = kvm_test_utils.wait_for_login(vm, 0,
+                                         float(params.get("boot_timeout", 240)),
+                                         0, 2)
+
+    def outb(session, port, data):
+        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 != 0:
+            logging.debug("None zero value returned")
+
+    def inb(session, port):
+        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 != 0:
+            logging.debug("None zero value returned")
+
+    def fuzz(session, inst_list):
+        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 have quit abnormally")
+    try:
+        ports = {}
+        ran = random.SystemRandom()
+        
+        logging.info("Enumerate the device 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 %s" % name)
+                continue
+            
+            logging.info("Fuzzing %s at 0x%x-0x%x" % (name, beg, end))
+            inst = []
+                     
+            # Read all ports
+            for port in range(beg, end+1):
+                inst.append(("read", [port]))
+                
+            # Outb with zero
+            for port in range(beg, end+1):
+                inst.append(("write", [port, 0]))
+                pass
+
+            # Random fuzzing 
+            for seq in range(fuzz_count * (end-beg+1)):
+                inst.append(("write", [ran.randint(beg, end), ran.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 d162cf8..01080bb 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -294,6 +294,8 @@ variants:
                 ksm_mode = "serial"
             - ksm_parallel:
                 ksm_mode = "parallel"
+    - iofuzz:
+        type = iofuzz
 
     # system_powerdown, system_reset and shutdown *must* be the last ones
     # defined (in this order), since the effect of such tests can leave

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux