All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/17] Patchset of network related subtests
@ 2010-08-23  8:51 Amos Kong
  2010-08-23  8:51 ` [PATCH v2 01/17] KVM-test: Add a new macaddress pool algorithm Amos Kong
                   ` (16 more replies)
  0 siblings, 17 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:51 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

This patchset contains 11 network related subtests, welcome more suggestions
about correctness, design and enhancement.
This is the version 2, thanks your comments.

---

Amos Kong (17):
      KVM-test: Add a new macaddress pool algorithm
      Add a get_ifname function
      KVM Test: Add a function get_interface_name() to kvm_test_utils.py
      KVM Test: Add a common ping module for network related tests
      KVM-test: Add a new subtest ping
      KVM-test: Add a subtest jumbo
      KVM-test: Add basic file transfer test
      KVM-test: Add a subtest of load/unload nic driver
      KVM-test: Add a subtest of nic promisc
      KVM-test: Add a subtest of multicast
      KVM-test: Add a subtest of pxe
      KVM-test: Add a subtest of changing mac address
      KVM-test: Add a subtest of netperf
      Add support of check if remote port free
      KVM-test: Improve vlan subtest
      Vlan: Replace extra_params '-snapshot' with image_snapshot
      KVM-test: Add subtest of testing offload by ethtool


 0 files changed, 0 insertions(+), 0 deletions(-)

-- 
Amos Kong

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 01/17] KVM-test: Add a new macaddress pool algorithm
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
@ 2010-08-23  8:51 ` Amos Kong
  2010-08-23  8:52 ` [PATCH v2 02/17] Add a get_ifname function Amos Kong
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:51 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

Old method uses the addresses in the config files which could lead serious
problem when multiple tests running in different hosts.
This patch adds a new macaddress pool algorithm, it generates the mac prefix
based on mac address of the host, and fix it to correspond to IEEE802.
When user have set the mac_prefix in the config file, we should use it instead
of the dynamic generated mac prefix.
Add a parameter like 'preserve_mac', to preserve the original mac address, for
things like migration.

MAC addresses are recorded into a dictionary 'address_pool' in following
format: {{'20100310-165222-Wt7l:0' : 'AE:9D:94:6A:9b:f9'},...}
  20100310-165222-Wt7l : instance attribute of VM
  0                    : index of NIC
  AE:9D:94:6A:9b:f9    : mac address
Use 'vm instance' + 'nic index' as the key, macaddress is the value.

Changs from v1:
- Use 'vm instance' + 'nic index' as the key of address_pool, address is value.
- Put 'mac_lock' and 'address_pool' to '/tmp', for sharing them to other
  autotest instances running on the same host.
- Change function names for less confusion.
- Do not copy 'vm.instance' in vm.clone()
- Split 'adding get_ifname function' to another patch

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Feng Yang <fyang@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py
index fb2d1c2..b019fc5 100644
--- a/client/tests/kvm/kvm_utils.py
+++ b/client/tests/kvm/kvm_utils.py
@@ -5,6 +5,7 @@ KVM test utility functions.
 """
 
 import time, string, random, socket, os, signal, re, logging, commands, cPickle
+import fcntl, shelve
 from autotest_lib.client.bin import utils
 from autotest_lib.client.common_lib import error, logging_config
 import kvm_subprocess
@@ -82,6 +83,79 @@ def get_sub_dict_names(dict, keyword):
 
 # Functions related to MAC/IP addresses
 
+def generate_mac_address(root_dir, instance_vm, nic_index, prefix='00:11:22:33:'):
+    """
+    Random generate a MAC address and add it to the MAC pool.
+
+    Try to generate macaddress based on the mac address prefix, add it to a
+    dictionary 'address_pool'.
+    key = VM instance + nic index, value = mac address
+    {['20100310-165222-Wt7l:0'] : 'AE:9D:94:6A:9b:f9'}
+
+    @param root_dir: Root dir for kvm
+    @param instance_vm: Here we use instance of vm
+    @param nic_index: The index of nic
+    @param prefix: Prefix of mac address
+    @Return: Return mac address.
+    """
+    lock_file = open("/tmp/mac_lock", 'w')
+    fcntl.lockf(lock_file.fileno() ,fcntl.LOCK_EX)
+    mac_pool = shelve.open("/tmp/address_pool", writeback=False)
+    found = False
+    key = "%s:%s" % (instance_vm, nic_index)
+
+    if mac_pool.get(key):
+        found = True
+        mac = mac_pool.get(key)
+
+    while not found:
+        suffix = "%02x:%02x" % (random.randint(0x00,0xfe),
+                                random.randint(0x00,0xfe))
+        mac = prefix + suffix
+        mac_list = mac.split(":")
+        # Clear multicast bit
+        mac_list[0] = int(mac_list[0],16) & 0xfe
+        # Set local assignment bit (IEEE802)
+        mac_list[0] = mac_list[0] | 0x02
+        mac_list[0] = "%02x" % mac_list[0]
+        mac = ":".join(mac_list)
+        if mac in [mac_pool.get(k) for k in mac_pool.keys()]:
+                continue
+        mac_pool[key] = mac
+        found = True
+    logging.debug("Generated mac addr %s " % mac)
+
+    mac_pool.close()
+    fcntl.lockf(lock_file.fileno(), fcntl.LOCK_UN)
+    lock_file.close()
+    return mac
+
+
+def free_mac_address(root_dir, instance_vm, nic_index):
+    """
+    Free mac address from address pool
+
+    @param root_dir: Root dir for kvm
+    @param instance_vm: Here we use instance attribute of vm
+    @param nic_index: The index of nic
+    """
+    lock_file = open("/tmp/mac_lock", 'w')
+    fcntl.lockf(lock_file.fileno() ,fcntl.LOCK_EX)
+    mac_pool = shelve.open("/tmp/address_pool", writeback=False)
+    key = "%s:%s" % (instance_vm, nic_index)
+    if not mac_pool or (not key in mac_pool.keys()):
+        logging.debug("Nic not present in the MAC pool, not modifying pool")
+        logging.debug("Key : %s" % key)
+        logging.debug("pool is %s" % mac_pool)
+    else:
+        logging.debug("Freeing mac addr %s" % mac_pool[key])
+        mac_pool.pop(key)
+
+    mac_pool.close()
+    fcntl.lockf(lock_file.fileno(), fcntl.LOCK_UN)
+    lock_file.close()
+
+
 def mac_str_to_int(addr):
     """
     Convert MAC address string to integer.
diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py
index bdc9aab..6812c98 100755
--- a/client/tests/kvm/kvm_vm.py
+++ b/client/tests/kvm/kvm_vm.py
@@ -5,7 +5,7 @@ Utility classes and functions to handle Virtual Machine creation using qemu.
 @copyright: 2008-2009 Red Hat Inc.
 """
 
-import time, socket, os, logging, fcntl, re, commands, glob
+import time, socket, os, logging, fcntl, re, commands, shelve, glob
 import kvm_utils, kvm_subprocess, kvm_monitor, rss_file_transfer
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
@@ -117,6 +117,7 @@ class VM:
         self.params = params
         self.root_dir = root_dir
         self.address_cache = address_cache
+        self.mac_prefix = params.get('mac_prefix')
         self.netdev_id = []
 
         # Find a unique identifier for this VM
@@ -126,8 +127,15 @@ class VM:
             if not glob.glob("/tmp/*%s" % self.instance):
                 break
 
+        if self.mac_prefix is None:
+            s, o = commands.getstatusoutput("ifconfig eth0")
+            if s == 0:
+                mac = re.findall("HWaddr (\S*)", o)[0]
+                self.mac_prefix = '00' + mac[8:] + ':'
+
 
-    def clone(self, name=None, params=None, root_dir=None, address_cache=None):
+    def clone(self, name=None, params=None, root_dir=None,
+                    address_cache=None, preserve_mac=True):
         """
         Return a clone of the VM object with optionally modified parameters.
         The clone is initially not alive and needs to be started using create().
@@ -138,6 +146,7 @@ class VM:
         @param params: Optional new VM creation parameters
         @param root_dir: Optional new base directory for relative filenames
         @param address_cache: A dict that maps MAC addresses to IP addresses
+        @param preserve_mac: Clone mac address or not.
         """
         if name is None:
             name = self.name
@@ -147,7 +156,20 @@ class VM:
             root_dir = self.root_dir
         if address_cache is None:
             address_cache = self.address_cache
-        return VM(name, params, root_dir, address_cache)
+        vm = VM(name, params, root_dir, address_cache)
+        if preserve_mac:
+            vlan = 0
+            for nic_name in kvm_utils.get_sub_dict_names(params, "nics"):
+                nic_params = kvm_utils.get_sub_dict(params, nic_name)
+                vm.set_macaddr(self.get_macaddr(vlan), vlan, True)
+                vlan += 1
+        return vm
+
+
+    def free_mac_addresses(self):
+        nic_num = len(kvm_utils.get_sub_dict_names(self.params, "nics"))
+        for i in range(nic_num):
+            kvm_utils.free_mac_address(self.root_dir, self.instance, i)
 
 
     def make_qemu_command(self, name=None, params=None, root_dir=None):
@@ -386,6 +408,13 @@ class VM:
             mac = None
             if "address_index" in nic_params:
                 mac = kvm_utils.get_mac_ip_pair_from_dict(nic_params)[0]
+                self.set_macaddr(mac=mac, nic_index=vlan)
+            else:
+                mac = kvm_utils.generate_mac_address(self.root_dir,
+                                                     self.instance,
+                                                     vlan,
+                                                     self.mac_prefix)
+
             qemu_cmd += add_nic(help, vlan, nic_params.get("nic_model"), mac,
                                 self.netdev_id[vlan])
             # Handle the '-net tap' or '-net user' part
@@ -749,11 +778,15 @@ class VM:
                         logging.debug("Shutdown command sent; waiting for VM "
                                       "to go down...")
                         if kvm_utils.wait_for(self.is_dead, 60, 1, 1):
-                            logging.debug("VM is down")
+                            logging.debug("VM is down, freeing mac address.")
+                            self.free_mac_addresses()
                             return
                     finally:
                         session.close()
 
+            # Free mac addresses
+            self.free_mac_addresses()
+
             if self.monitor:
                 # Try to destroy with a monitor command
                 logging.debug("Trying to kill VM with monitor command...")
@@ -879,10 +912,13 @@ class VM:
         nic_name = nics[index]
         nic_params = kvm_utils.get_sub_dict(self.params, nic_name)
         if nic_params.get("nic_mode") == "tap":
-            mac, ip = kvm_utils.get_mac_ip_pair_from_dict(nic_params)
+            mac = self.get_macaddr(index)
             if not mac:
                 logging.debug("MAC address unavailable")
                 return None
+            mac = mac.lower()
+            ip = None
+
             if not ip or nic_params.get("always_use_tcpdump") == "yes":
                 # Get the IP address from the cache
                 ip = self.address_cache.get(mac)
@@ -895,6 +931,7 @@ class VM:
                              for nic in nics]
                 macs = [kvm_utils.get_mac_ip_pair_from_dict(dict)[0]
                         for dict in nic_dicts]
+                macs.append(mac)
                 if not kvm_utils.verify_ip_address_ownership(ip, macs):
                     logging.debug("Could not verify MAC-IP address mapping: "
                                   "%s ---> %s" % (mac, ip))
@@ -923,6 +960,42 @@ class VM:
                              "redirected" % port)
             return self.redirs.get(port)
 
+    def get_macaddr(self, nic_index=0):
+        """
+        Return the macaddr of guest nic.
+
+        @param nic_index: Index of the NIC
+        """
+        mac_pool = shelve.open("/tmp/address_pool", writeback=False)
+        key = "%s:%s" % (self.instance, nic_index)
+        if key in mac_pool.keys():
+            return mac_pool[key]
+        else:
+            return None
+
+    def set_macaddr(self, mac, nic_index=0, shareable=False):
+        """
+        Set mac address for guest. Note: It just update address pool.
+
+        @param mac: address will set to guest
+        @param nic_index: Index of the NIC
+        @param shareable: Where VM can share mac with other VM or not.
+        """
+        lock_file = open("/tmp/mac_lock", 'w')
+        fcntl.lockf(lock_file.fileno() ,fcntl.LOCK_EX)
+        mac_pool = shelve.open("/tmp/address_pool", writeback=False)
+        key = "%s:%s" % (self.instance, nic_index)
+
+        if not mac in [mac_pool[i] for i in mac_pool.keys()]:
+            mac_pool[key] = mac
+        else:
+            if shareable:
+                mac_pool[key] = mac
+            else:
+                logging.error("Mac address already be used!")
+        mac_pool.close()
+        fcntl.lockf(lock_file.fileno(), fcntl.LOCK_UN)
+        lock_file.close()
 
     def get_pid(self):
         """
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index cb35f5e..26760f6 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -54,7 +54,7 @@ guest_port_remote_shell = 22
 nic_mode = user
 #nic_mode = tap
 nic_script = scripts/qemu-ifup
-address_index = 0
+#address_index = 0
 run_tcpdump = yes
 
 # Misc


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 02/17] Add a get_ifname function
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
  2010-08-23  8:51 ` [PATCH v2 01/17] KVM-test: Add a new macaddress pool algorithm Amos Kong
@ 2010-08-23  8:52 ` Amos Kong
  2010-08-23  8:52 ` [PATCH v2 03/17] KVM Test: Add a function get_interface_name() to kvm_test_utils.py Amos Kong
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:52 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

It's more clear to use 'nic_mode + nic_index + vnc_port' than 'tap0',
It's also unique for one guest.

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py
index 6812c98..e4f216c 100755
--- a/client/tests/kvm/kvm_vm.py
+++ b/client/tests/kvm/kvm_vm.py
@@ -428,7 +428,7 @@ class VM:
             if tftp:
                 tftp = kvm_utils.get_path(root_dir, tftp)
             qemu_cmd += add_net(help, vlan, nic_params.get("nic_mode", "user"),
-                                nic_params.get("nic_ifname"),
+                                self.get_ifname(vlan),
                                 script, downscript, tftp,
                                 nic_params.get("bootp"), redirs,
                                 self.netdev_id[vlan])
@@ -960,6 +960,24 @@ class VM:
                              "redirected" % port)
             return self.redirs.get(port)
 
+    def get_ifname(self, nic_index=0):
+        """
+        Return the ifname of tap device for the guest nic.
+
+        The vnc_port is unique for each VM, nic_index is unique for each nic
+        of one VM, it can avoid repeated ifname.
+
+        @param nic_index: Index of the NIC
+        """
+        nics = kvm_utils.get_sub_dict_names(self.params, "nics")
+        nic_name = nics[nic_index]
+        nic_params = kvm_utils.get_sub_dict(self.params, nic_name)
+        if nic_params.get("nic_ifname"):
+            return nic_params.get("nic_ifname")
+        else:
+            return "%s_%s_%s" % (nic_params.get("nic_model"),
+                                 nic_index, self.vnc_port)
+
     def get_macaddr(self, nic_index=0):
         """
         Return the macaddr of guest nic.


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 03/17] KVM Test: Add a function get_interface_name() to kvm_test_utils.py
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
  2010-08-23  8:51 ` [PATCH v2 01/17] KVM-test: Add a new macaddress pool algorithm Amos Kong
  2010-08-23  8:52 ` [PATCH v2 02/17] Add a get_ifname function Amos Kong
@ 2010-08-23  8:52 ` Amos Kong
  2010-08-23  8:52 ` [PATCH v2 04/17] KVM Test: Add a common ping module for network related tests Amos Kong
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:52 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

The function get_interface_name is used to get the interface name of linux
guest through the macaddress of specified macaddress.

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/kvm_test_utils.py b/client/tests/kvm/kvm_test_utils.py
index 53c11ae..8cd7acd 100644
--- a/client/tests/kvm/kvm_test_utils.py
+++ b/client/tests/kvm/kvm_test_utils.py
@@ -481,3 +481,20 @@ def run_autotest(vm, session, control_path, timeout, outputdir):
             e_msg = ("Tests %s failed during control file execution" %
                      " ".join(bad_results))
         raise error.TestFail(e_msg)
+
+
+def get_linux_ifname(session, mac_address):
+    """
+    Return the interface name through the mac address.
+
+    @param session: session to the virtual machine
+    @mac_address: the macaddress of nic
+    """
+    output = session.get_command_output("ifconfig -a")
+
+    try:
+        ethname = re.findall("(\w+)\s+Link.*%s" % mac_address, output,
+                             re.IGNORECASE)[0]
+        return ethname
+    except:
+        return None


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 04/17] KVM Test: Add a common ping module for network related tests
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (2 preceding siblings ...)
  2010-08-23  8:52 ` [PATCH v2 03/17] KVM Test: Add a function get_interface_name() to kvm_test_utils.py Amos Kong
@ 2010-08-23  8:52 ` Amos Kong
  2010-08-23  8:52 ` [PATCH v2 05/17] KVM-test: Add a new subtest ping Amos Kong
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:52 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

The kvm_net_utils.py is a just a place that wraps common network
related commands which is used to do the network-related tests.
Use -1 as the packet ratio for loss analysis.
Use quiet mode when doing the flood ping.

Changes from v1:
- Use None to indicate that the session should be local in raw_ping
- Use session.sendline("\003") to send (ctrl+c) signal
- Use None to indicate that the session should be local
- Fix of coding style

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/kvm_test_utils.py b/client/tests/kvm/kvm_test_utils.py
index 8cd7acd..6a93b72 100644
--- a/client/tests/kvm/kvm_test_utils.py
+++ b/client/tests/kvm/kvm_test_utils.py
@@ -21,7 +21,7 @@ More specifically:
 @copyright: 2008-2009 Red Hat Inc.
 """
 
-import time, os, logging, re, commands
+import time, os, logging, re, commands, signal
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
 import kvm_utils, kvm_vm, kvm_subprocess, scan_results
@@ -498,3 +498,113 @@ def get_linux_ifname(session, mac_address):
         return ethname
     except:
         return None
+
+
+def get_loss_ratio(output):
+    """
+    Get the packet loss ratio from the output of ping
+
+    @param output
+    """
+    try:
+        return int(re.findall('(\d+)% packet loss', output)[0])
+    except IndexError:
+        logging.debug(output)
+        return -1
+
+
+def raw_ping(command, timeout, session, output_func):
+    """
+    Low-level ping command execution.
+
+    @param command: ping command
+    @param timeout: timeout of the ping command
+    @param session: local executon hint or session to execute the ping command
+    """
+    if session is None:
+        process = kvm_subprocess.run_bg(command, output_func=output_func,
+                                        timeout=timeout)
+
+        # Send SIGINT signal to notify the timeout of running ping process,
+        # Because ping have the ability to catch the SIGINT signal so we can
+        # always get the packet loss ratio even if timeout.
+        if process.is_alive():
+            kvm_utils.kill_process_tree(process.get_pid(), signal.SIGINT)
+
+        status = process.get_status()
+        output = process.get_output()
+
+        process.close()
+        return status, output
+    else:
+        session.sendline(command)
+        status, output = session.read_up_to_prompt(timeout=timeout,
+                                                   print_func=output_func)
+        if not status:
+            # Send ctrl+c (SIGINT) through ssh session
+            session.send("\003")
+            status, output2 = session.read_up_to_prompt(print_func=output_func)
+            output += output2
+            if not status:
+                # We also need to use this session to query the return value
+                session.send("\003")
+
+        session.sendline(session.status_test_command)
+        s2, o2 = session.read_up_to_prompt()
+        if not s2:
+            status = -1
+        else:
+            try:
+                status = int(re.findall("\d+", o2)[0])
+            except:
+                status = -1
+
+        return status, output
+
+
+def ping(dest=None, count=None, interval=None, interface=None,
+         packetsize=None, ttl=None, hint=None, adaptive=False,
+         broadcast=False, flood=False, timeout=0,
+         output_func=logging.debug, session=None):
+    """
+    Wrapper of ping.
+
+    @param dest: destination address
+    @param count: count of icmp packet
+    @param interval: interval of two icmp echo request
+    @param interface: specified interface of the source address
+    @param packetsize: packet size of icmp
+    @param ttl: ip time to live
+    @param hint: path mtu discovery hint
+    @param adaptive: adaptive ping flag
+    @param broadcast: broadcast ping flag
+    @param flood: flood ping flag
+    @param timeout: timeout for the ping command
+    @param output_func: function used to log the result of ping
+    @param session: local executon hint or session to execute the ping command
+    """
+    if dest is not None:
+        command = "ping %s " % dest
+    else:
+        command = "ping localhost "
+    if count is not None:
+        command += " -c %s" % count
+    if interval is not None:
+        command += " -i %s" % interval
+    if interface is not None:
+        command += " -I %s" % interface
+    if packetsize is not None:
+        command += " -s %s" % packetsize
+    if ttl is not None:
+        command += " -t %s" % ttl
+    if hint is not None:
+        command += " -M %s" % hint
+    if adaptive:
+        command += " -A"
+    if broadcast:
+        command += " -b"
+    if flood:
+        command += " -f -q"
+        output_func = None
+
+    return raw_ping(command, timeout, session, output_func)


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 05/17] KVM-test: Add a new subtest ping
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (3 preceding siblings ...)
  2010-08-23  8:52 ` [PATCH v2 04/17] KVM Test: Add a common ping module for network related tests Amos Kong
@ 2010-08-23  8:52 ` Amos Kong
  2010-08-23  8:52 ` [PATCH v2 06/17] KVM-test: Add a subtest jumbo Amos Kong
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:52 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

This test use ping to check the virtual nics, it contains two kinds of test:
1. Packet loss ratio test, ping the guest with different size of packets.
2. Stress test, flood ping guest then use ordinary ping to test the network.

We could not raise an error when flood ping failed, it's too strict.
But we must check the ping result before/after flood-ping.
The interval and packet size could be configurated through tests_base.cfg

Changes from v1:
- Improve error message

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/ping.py b/client/tests/kvm/tests/ping.py
new file mode 100644
index 0000000..07c1d3d
--- /dev/null
+++ b/client/tests/kvm/tests/ping.py
@@ -0,0 +1,71 @@
+import logging
+from autotest_lib.client.common_lib import error
+import kvm_test_utils
+
+
+def run_ping(test, params, env):
+    """
+    Ping the guest with different size of packets.
+
+    Packet Loss Test:
+    1) Ping the guest with different size/interval of packets.
+    Stress Test:
+    1) Flood ping the guest.
+    2) Check if the network is still usable.
+
+    @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)
+
+    counts = params.get("ping_counts", 100)
+    flood_minutes = float(params.get("flood_minutes", 10))
+    nics = params.get("nics").split()
+    strict_check = params.get("strict_check", "no") == "yes"
+
+    packet_size = [0, 1, 4, 48, 512, 1440, 1500, 1505, 4054, 4055, 4096, 4192,
+                   8878, 9000, 32767, 65507]
+
+    try:
+        for i, nic in enumerate(nics):
+            ip = vm.get_address(i)
+            if not ip:
+                logging.error("Could not get the ip of nic index %d" % i)
+                continue
+
+            for size in packet_size:
+                logging.info("Ping with packet size %s" % size)
+                status, output = kvm_test_utils.ping(ip, 10,
+                                                    packetsize=size,
+                                                    timeout=20)
+                if strict_check:
+                    ratio = kvm_test_utils.get_loss_ratio(output)
+                    if ratio != 0:
+                        raise error.TestFail(" Loss ratio is %s for packet size"
+                                             " %s" % (ratio, size))
+                else:
+                    if status != 0:
+                        raise error.TestFail(" Ping failed, status: %s,"
+                                             " output: %s" % (status, output))
+
+            logging.info("Flood ping test")
+            kvm_test_utils.ping(ip, None, flood=True, output_func=None,
+                               timeout=flood_minutes * 60)
+
+            logging.info("Final ping test")
+            status, output = kvm_test_utils.ping(ip, counts,
+                                                timeout=float(counts) * 1.5)
+            if strict_check:
+                ratio = kvm_test_utils.get_loss_ratio(output)
+                if ratio != 0:
+                    raise error.TestFail(" Ping failed, status: %s,"
+                                         " output: %s" % (status, output))
+            else:
+                if status != 0:
+                    raise error.TestFail(" Ping returns non-zero value %s" %
+                                         output)
+    finally:
+        session.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index 26760f6..d4b0ed0 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -353,6 +353,11 @@ variants:
         kill_vm_gracefully_vm2 = no
         address_index_vm2 = 1
 
+    - ping: install setup unattended_install.cdrom
+        type = ping
+        counts = 100
+        flood_minutes = 10
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 06/17] KVM-test: Add a subtest jumbo
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (4 preceding siblings ...)
  2010-08-23  8:52 ` [PATCH v2 05/17] KVM-test: Add a new subtest ping Amos Kong
@ 2010-08-23  8:52 ` Amos Kong
  2010-08-23  8:52 ` [PATCH v2 07/17] KVM-test: Add basic file transfer test Amos Kong
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:52 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

According to different nic model set different MTU for it. And ping from guest
to host, to see whether tested size can be received by host.

Changes from v1:
- Make standard of lost ratio can be configured

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/jumbo.py b/client/tests/kvm/tests/jumbo.py
new file mode 100644
index 0000000..0d7acf0
--- /dev/null
+++ b/client/tests/kvm/tests/jumbo.py
@@ -0,0 +1,129 @@
+import logging, commands, random
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+import kvm_test_utils, kvm_utils
+
+def run_jumbo(test, params, env):
+    """
+    Test the RX jumbo frame function of vnics:
+
+    1) boot the vm
+    2) change the MTU of guest nics and host taps depending on the nic model
+    3) add the static arp entry for guest nic
+    4) wait for the MTU ok
+    5) verify the patch mtu using ping
+    6) ping the guest with large frames
+    7) increment size ping
+    8) flood ping the guest with large frames
+    9) verify the path mtu
+    10) recover the mtu
+
+    @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)
+    mtu = params.get("mtu", "1500")
+    flood_time = params.get("flood_time", "300")
+    max_icmp_pkt_size = int(mtu) - 28
+
+    ifname = vm.get_ifname(0)
+    ip = vm.get_address(0)
+    if ip is None:
+        raise error.TestError("Could not get the ip address")
+
+    try:
+        # Environment preparation
+        ethname = kvm_test_utils.get_linux_ifname(session, vm.get_macaddr(0))
+
+        logging.info("Changing the mtu of guest ...")
+        guest_mtu_cmd = "ifconfig %s mtu %s" % (ethname , mtu)
+        s, o = session.get_command_status_output(guest_mtu_cmd)
+        if s != 0:
+            logging.error(o)
+            raise error.TestError("Fail to set the mtu of guest nic: %s"
+                                  % ethname)
+
+        logging.info("Chaning the mtu of host tap ...")
+        host_mtu_cmd = "ifconfig %s mtu %s" % (ifname, mtu)
+        utils.run(host_mtu_cmd)
+
+        logging.info("Add a temporary static arp entry ...")
+        arp_add_cmd = "arp -s %s %s -i %s" % (ip, vm.get_macaddr(0), ifname)
+        utils.run(arp_add_cmd)
+
+        def is_mtu_ok():
+            s, o = kvm_test_utils.ping(ip, 1, interface=ifname,
+                                      packetsize=max_icmp_pkt_size,
+                                      hint="do", timeout=2)
+            return s == 0
+
+        def verify_mtu():
+            logging.info("Verify the path mtu")
+            s, o = kvm_test_utils.ping(ip, 10, interface=ifname,
+                                      packetsize=max_icmp_pkt_size,
+                                      hint="do", timeout=15)
+            if s != 0 :
+                logging.error(o)
+                raise error.TestFail("Path MTU is not as expected")
+            if kvm_test_utils.get_loss_ratio(o) != 0:
+                logging.error(o)
+                raise error.TestFail("Packet loss ratio during mtu verification"
+                                     " is not zero")
+
+        def flood_ping():
+            logging.info("Flood with large frames")
+            kvm_test_utils.ping(ip, interface=ifname,
+                               packetsize=max_icmp_pkt_size,
+                               flood=True, timeout=float(flood_time))
+
+        def large_frame_ping(count=100):
+            logging.info("Large frame ping")
+            s, o = kvm_test_utils.ping(ip, count, interface=ifname,
+                                      packetsize=max_icmp_pkt_size,
+                                      timeout=float(count) * 2)
+            ratio = kvm_test_utils.get_loss_ratio(o)
+            if ratio != 0:
+                raise error.TestFail("Loss ratio of large frame ping is %s"
+                                     % ratio)
+
+        def size_increase_ping(step=random.randrange(90, 110)):
+            logging.info("Size increase ping")
+            for size in range(0, max_icmp_pkt_size + 1, step):
+                logging.info("Ping %s with size %s" % (ip, size))
+                s, o = kvm_test_utils.ping(ip, 1, interface=ifname,
+                                          packetsize=size,
+                                          hint="do", timeout=1)
+                if s != 0:
+                    s, o = kvm_test_utils.ping(ip, 10, interface=ifname,
+                                              packetsize=size,
+                                              adaptive=True, hint="do",
+                                              timeout=20)
+
+                    if kvm_test_utils.get_loss_ratio(o) > int(params.get(
+                                                      "fail_ratio", 50)):
+                        raise error.TestFail("ping loss ratio is greater "
+                                             "than 50% for size %s" % size)
+
+        logging.info("Waiting for the MTU to be OK")
+        if not kvm_utils.wait_for(is_mtu_ok, 10, 0, 1):
+            logging.debug(commands.getoutput("ifconfig -a"))
+            raise error.TestError("10 seconds elapsed while the mtu is not"
+                                  " as expected")
+
+        # Functional Test
+        verify_mtu()
+        large_frame_ping()
+        size_increase_ping()
+
+        # Stress test
+        flood_ping()
+        verify_mtu()
+
+    finally:
+        # Environment clean
+        session.close()
+        logging.info("Removing the temporary arp entry")
+        utils.run("arp -d %s -i %s" % (ip, ifname))
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index d4b0ed0..1b80cdd 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -358,6 +358,9 @@ variants:
         counts = 100
         flood_minutes = 10
 
+    - jumbo: install setup unattended_install.cdrom
+        type = jumbo
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'
@@ -493,10 +496,16 @@ variants:
 variants:
     - @rtl8139:
         nic_model = rtl8139
+        jumbo:
+            mtu = 1500
     - e1000:
         nic_model = e1000
+        jumbo:
+            mtu = 16110
     - virtio:
         nic_model = virtio
+        jumbo:
+            mtu = 65520
 
 
 # Guests
@@ -1050,7 +1059,7 @@ variants:
 
     # Windows section
     - @Windows:
-        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks)
+        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo
         shutdown_command = shutdown /s /f /t 0
         reboot_command = shutdown /r /f /t 0
         status_test_command = echo %errorlevel%


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 07/17] KVM-test: Add basic file transfer test
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (5 preceding siblings ...)
  2010-08-23  8:52 ` [PATCH v2 06/17] KVM-test: Add a subtest jumbo Amos Kong
@ 2010-08-23  8:52 ` Amos Kong
  2010-08-23  8:52 ` [PATCH v2 08/17] KVM-test: Add a subtest of load/unload nic driver Amos Kong
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:52 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

This test is the basic test of transfering file between host and guest. Try to
transfer a large file from host to guest, and transfer it back to host, then
compare the files by diff command.
The default file size is 4000M, scp timeout is 1000s. It means if the average
speed is less than 4M/s, this test will be fail.
We can extend this test by using another disk later, then we can transfer larger
files without the limit of first disk size.

Changes from v1:
- Use md5 to verify the integrity of files
- Try to use autotest API, such as, utils.system()

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/file_transfer.py b/client/tests/kvm/tests/file_transfer.py
new file mode 100644
index 0000000..c9a3476
--- /dev/null
+++ b/client/tests/kvm/tests/file_transfer.py
@@ -0,0 +1,55 @@
+import logging, commands, re
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+import kvm_utils, kvm_test_utils
+
+def run_file_transfer(test, params, env):
+    """
+    Test ethrnet device function by ethtool
+
+    1) Boot up a virtual machine
+    2) Create a large file by dd on host
+    3) Copy this file from host to guest
+    4) Copy this file from guest to host
+    5) Check if file transfers good
+
+    @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"))
+    timeout=int(params.get("login_timeout", 360))
+    logging.info("Trying to log into guest '%s' by serial", vm.name)
+    session = kvm_utils.wait_for(lambda: vm.serial_login(),
+                                 timeout, 0, step=2)
+    if not session:
+        raise error.TestFail("Could not log into guest '%s'" % vm.name)
+
+    dir = test.tmpdir
+    scp_timeout = int(params.get("scp_timeout"))
+    cmd = "dd if=/dev/urandom of=%s/a.out bs=1M count=%d" %  (dir, int(
+                                         params.get("filesize", 4000)))
+    try:
+        logging.info("Create file by dd command on host, cmd: %s" % cmd)
+        utils.run(cmd)
+
+        logging.info("Transfer file from host to guest")
+        if not vm.copy_files_to("%s/a.out" % dir, "/tmp/b.out",
+                                                        timeout=scp_timeout):
+            raise error.TestFail("Fail to transfer file from host to guest")
+
+        logging.info("Transfer file from guest to host")
+        if not vm.copy_files_from("/tmp/b.out", "%s/c.out" % dir,
+                                                        timeout=scp_timeout):
+            raise error.TestFail("Fail to transfer file from guest to host")
+
+        logging.debug(commands.getoutput("ls -l %s/[ac].out" % dir))
+        md5_orig = utils.hash_file("%s/a.out" % dir, method="md5")
+        md5_new = utils.hash_file("%s/c.out" % dir, method="md5")
+
+        if md5_orig != md5_new:
+            raise error.TestFail("File changed after transfer")
+    finally:
+        session.get_command_status("rm -f /tmp/b.out")
+        utils.run("rm -f %s/[ac].out" % dir)
+        session.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index 1b80cdd..bea77ed 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -361,6 +361,11 @@ variants:
     - jumbo: install setup unattended_install.cdrom
         type = jumbo
 
+    - file_transfer: install setup unattended_install.cdrom
+        type = file_transfer
+        filesize = 4000
+        scp_timeout = 1000
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'
@@ -1059,7 +1064,7 @@ variants:
 
     # Windows section
     - @Windows:
-        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo
+        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer
         shutdown_command = shutdown /s /f /t 0
         reboot_command = shutdown /r /f /t 0
         status_test_command = echo %errorlevel%


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 08/17] KVM-test: Add a subtest of load/unload nic driver
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (6 preceding siblings ...)
  2010-08-23  8:52 ` [PATCH v2 07/17] KVM-test: Add basic file transfer test Amos Kong
@ 2010-08-23  8:52 ` Amos Kong
  2010-08-23  8:53 ` [PATCH v2 09/17] KVM-test: Add a subtest of nic promisc Amos Kong
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:52 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

Repeatedly load/unload nic driver, try to transfer file between guest and host
by threads at the same time, and check the md5sum.

Changes from v1:
- Use a new method to get nic driver name
- Use utils.hash_file() to get md5sum

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/nicdriver_unload.py b/client/tests/kvm/tests/nicdriver_unload.py
new file mode 100644
index 0000000..4ddaa27
--- /dev/null
+++ b/client/tests/kvm/tests/nicdriver_unload.py
@@ -0,0 +1,115 @@
+import logging, threading, os
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+import kvm_utils, kvm_test_utils
+
+def run_nicdriver_unload(test, params, env):
+    """
+    Test nic driver
+
+    1) Boot a vm
+    2) Get the nic driver name
+    3) Repeatedly unload/load nic driver
+    4) Multi-session TCP transfer on test interface
+    5) Check the test interface should still work
+
+    @param test: KVM test object
+    @param params: Dictionary with the test parameters
+    @param env: Dictionary with test environment.
+    """
+    timeout = int(params.get("login_timeout", 360))
+    vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
+    session = kvm_test_utils.wait_for_login(vm, timeout=timeout)
+    logging.info("Trying to log into guest '%s' by serial", vm.name)
+    session2 = kvm_utils.wait_for(lambda: vm.serial_login(),
+                                  timeout, 0, step=2)
+    if not session2:
+        raise error.TestFail("Could not log into guest '%s'" % vm.name)
+
+    ethname = kvm_test_utils.get_linux_ifname(session, vm.get_macaddr(0))
+    temp_path = "/sys/class/net/%s/device/driver" % (ethname)
+    if os.path.islink(temp_path):
+        driver = os.path.split(os.path.realpath(temp_path))[-1]
+    else:
+        raise error.TestError("Could not find driver name")
+    logging.info("driver is %s" % driver)
+
+    class ThreadScp(threading.Thread):
+        def run(self):
+            remote_file = '/tmp/' + self.getName()
+            file_list.append(remote_file)
+            ret = vm.copy_files_to(file_name, remote_file, timeout=scp_timeout)
+            if ret:
+                logging.debug("File %s was transfered successfuly", remote_file)
+            else:
+                logging.debug("Failed to transfer file %s", remote_file)
+
+    def compare(origin_file, receive_file):
+        cmd = "md5sum %s"
+        check_sum1 = utils.hash_file(origin_file, method="md5")
+        s, output2 = session.get_command_status_output(cmd % receive_file)
+        if s != 0:
+            logging.error("Could not get md5sum of receive_file")
+            return False
+        check_sum2 = output2.strip().split()[0]
+        logging.debug("original file md5: %s, received file md5: %s"
+                      % (check_sum1, check_sum2))
+        if check_sum1 != check_sum2:
+            logging.error("md5sum doesn't match")
+            return False
+        return True
+
+    #produce sized file in host
+    file_size = params.get("file_size")
+    file_name = "/tmp/nicdriver_unload_file"
+    cmd = "dd if=/dev/urandom of=%s bs=%sM count=1"
+    utils.system(cmd % (file_name, file_size))
+
+    file_list = []
+    connect_time = params.get("connect_time")
+    scp_timeout = int(params.get("scp_timeout"))
+    thread_num = int(params.get("thread_num"))
+    unload_load_cmd = ("sleep %s && ifconfig %s down && modprobe -r %s && "
+                       "sleep 1 && modprobe %s && ifconfig %s up" %
+                       (connect_time, ethname, driver, driver, ethname))
+    pid = os.fork()
+    if pid != 0:
+        logging.info("unload/load nic driver repeatedly in guest...")
+        while True:
+            logging.debug("Try to unload/load nic drive once")
+            if session2.get_command_status(unload_load_cmd, timeout=120) != 0:
+                session.get_command_output("rm -rf /tmp/Thread-*")
+                raise error.TestFail("Unload/load nic driver failed")
+            pid, s = os.waitpid(pid, os.WNOHANG)
+            status = os.WEXITSTATUS(s)
+            if (pid, status) != (0, 0):
+                logging.debug("Child process ending")
+                break
+    else:
+        logging.info("Multi-session tcp data transfer")
+        threads = []
+        for i in range(thread_num):
+            t = ThreadScp()
+            t.start()
+            threads.append(t)
+        for t in threads:
+            t.join(timeout = scp_timeout)
+        os._exit(0)
+
+    session2.close()
+
+    try:
+        logging.info("Check md5sum for received files in multi-session")
+        for f in file_list:
+            if not compare(file_name, f):
+                raise error.TestFail("Fail to compare (guest)file %s" % f)
+
+        logging.info("Test nic function after load/unload")
+        if not vm.copy_files_to(file_name, file_name):
+            raise error.TestFail("Fail to copy file from host to guest")
+        if not compare(file_name, file_name):
+            raise error.TestFail("Test nic function after load/unload fail")
+
+    finally:
+        session.get_command_output("rm -rf /tmp/Thread-*")
+        session.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index bea77ed..7e1601c 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -366,6 +366,14 @@ variants:
         filesize = 4000
         scp_timeout = 1000
 
+    - nicdriver_unload:  install setup unattended_install.cdrom
+        type = nicdriver_unload
+        nic_mode = tap
+        file_size = 100
+        connect_time = 4
+        scp_timeout = 300
+        thread_num = 10
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'
@@ -1064,7 +1072,7 @@ variants:
 
     # Windows section
     - @Windows:
-        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer
+        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload
         shutdown_command = shutdown /s /f /t 0
         reboot_command = shutdown /r /f /t 0
         status_test_command = echo %errorlevel%


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 09/17] KVM-test: Add a subtest of nic promisc
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (7 preceding siblings ...)
  2010-08-23  8:52 ` [PATCH v2 08/17] KVM-test: Add a subtest of load/unload nic driver Amos Kong
@ 2010-08-23  8:53 ` Amos Kong
  2010-08-23  8:53 ` [PATCH v2 10/17] KVM-test: Add a subtest of multicast Amos Kong
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:53 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

This test mainly covers TCP sent from host to guest and from guest to host
with repeatedly turn on/off NIC promiscuous mode.

Changes from v1:
- Don't abruptly fail the whole test if we get a failure for a single size

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/nic_promisc.py b/client/tests/kvm/tests/nic_promisc.py
new file mode 100644
index 0000000..b75a1cd
--- /dev/null
+++ b/client/tests/kvm/tests/nic_promisc.py
@@ -0,0 +1,100 @@
+import logging
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+import kvm_utils, kvm_test_utils
+
+def run_nic_promisc(test, params, env):
+    """
+    Test nic driver in promisc mode:
+
+    1) Boot up a guest
+    2) Repeatedly enable/disable promiscuous mode in guest
+    3) TCP data transmission from host to guest, and from guest to host,
+       with 1/1460/65000/100000000 bytes payloads
+    4) Clean temporary files
+    5) Stop enable/disable promiscuous mode change
+
+    @param test: kvm test object
+    @param params: Dictionary with the test parameters
+    @param env: Dictionary with test environment
+    """
+    timeout = int(params.get("login_timeout", 360))
+    vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
+    session = kvm_test_utils.wait_for_login(vm, timeout=timeout)
+    logging.info("Trying to log into guest '%s' by serial", vm.name)
+    session2 = kvm_utils.wait_for(lambda: vm.serial_login(),
+                                  timeout, 0, step=2)
+    if not session2:
+        raise error.TestFail("Could not log into guest '%s'" % vm.name)
+
+    def compare(filename):
+        cmd = "md5sum %s" % filename
+        md5_host = utils.hash_file(filename, method="md5")
+        rc_guest, md5_guest = session.get_command_status_output(cmd)
+        if rc_guest:
+            logging.debug("Could not get MD5 hash for file %s on guest,"
+                          "output: %s", filename, md5_guest)
+            return False
+        md5_guest = md5_guest.split()[0]
+        if md5_host != md5_guest:
+            logging.error("MD5 hash mismatch between file %s "
+                          "present on guest and on host", filename)
+            logging.error("MD5 hash for file on guest: %s,"
+                          "MD5 hash for file on host: %s", md5_host, md5_guest)
+            return False
+        return True
+
+    ethname = kvm_test_utils.get_linux_ifname(session, vm.get_macaddr(0))
+    set_promisc_cmd = ("ip link set %s promisc on; sleep 0.01;"
+                       "ip link set %s promisc off; sleep 0.01"
+                       % (ethname, ethname))
+    logging.info("Set promisc change repeatedly in guest")
+    session2.sendline("while true; do %s; done" % set_promisc_cmd)
+
+    dd_cmd = "dd if=/dev/urandom of=%s bs=%d count=1"
+    filename = "/tmp/nic_promisc_file"
+    file_size = params.get("file_size", "1, 1460, 65000, 100000000").split(",")
+    success_counter = 0
+    try:
+        for size in file_size:
+            logging.info("Create %s bytes file on host" % size)
+            utils.run(dd_cmd % (filename, int(size)))
+
+            logging.info("Transfer file from host to guest")
+            if not vm.copy_files_to(filename, filename):
+                logging.error("File transfer failed")
+                continue
+            if not compare(filename):
+                logging.error("Compare file failed")
+                continue
+            else:
+                success_counter += 1
+
+            logging.info("Create %s bytes file on guest" % size)
+            if session.get_command_status(dd_cmd % (filename, int(size)),
+                                                    timeout=100) != 0:
+                logging.error("Create file on guest failed")
+                continue
+
+            logging.info("Transfer file from guest to host")
+            if not vm.copy_files_from(filename, filename):
+                logging.error("File transfer failed")
+                continue
+            if not compare(filename):
+                logging.error("Compare file failed")
+                continue
+            else:
+                success_counter += 1
+
+            logging.info("Clean temporary files")
+            cmd = "rm -f %s" % filename
+            utils.run(cmd)
+            session.get_command_status(cmd)
+    finally:
+        logging.info("Restore the %s to the nonpromisc mode" % ethname)
+        session2.close()
+        session.get_command_status("ip link set %s promisc off" % ethname)
+        session.close()
+    if success_counter != 2 * len(file_size):
+        raise error.TestFail("Some tests failed, succss_ratio : %s/%s"
+                             % (success_counter, len(file_size)))
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index 7e1601c..89ec4b0 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -374,6 +374,10 @@ variants:
         scp_timeout = 300
         thread_num = 10
 
+    - nic_promisc:  install setup unattended_install.cdrom
+        type = nic_promisc
+        file_size = 1, 1460, 65000, 100000000
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'
@@ -1072,7 +1076,7 @@ variants:
 
     # Windows section
     - @Windows:
-        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload
+        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc
         shutdown_command = shutdown /s /f /t 0
         reboot_command = shutdown /r /f /t 0
         status_test_command = echo %errorlevel%


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 10/17] KVM-test: Add a subtest of multicast
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (8 preceding siblings ...)
  2010-08-23  8:53 ` [PATCH v2 09/17] KVM-test: Add a subtest of nic promisc Amos Kong
@ 2010-08-23  8:53 ` Amos Kong
  2010-08-23  8:53 ` [PATCH v2 11/17] KVM-test: Add a subtest of pxe Amos Kong
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:53 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

Use 'ping' to test send/recive multicat packets. Flood ping test is also added.
Limit guest network as 'bridge' mode, because multicast packets could not be
transmitted to guest when using 'user' network.
Add join_mcast.py for joining machine into multicast groups.

Changes from v1:
- Just flush the firewall rules with iptables -F

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/scripts/join_mcast.py b/client/tests/kvm/scripts/join_mcast.py
new file mode 100755
index 0000000..0d90e5c
--- /dev/null
+++ b/client/tests/kvm/scripts/join_mcast.py
@@ -0,0 +1,29 @@
+import socket, struct, os, signal, sys
+# this script is used to join machine into multicast groups
+# author: Amos Kong <akong@redhat.com>
+
+if len(sys.argv) < 4:
+    print """%s [mgroup_count] [prefix] [suffix]
+    mgroup_count: count of multicast addresses
+    prefix: multicast address prefix
+    suffix: multicast address suffix""" % sys.argv[0]
+    sys.exit()
+
+mgroup_count = int(sys.argv[1])
+prefix = sys.argv[2]
+suffix = int(sys.argv[3])
+
+s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+for i in range(mgroup_count):
+    mcast = prefix + "." + str(suffix + i)
+    try:
+        mreq = struct.pack("4sl", socket.inet_aton(mcast), socket.INADDR_ANY)
+        s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
+    except:
+        s.close()
+        print "Could not join multicast: %s" % mcast
+        raise
+
+print "join_mcast_pid:%s" % os.getpid()
+os.kill(os.getpid(), signal.SIGSTOP)
+s.close()
diff --git a/client/tests/kvm/tests/multicast.py b/client/tests/kvm/tests/multicast.py
new file mode 100644
index 0000000..d0084f1
--- /dev/null
+++ b/client/tests/kvm/tests/multicast.py
@@ -0,0 +1,72 @@
+import logging, os, re
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+import kvm_test_utils
+
+
+def run_multicast(test, params, env):
+    """
+    Test multicast function of nic (rtl8139/e1000/virtio)
+
+    1) Create a VM
+    2) Join guest into multicast groups
+    3) Ping multicast addresses on host
+    4) Flood ping test with different size of packets
+    5) Final ping test and check if lose packet
+
+    @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,
+                  timeout=int(params.get("login_timeout", 360)))
+
+    # flush the firewall rules
+    cmd = "iptables -F; test -e /selinux/enforce && echo 0 >/selinux/enforce"
+    session.get_command_status(cmd)
+    utils.run(cmd)
+    # make sure guest replies to broadcasts
+    session.get_command_status("echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore"
+            "_broadcasts && echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all")
+
+    # base multicast address
+    mcast = params.get("mcast", "225.0.0.1")
+    # count of multicast addresses, less than 20
+    mgroup_count = int(params.get("mgroup_count", 5))
+    flood_minutes = float(params.get("flood_minutes", 10))
+    ifname = vm.get_ifname()
+    prefix = re.findall("\d+.\d+.\d+", mcast)[0]
+    suffix = int(re.findall("\d+", mcast)[-1])
+    # copy python script to guest for joining guest to multicast groups
+    mcast_path = os.path.join(test.bindir, "scripts/join_mcast.py")
+    if not vm.copy_files_to(mcast_path, "/tmp"):
+        raise error.TestError("Fail to copy %s to guest" % mcast_path)
+    output = session.get_command_output("python /tmp/join_mcast.py %d %s %d" %
+                                        (mgroup_count, prefix, suffix))
+    # if success to join multicast, the process will be paused, and return pid.
+    try:
+        pid = re.findall("join_mcast_pid:(\d+)", output)[0]
+    except IndexError:
+        raise error.TestFail("Can't join multicast groups,output:%s" % output)
+
+    try:
+        for i in range(mgroup_count):
+            new_suffix = suffix + i
+            mcast = "%s.%d" % (prefix, new_suffix)
+            logging.info("Initial ping test, mcast: %s", mcast)
+            s, o = kvm_test_utils.ping(mcast, 10, interface=ifname, timeout=20)
+            if s != 0:
+                raise error.TestFail(" Ping return non-zero value %s" % o)
+            logging.info("Flood ping test, mcast: %s", mcast)
+            kvm_test_utils.ping(mcast, None, interface=ifname, flood=True,
+                               output_func=None, timeout=flood_minutes*60)
+            logging.info("Final ping test, mcast: %s", mcast)
+            s, o = kvm_test_utils.ping(mcast, 10, interface=ifname, timeout=20)
+            if s != 0:
+                raise error.TestFail("Ping failed, status: %s, output: %s"
+                                     % (s, o))
+    finally:
+        logging.debug(session.get_command_output("ipmaddr show"))
+        session.get_command_output("kill -s SIGCONT %s" % pid)
+        session.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index 89ec4b0..a53ab64 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -378,6 +378,13 @@ variants:
         type = nic_promisc
         file_size = 1, 1460, 65000, 100000000
 
+    - multicast: install setup unattended_install.cdrom
+        type = multicast
+        nic_mode = tap
+        mcast = 225.0.0.1
+        mgroup_count = 20
+        flood_minutes = 1
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'
@@ -1076,7 +1083,7 @@ variants:
 
     # Windows section
     - @Windows:
-        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc
+        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc multicast
         shutdown_command = shutdown /s /f /t 0
         reboot_command = shutdown /r /f /t 0
         status_test_command = echo %errorlevel%


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 11/17] KVM-test: Add a subtest of pxe
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (9 preceding siblings ...)
  2010-08-23  8:53 ` [PATCH v2 10/17] KVM-test: Add a subtest of multicast Amos Kong
@ 2010-08-23  8:53 ` Amos Kong
  2010-08-23  8:53 ` [PATCH v2 12/17] KVM-test: Add a subtest of changing mac address Amos Kong
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:53 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

This case just snoop tftp packet through tcpdump, it depends on public dhcp
server, better to test it through dnsmasq.

FIXME: Use dnsmasq for pxe test

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/pxe.py b/client/tests/kvm/tests/pxe.py
new file mode 100644
index 0000000..59b1030
--- /dev/null
+++ b/client/tests/kvm/tests/pxe.py
@@ -0,0 +1,30 @@
+import logging
+from autotest_lib.client.common_lib import error
+import kvm_subprocess, kvm_test_utils
+
+
+def run_pxe(test, params, env):
+    """
+    PXE test:
+
+    1) Snoop the tftp packet in the tap device
+    2) Wait for some seconds
+    3) Check whether capture tftp packets
+
+    @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"))
+    timeout = int(params.get("pxe_timeout", 60))
+
+    logging.info("Try to boot from pxe")
+    status, output = kvm_subprocess.run_fg("tcpdump -nli %s" % vm.get_ifname(),
+                                           logging.debug,
+                                           "(pxe) ",
+                                           timeout)
+
+    logging.info("Analyzing the tcpdump result...")
+    if not "tftp" in output:
+        raise error.TestFail("Couldn't find tftp packet in %s seconds" % timeout)
+    logging.info("Found tftp packet")
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index a53ab64..918d5aa 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -385,6 +385,19 @@ variants:
         mgroup_count = 20
         flood_minutes = 1
 
+    - pxe:
+        type = pxe
+        images = pxe
+        image_name_pxe = pxe-test
+        image_size_pxe = 1G
+        force_create_image_pxe = yes
+        remove_image_pxe = yes
+        extra_params += ' -boot n'
+        kill_vm_on_error = yes
+        network = bridge
+        restart_vm = yes
+        pxe_timeout = 60
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 12/17] KVM-test: Add a subtest of changing mac address
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (10 preceding siblings ...)
  2010-08-23  8:53 ` [PATCH v2 11/17] KVM-test: Add a subtest of pxe Amos Kong
@ 2010-08-23  8:53 ` Amos Kong
  2010-08-23  8:53 ` [PATCH v2 13/17] KVM-test: Add a subtest of netperf Amos Kong
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:53 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

Mainly test steps:
1. get a new mac from pool, and the old mac addr of guest.
2. execute the mac_change.sh in guest.
3. relogin to guest and query the interfaces info by `ifconfig`

Signed-off-by: Cao, Chen <kcao@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/mac_change.py b/client/tests/kvm/tests/mac_change.py
new file mode 100644
index 0000000..7422fff
--- /dev/null
+++ b/client/tests/kvm/tests/mac_change.py
@@ -0,0 +1,65 @@
+import logging
+from autotest_lib.client.common_lib import error
+import kvm_utils, kvm_test_utils
+
+
+def run_mac_change(test, params, env):
+    """
+    Change MAC Address of Guest.
+
+    1. get a new mac from pool, and the old mac addr of guest.
+    2. set new mac in guest and regain new IP.
+    3. re-log into guest with new mac
+
+    @param test: kvm test object
+    @param params: Dictionary with the test parameters
+    @param env: Dictionary with test environment.
+    """
+    timeout = int(params.get("login_timeout", 360))
+    vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
+    logging.info("Trying to log into guest '%s' by serial", vm.name)
+    session = kvm_utils.wait_for(lambda: vm.serial_login(),
+                                  timeout, 0, step=2)
+    if not session:
+        raise error.TestFail("Could not log into guest '%s'" % vm.name)
+
+    old_mac = vm.get_macaddr(0)
+    kvm_utils.free_mac_address(vm.root_dir, vm, 0)
+    new_mac = kvm_utils.generate_mac_address(vm.root_dir,
+                                             vm.instance,
+                                             0, vm.mac_prefix)
+    logging.info("The initial MAC address is %s" % old_mac)
+    interface = kvm_test_utils.get_linux_ifname(session, old_mac)
+
+    # Start change mac address
+    logging.info("Changing mac address to %s" % new_mac)
+    change_cmd = "ifconfig %s down && ifconfig %s hw ether %s && ifconfig %s up"\
+                 % (interface, interface, new_mac, interface)
+    if session.get_command_status(change_cmd) != 0:
+        raise error.TestFail("Fail to send mac_change command")
+
+    # Verify whether mac address is changed to new one
+    logging.info("Verifying the new mac address")
+    if session.get_command_status("ifconfig | grep -i %s" % new_mac) != 0:
+        raise error.TestFail("Fail to change mac address")
+
+    # Restart `dhclient' to regain IP for new mac address
+    logging.info("Re-start the network to gain new ip")
+    dhclient_cmd = "dhclient -r && dhclient %s" % interface
+    session.sendline(dhclient_cmd)
+
+    # Re-log into the guest after changing mac address
+    if kvm_utils.wait_for(session.is_responsive, 120, 20, 3):
+        # Just warning when failed to see the session become dead,
+        # because there is a little chance the ip does not change.
+        logging.warn("The session is still responsive, settings may fail.")
+    session.close()
+
+    # Re-log into guest and check if session is responsive
+    logging.info("Re-log into the guest")
+    session = kvm_test_utils.wait_for_login(vm,
+              timeout=int(params.get("login_timeout", 360)))
+    if not session.is_responsive():
+        raise error.TestFail("The new session is not responsive.")
+
+    session.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index 918d5aa..36e3564 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -398,6 +398,10 @@ variants:
         restart_vm = yes
         pxe_timeout = 60
 
+    - mac_change: install setup unattended_install.cdrom
+        type = mac_change
+        kill_vm = yes
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'
@@ -1096,7 +1100,7 @@ variants:
 
     # Windows section
     - @Windows:
-        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc multicast
+        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc multicast mac_change
         shutdown_command = shutdown /s /f /t 0
         reboot_command = shutdown /r /f /t 0
         status_test_command = echo %errorlevel%


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 13/17] KVM-test: Add a subtest of netperf
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (11 preceding siblings ...)
  2010-08-23  8:53 ` [PATCH v2 12/17] KVM-test: Add a subtest of changing mac address Amos Kong
@ 2010-08-23  8:53 ` Amos Kong
  2010-08-23  8:53 ` [PATCH v2 14/17] Add support of check if remote port free Amos Kong
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:53 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

Add network load by netperf, server is launched on guest, execute netperf
client with different protocols on host. if all clients execute successfully,
case will be pass. Test result will be record into result.txt.
Now this case only tests with "TCP_RR TCP_CRR UDP_RR TCP_STREAM TCP_MAERTS
TCP_SENDFILE UDP_STREAM". DLPI only supported by Unix, unix domain test is
not necessary, so drop test of DLPI and unix domain.

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/netperf.py b/client/tests/kvm/tests/netperf.py
new file mode 100644
index 0000000..f143bf8
--- /dev/null
+++ b/client/tests/kvm/tests/netperf.py
@@ -0,0 +1,55 @@
+import logging, commands, os
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+import kvm_test_utils
+
+def run_netperf(test, params, env):
+    """
+    Network stress test with netperf
+
+    1) Boot up a virtual machine
+    2) Launch netserver on guest
+    3) Execute netperf client on host with different protocols
+    4) Outout the test result
+
+    @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,
+                   timeout=int(params.get("login_timeout", 360)))
+    netperf_dir = os.path.join(os.environ['AUTODIR'], "tests/netperf2")
+    setup_cmd = params.get("setup_cmd")
+    guest_ip = vm.get_address()
+    result_file = os.path.join(test.resultsdir, "output_%s" % test.iteration)
+
+    session.get_command_output("iptables -F")
+    for i in params.get("netperf_files").split():
+        if not vm.copy_files_to(os.path.join(netperf_dir, i), "/tmp"):
+            raise error.TestError("Could not copy files to guest")
+    if session.get_command_status(setup_cmd % "/tmp", timeout=200) != 0:
+        raise error.TestFail("Fail to setup netperf on guest")
+    if session.get_command_status(params.get("netserver_cmd") % "/tmp") != 0:
+        raise error.TestFail("Fail to start netperf server on guest")
+
+    try:
+        logging.info("Setup and run netperf client on host")
+        utils.run(setup_cmd % netperf_dir)
+        success = True
+        file(result_file, "w").write("Netperf Test Result\n")
+        for i in params.get("protocols").split():
+            cmd = params.get("netperf_cmd") % (netperf_dir, i, guest_ip)
+            logging.debug("Execute netperf client test: %s" % cmd)
+            s, o = commands.getstatusoutput(cmd)
+            if s != 0:
+                logging.error("Fail to execute netperf test, protocol:%s" % i)
+                success = False
+            else:
+                logging.info(o)
+                file(result_file, "a+").write("%s\n" % o)
+        if not success:
+            raise error.TestFail("Some of the netperf tests failed")
+    finally:
+        session.get_command_output("killall netserver")
+        session.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index 36e3564..3332bc6 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -402,6 +402,16 @@ variants:
         type = mac_change
         kill_vm = yes
 
+    - netperf: install setup unattended_install.cdrom
+        type = netperf
+        nic_mode = tap
+        netperf_files = netperf-2.4.5.tar.bz2 wait_before_data.patch
+        setup_cmd = "cd %s && tar xvfj netperf-2.4.5.tar.bz2 && cd netperf-2.4.5 && patch -p0 < ../wait_before_data.patch && ./configure && make"
+        netserver_cmd =  %s/netperf-2.4.5/src/netserver
+        # test time is 60 seconds, set the buffer size to 1 for more hardware interrupt
+        netperf_cmd = %s/netperf-2.4.5/src/netperf -t %s -H %s -l 60 -- -m 1
+        protocols = "TCP_STREAM TCP_MAERTS TCP_RR TCP_CRR UDP_RR TCP_SENDFILE UDP_STREAM"
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 14/17] Add support of check if remote port free
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (12 preceding siblings ...)
  2010-08-23  8:53 ` [PATCH v2 13/17] KVM-test: Add a subtest of netperf Amos Kong
@ 2010-08-23  8:53 ` Amos Kong
  2010-08-23  8:53 ` [PATCH v2 15/17] KVM-test: Improve vlan subtest Amos Kong
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:53 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py
index b019fc5..a24585b 100644
--- a/client/tests/kvm/kvm_utils.py
+++ b/client/tests/kvm/kvm_utils.py
@@ -789,7 +789,7 @@ def scp_from_remote(host, port, username, password, remote_path, local_path,
 
 # The following are utility functions related to ports.
 
-def is_port_free(port):
+def is_port_free(port, address):
     """
     Return True if the given port is available for use.
 
@@ -798,15 +798,22 @@ def is_port_free(port):
     try:
         s = socket.socket()
         #s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        s.bind(("localhost", port))
-        free = True
+        if address == "localhost":
+            s.bind(("localhost", port))
+            free = True
+        else:
+            s.connect((address, port))
+            free = False
     except socket.error:
-        free = False
+        if address == "localhost":
+            free = False
+        else:
+            free = True
     s.close()
     return free
 
 
-def find_free_port(start_port, end_port):
+def find_free_port(start_port, end_port, address="localhost"):
     """
     Return a host free port in the range [start_port, end_port].
 
@@ -814,12 +821,12 @@ def find_free_port(start_port, end_port):
     @param end_port: Port immediately after the last one that will be checked.
     """
     for i in range(start_port, end_port):
-        if is_port_free(i):
+        if is_port_free(i, address):
             return i
     return None
 
 
-def find_free_ports(start_port, end_port, count):
+def find_free_ports(start_port, end_port, count, address="localhost"):
     """
     Return count of host free ports in the range [start_port, end_port].
 
@@ -830,7 +837,7 @@ def find_free_ports(start_port, end_port, count):
     ports = []
     i = start_port
     while i < end_port and count > 0:
-        if is_port_free(i):
+        if is_port_free(i, address):
             ports.append(i)
             count -= 1
         i += 1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 15/17] KVM-test: Improve vlan subtest
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (13 preceding siblings ...)
  2010-08-23  8:53 ` [PATCH v2 14/17] Add support of check if remote port free Amos Kong
@ 2010-08-23  8:53 ` Amos Kong
  2010-08-23  8:54 ` [PATCH v2 16/17] Vlan: Replace extra_params '-snapshot' with image_snapshot Amos Kong
  2010-08-23  8:54 ` [PATCH v2 17/17] KVM-test: Add subtest of testing offload by ethtool Amos Kong
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:53 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

This is an enhancement of existed vlan test. Rename the vlan_tag.py to vlan.py,
it is more reasonable.
. Setup arp from "/proc/sys/net/ipv4/conf/all/arp_ignore"
. Multiple vlans exist simultaneously
. Test ping between same and different vlans
. Test by TCP data transfer, floop ping between same vlan
. Maximal plumb/unplumb vlans

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/vlan.py b/client/tests/kvm/tests/vlan.py
new file mode 100644
index 0000000..a9c84b2
--- /dev/null
+++ b/client/tests/kvm/tests/vlan.py
@@ -0,0 +1,181 @@
+import logging, time, re
+from autotest_lib.client.common_lib import error
+import kvm_test_utils, kvm_utils
+
+def run_vlan(test, params, env):
+    """
+    Test 802.1Q vlan of NIC, config it by vconfig command.
+
+    1) Create two VMs
+    2) Setup guests in 10 different vlans by vconfig and using hard-coded
+       ip address
+    3) Test by ping between same and different vlans of two VMs
+    4) Test by TCP data transfer, floop ping between same vlan of two VMs
+    5) Test maximal plumb/unplumb vlans
+    6) Recover the vlan config
+
+    @param test: KVM test object.
+    @param params: Dictionary with the test parameters.
+    @param env: Dictionary with test environment.
+    """
+
+    vm = []
+    session = []
+    vm_ip = []
+    digest_origin = []
+    vlan_ip = ['', '']
+    ip_unit = ['1', '2']
+    subnet = params.get("subnet")
+    vlan_num = int(params.get("vlan_num"))
+    maximal = int(params.get("maximal"))
+    file_size = params.get("file_size")
+
+    vm.append(kvm_test_utils.get_living_vm(env, params.get("main_vm")))
+    vm.append(kvm_test_utils.get_living_vm(env, "vm2"))
+
+    def add_vlan(session, id, iface="eth0"):
+        if session.get_command_status("vconfig add %s %s" % (iface, id)) != 0:
+            raise error.TestError("Fail to add %s.%s" % (iface, id))
+
+    def set_ip_vlan(session, id, ip, iface="eth0"):
+        iface = "%s.%s" % (iface, id)
+        if session.get_command_status("ifconfig %s %s" % (iface, ip)) != 0:
+            raise error.TestError("Fail to configure ip for %s" % iface)
+
+    def set_arp_ignore(session, iface="eth0"):
+        ignore_cmd = "echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore"
+        if session.get_command_status(ignore_cmd) != 0:
+            raise error.TestError("Fail to set arp_ignore of %s" % session)
+
+    def rem_vlan(session, id, iface="eth0"):
+        rem_vlan_cmd = "if [[ -e /proc/net/vlan/%s ]];then vconfig rem %s;fi"
+        iface = "%s.%s" % (iface, id)
+        s = session.get_command_status(rem_vlan_cmd % (iface, iface))
+        return s
+
+    def nc_transfer(src, dst):
+        nc_port = kvm_utils.find_free_port(1025, 5334, vm_ip[dst])
+        listen_cmd = params.get("listen_cmd")
+        send_cmd = params.get("send_cmd")
+
+        #listen in dst
+        listen_cmd = listen_cmd % (nc_port, "receive")
+        session[dst].sendline(listen_cmd)
+        time.sleep(2)
+        #send file from src to dst
+        send_cmd = send_cmd % (vlan_ip[dst], str(nc_port), "file")
+        if session[src].get_command_status(send_cmd, timeout = 60) != 0:
+            raise error.TestFail ("Fail to send file"
+                                    " from vm%s to vm%s" % (src+1, dst+1))
+        s, o = session[dst].read_up_to_prompt(timeout=60)
+        if s != True:
+            raise error.TestFail ("Fail to receive file"
+                                    " from vm%s to vm%s" % (src+1, dst+1))
+        #check MD5 message digest of receive file in dst
+        output = session[dst].get_command_output("md5sum receive").strip()
+        digest_receive = re.findall(r'(\w+)', output)[0]
+        if digest_receive == digest_origin[src]:
+            logging.info("file succeed received in vm %s" % vlan_ip[dst])
+        else:
+            logging.info("digest_origin is  %s" % digest_origin[src])
+            logging.info("digest_receive is %s" % digest_receive)
+            raise error.TestFail("File transfered differ from origin")
+        session[dst].get_command_status("rm -f receive")
+
+    for i in range(2):
+        session.append(kvm_test_utils.wait_for_login(vm[i],
+                       timeout=int(params.get("login_timeout", 360))))
+        if not session[i] :
+            raise error.TestError("Could not log into guest(vm%d)" % i)
+        logging.info("Logged in")
+
+        #get guest ip
+        vm_ip.append(vm[i].get_address())
+
+        #produce sized file in vm
+        dd_cmd = "dd if=/dev/urandom of=file bs=1024k count=%s"
+        if session[i].get_command_status(dd_cmd % file_size) != 0:
+            raise error.TestFail("File producing failed")
+        #record MD5 message digest of file
+        s, output =session[i].get_command_status_output("md5sum file",
+                                                        timeout=60)
+        if s != 0:
+            raise error.TestFail("File MD5_checking failed" )
+        digest_origin.append(re.findall(r'(\w+)', output)[0])
+
+        #stop firewall in vm
+        session[i].get_command_status("/etc/init.d/iptables stop")
+
+        #load 8021q module for vconfig
+        load_8021q_cmd = "modprobe 8021q"
+        if session[i].get_command_status(load_8021q_cmd) != 0:
+            raise error.TestError("Fail to load 8021q module on VM%s" % i)
+
+    try:
+        for i in range(2):
+            for vlan_i in range(1, vlan_num+1):
+                add_vlan(session[i], vlan_i)
+                set_ip_vlan(session[i], vlan_i, "%s.%s.%s" % \
+                                          (subnet, vlan_i, ip_unit[i]))
+            set_arp_ignore(session[i])
+
+        for vlan in range(1, vlan_num+1):
+            logging.info("Test for vlan %s" % vlan)
+
+            logging.info("Ping between vlans")
+            interface = 'eth0.' + str(vlan)
+            for vlan2 in range(1, vlan_num+1):
+                for i in range(2):
+                    dest = subnet +'.'+ str(vlan2)+ '.' + ip_unit[(i+1)%2]
+                    s, o = kvm_test_utils.ping(dest, count=2,
+                                              interface=interface,
+                                              session=session[i], timeout=30)
+                    if ((vlan == vlan2) ^ (s == 0)):
+                        raise error.TestFail ("%s ping %s unexpected" %
+                                                    (interface, dest))
+
+            vlan_ip[0] = subnet + '.' + str(vlan) + '.' + ip_unit[0]
+            vlan_ip[1] = subnet + '.' + str(vlan) + '.' + ip_unit[1]
+
+            logging.info("Flood ping")
+            def flood_ping(src, dst):
+                # we must use a dedicated session becuase the kvm_subprocess
+                # does not have the other method to interrupt the process in
+                # the guest rather than close the session.
+                session_flood = kvm_test_utils.wait_for_login(vm[src],
+                                                              timeout = 60)
+                kvm_test_utils.ping(vlan_ip[dst], flood=True,
+                                   interface=interface,
+                                   session=session_flood, timeout=10)
+                session_flood.close()
+
+            flood_ping(0,1)
+            flood_ping(1,0)
+
+            logging.info("Transfering data through nc")
+            nc_transfer(0, 1)
+            nc_transfer(1, 0)
+
+    finally:
+        for vlan in range(1, vlan_num+1):
+            rem_vlan(session[0], vlan)
+            rem_vlan(session[1], vlan)
+            logging.info("rem eth0.%s" % vlan)
+
+    #Plumb/unplumb maximal unber of vlan interfaces
+    i = 1
+    s = 0
+    try:
+        logging.info("Testing the plumb of vlan interface")
+        for i in range (1, maximal+1):
+            add_vlan(session[0], i)
+    finally:
+        for j in range (1, i+1):
+            s = s or rem_vlan(session[0], j)
+        if s == 0:
+            logging.info("maximal interface plumb test done")
+        else:
+            logging.error("maximal interface plumb test failed")
+
+    session[0].close()
+    session[1].close()
diff --git a/client/tests/kvm/tests/vlan_tag.py b/client/tests/kvm/tests/vlan_tag.py
deleted file mode 100644
index cafd8fe..0000000
--- a/client/tests/kvm/tests/vlan_tag.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import logging, time
-from autotest_lib.client.common_lib import error
-import kvm_subprocess, kvm_test_utils, kvm_utils
-
-
-def run_vlan_tag(test, params, env):
-    """
-    Test 802.1Q vlan of NIC, config it by vconfig command.
-
-    1) Create two VMs.
-    2) Setup guests in different VLANs by vconfig and test communication by
-       ping using hard-coded ip addresses.
-    3) Setup guests in same vlan and test communication by ping.
-    4) Recover the vlan config.
-
-    @param test: KVM test object.
-    @param params: Dictionary with the test parameters.
-    @param env: Dictionary with test environment.
-    """
-    subnet = params.get("subnet")
-    vlans = params.get("vlans").split()
-
-    vm1 = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
-    vm2 = kvm_test_utils.get_living_vm(env, "vm2")
-
-    timeout = int(params.get("login_timeout", 360))
-    session1 = kvm_test_utils.wait_for_login(vm1, timeout=timeout)
-    session2 = kvm_test_utils.wait_for_login(vm2, timeout=timeout)
-
-    try:
-        ip_cfg_base = "vconfig add eth0 %s && ifconfig eth0.%s %s.%s"
-        ip_cfg_cmd1 = ip_cfg_base % (vlans[0], vlans[0], subnet, "11")
-        ip_cfg_cmd2 = ip_cfg_base % (vlans[1], vlans[1], subnet, "12")
-
-        # Configure VM1 and VM2 in different VLANs
-        ip_cfg_vm1 = session1.get_command_status(ip_cfg_cmd1)
-        if ip_cfg_vm1 != 0:
-            raise error.TestError("Failed to config VM 1 IP address")
-        ip_cfg_vm2 = session2.get_command_status(ip_cfg_cmd2)
-        if ip_cfg_vm2 != 0:
-            raise error.TestError("Failed to config VM 2 IP address")
-
-        # Trying to ping VM 2 from VM 1, this shouldn't work
-        ping_cmd = "ping -c 2 -I eth0.%s %s.%s" % (vlans[0], subnet, "12")
-        ping_diff_vlan = session1.get_command_status(ping_cmd)
-        if ping_diff_vlan == 0:
-            raise error.TestFail("VM 2 can be reached even though it was "
-                                 "configured on a different VLAN")
-
-        # Now let's put VM 2 in the same VLAN as VM 1
-        ip_cfg_reconfig= ("vconfig rem eth0.%s && vconfig add eth0 %s && "
-                          "ifconfig eth0.%s %s.%s" % (vlans[1], vlans[0],
-                                                      vlans[0], subnet, "12"))
-        ip_cfg_vm2 = session2.get_command_status(ip_cfg_reconfig)
-        if ip_cfg_vm2 != 0:
-            raise error.TestError("Failed to re-config IP address of VM 2")
-
-        # Try to ping VM 2 from VM 1, this should work
-        ping_same_vlan = session1.get_command_status(ping_cmd)
-        if ping_same_vlan != 0:
-            raise error.TestFail("Failed to ping VM 2 even though it was "
-                                 "configured on the same VLAN")
-
-    finally:
-        session1.get_command_status("vconfig rem eth0.%s" % vlans[0])
-        session1.close()
-        session2.get_command_status("vconfig rem eth0.%s" % vlans[0])
-        session2.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index 3332bc6..d893d3a 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -341,17 +341,21 @@ variants:
             - fmt_raw:
                 image_format_stg = raw
 
-    - vlan_tag:  install setup unattended_install.cdrom
-        type = vlan_tag
+    - vlan:  install setup unattended_install.cdrom
+        type = vlan
         # subnet should not be used by host
-        subnet = 192.168.123
-        vlans = "10 20"
+        subnet = "192.168"
+        vlan_num = 5
+        file_size = 10
+        maximal = 4094
+        listen_cmd = "nc -l %s > %s"
+        send_cmd = "nc %s %s < %s"
         nic_mode = tap
         vms += " vm2"
         extra_params_vm1 += " -snapshot"
         extra_params_vm2 += " -snapshot"
+        kill_vm_vm2 = yes
         kill_vm_gracefully_vm2 = no
-        address_index_vm2 = 1
 
     - ping: install setup unattended_install.cdrom
         type = ping
@@ -1110,7 +1114,7 @@ variants:
 
     # Windows section
     - @Windows:
-        no autotest linux_s3 vlan_tag ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc multicast mac_change
+        no autotest linux_s3 vlan ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc multicast mac_change
         shutdown_command = shutdown /s /f /t 0
         reboot_command = shutdown /r /f /t 0
         status_test_command = echo %errorlevel%


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 16/17] Vlan: Replace extra_params '-snapshot' with image_snapshot
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (14 preceding siblings ...)
  2010-08-23  8:53 ` [PATCH v2 15/17] KVM-test: Improve vlan subtest Amos Kong
@ 2010-08-23  8:54 ` Amos Kong
  2010-08-23  8:54 ` [PATCH v2 17/17] KVM-test: Add subtest of testing offload by ethtool Amos Kong
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:54 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

Framework could not totalise default extra_params and extra_params_vm1 in the
following condition, it's difficult to realise when parsing config file or
calling get_sub_dict*().

extra_params += ' str1'
- case:
extra_params_vm1 += " str2"

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index d893d3a..8af3a52 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -352,8 +352,7 @@ variants:
         send_cmd = "nc %s %s < %s"
         nic_mode = tap
         vms += " vm2"
-        extra_params_vm1 += " -snapshot"
-        extra_params_vm2 += " -snapshot"
+        image_snapshot = yes
         kill_vm_vm2 = yes
         kill_vm_gracefully_vm2 = no
 


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 17/17] KVM-test: Add subtest of testing offload by ethtool
  2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
                   ` (15 preceding siblings ...)
  2010-08-23  8:54 ` [PATCH v2 16/17] Vlan: Replace extra_params '-snapshot' with image_snapshot Amos Kong
@ 2010-08-23  8:54 ` Amos Kong
  16 siblings, 0 replies; 18+ messages in thread
From: Amos Kong @ 2010-08-23  8:54 UTC (permalink / raw)
  To: autotest; +Cc: lmr, kvm

The latest case contains TX/RX/SG/TSO/GSO/GRO/LRO test. RTL8139 NIC doesn't
support TSO, LRO, it's too old, so drop offload test from rtl8139. LRO, GRO
are only supported by latest kernel, virtio nic doesn't support receive
offloading function.
Initialize the callbacks first and execute all the sub tests one by one, all
the result will be check at the end.
When execute this test, vhost should be enabled, then most of new feature can
be used. Vhost doestn't support VIRTIO_NET_F_MRG_RXBUF, so do not check large
packets in received offload test.
Transfer files by scp between host and guest, match new opened TCP port by
netstat. Capture the packages info by tcpdump, it contains package length.

FIXME: Quary supported offload function by 'ethtool'

Signed-off-by: Amos Kong <akong@redhat.com>
---
 0 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/tests/ethtool.py b/client/tests/kvm/tests/ethtool.py
new file mode 100644
index 0000000..a6a653c
--- /dev/null
+++ b/client/tests/kvm/tests/ethtool.py
@@ -0,0 +1,205 @@
+import logging, commands, re
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+import kvm_test_utils, kvm_utils
+
+def run_ethtool(test, params, env):
+    """
+    Test offload functions of ethernet device by ethtool
+
+    1) Log into a guest
+    2) Initialize the callback of sub functions
+    3) Enable/disable sub function of NIC
+    4) Execute callback function
+    5) Check the return value
+    6) Restore original configuration
+
+    @param test: Kvm test object
+    @param params: Dictionary with the test parameters.
+    @param env: Dictionary with test environment.
+    """
+    def ethtool_get(type):
+        feature_pattern = {
+            'tx':  'tx.*checksumming',
+            'rx':  'rx.*checksumming',
+            'sg':  'scatter.*gather',
+            'tso': 'tcp.*segmentation.*offload',
+            'gso': 'generic.*segmentation.*offload',
+            'gro': 'generic.*receive.*offload',
+            'lro': 'large.*receive.*offload',
+            }
+        s, o = session.get_command_status_output("ethtool -k %s" % ethname)
+        try:
+            return re.findall("%s: (.*)" % feature_pattern.get(type), o)[0]
+        except IndexError:
+            logging.debug("Could not get %s status" % type)
+
+    def ethtool_set(type, status):
+        """
+        Set ethernet device offload status
+
+        @param type: Offload type name
+        @param status: New status will be changed to
+        """
+        logging.info("Try to set %s %s" % (type, status))
+        if status not in ["off", "on"]:
+            return False
+        cmd = "ethtool -K %s %s %s" % (ethname, type, status)
+        if ethtool_get(type) != status:
+            return session.get_command_status(cmd) == 0
+        if ethtool_get(type) != status:
+            logging.error("Fail to set %s %s" % (type, status))
+            return False
+        return True
+
+    def ethtool_save_params():
+        logging.info("Save ethtool configuration")
+        for i in supported_features:
+            feature_status[i] = ethtool_get(i)
+
+    def ethtool_restore_params():
+        logging.info("Restore ethtool configuration")
+        for i in supported_features:
+            ethtool_set(i, feature_status[i])
+
+    def compare_md5sum(name):
+        logging.info("Compare md5sum of the files on guest and host")
+        host_result = utils.hash_file(name, method="md5")
+        try:
+            o = session.get_command_output("md5sum %s" % name)
+            guest_result = re.findall("\w+", o)[0]
+        except IndexError:
+            logging.error("Could not get file md5sum in guest")
+            return False
+        logging.debug("md5sum: guest(%s), host(%s)" % (guest_result,
+                                                   host_result))
+        return guest_result == host_result
+
+    def transfer_file(src="guest"):
+        """
+        Transfer file by scp, use tcpdump to capture packets, then check the
+        return string.
+
+        @param src: Source host of transfer file
+        @return: Tuple (status, error msg/tcpdump result)
+        """
+        session2.get_command_status("rm -rf %s" % filename)
+        dd_cmd = "dd if=/dev/urandom of=%s bs=1M count=%s" % (filename,
+                                                   params.get("filesize"))
+        logging.info("Creat file in source host, cmd: %s" % dd_cmd)
+        tcpdump_cmd = "tcpdump -lep -s 0 tcp -vv port ssh"
+        if src == "guest":
+            s = session.get_command_status(dd_cmd, timeout=360)
+            tcpdump_cmd += " and src %s" % guest_ip
+            copy_files_fun = vm.copy_files_from
+        else:
+            s, o = commands.getstatusoutput(dd_cmd)
+            tcpdump_cmd += " and dst %s" % guest_ip
+            copy_files_fun = vm.copy_files_to
+        if s != 0:
+            return (False, "Fail to create file by dd, cmd: %s" % dd_cmd)
+
+        # only capture the new tcp port after offload setup
+        original_tcp_ports = re.findall("tcp.*:(\d+).*%s" % guest_ip,
+                                      utils.system_output("/bin/netstat -nap"))
+        for i in original_tcp_ports:
+            tcpdump_cmd += " and not port %s" % i
+        logging.debug("Listen by command: %s" % tcpdump_cmd)
+        session2.sendline(tcpdump_cmd)
+        if not kvm_utils.wait_for(lambda: session.get_command_status(
+                                           "pgrep tcpdump") == 0, 30):
+            return (False, "Tcpdump process wasn't launched")
+
+        logging.info("Start to transfer file")
+        if not copy_files_fun(filename, filename):
+            return (False, "Child process transfer file failed")
+        logging.info("Transfer file completed")
+        if session.get_command_status("killall tcpdump") != 0:
+            return (False, "Could not kill all tcpdump process")
+        s, tcpdump_string = session2.read_up_to_prompt(timeout=60)
+        if not s:
+            return (False, "Fail to read tcpdump's output")
+
+        if not compare_md5sum(filename):
+            return (False, "Files' md5sum mismatched")
+        return (True, tcpdump_string)
+
+    def tx_callback(status="on"):
+        s, o = transfer_file(src="guest")
+        if not s:
+            logging.error(o)
+            return False
+        return True
+
+    def rx_callback(status="on"):
+        s, o = transfer_file(src="host")
+        if not s:
+            logging.error(o)
+            return False
+        return True
+
+    def so_callback(status="on"):
+        s, o = transfer_file(src="guest")
+        if not s:
+            logging.error(o)
+            return False
+        logging.info("Check if contained large frame")
+        # mtu: default IPv4 MTU is 1500 Bytes, ethernet header is 14 Bytes
+        return (status == "on") ^ (len([i for i in re.findall(
+                                   "length (\d*):", o) if int(i) > mtu]) == 0)
+
+    def ro_callback(status="on"):
+        s, o = transfer_file(src="host")
+        if not s:
+            logging.error(o)
+            return False
+        return True
+
+    vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
+    session = kvm_test_utils.wait_for_login(vm,
+                  timeout=int(params.get("login_timeout", 360)))
+    session2 = kvm_test_utils.wait_for_login(vm,
+                  timeout=int(params.get("login_timeout", 360)))
+    mtu = 1514
+    feature_status = {}
+    filename = "/tmp/ethtool.dd"
+    guest_ip = vm.get_address()
+    ethname = kvm_test_utils.get_linux_ifname(session, vm.get_macaddr(0))
+    supported_features = params.get("supported_features").split()
+    test_matrix = {
+        # type:(callback,    (dependence), (exclude)
+        "tx":  (tx_callback, (), ()),
+        "rx":  (rx_callback, (), ()),
+        "sg":  (tx_callback, ("tx",), ()),
+        "tso": (so_callback, ("tx", "sg",), ("gso",)),
+        "gso": (so_callback, (), ("tso",)),
+        "gro": (ro_callback, ("rx",), ("lro",)),
+        "lro": (rx_callback, (), ("gro",)),
+        }
+    ethtool_save_params()
+    success = True
+    try:
+        for type in supported_features:
+            callback = test_matrix[type][0]
+            for i in test_matrix[type][2]:
+                if not ethtool_set(i, "off"):
+                    logging.error("Fail to disable %s" % i)
+                    success = False
+            for i in [f for f in test_matrix[type][1]] + [type]:
+                if not ethtool_set(i, "on"):
+                    logging.error("Fail to enable %s" % i)
+                    success = False
+            if not callback():
+                raise error.TestFail("Test failed, %s: on" % type)
+
+            if not ethtool_set(type, "off"):
+                logging.error("Fail to disable %s" % type)
+                success = False
+            if not callback(status="off"):
+                raise error.TestFail("Test failed, %s: off" % type)
+        if not success:
+            raise error.TestError("Enable/disable offload function fail")
+    finally:
+        ethtool_restore_params()
+        session.close()
+        session2.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index 8af3a52..a6509cd 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -415,6 +415,11 @@ variants:
         netperf_cmd = %s/netperf-2.4.5/src/netperf -t %s -H %s -l 60 -- -m 1
         protocols = "TCP_STREAM TCP_MAERTS TCP_RR TCP_CRR UDP_RR TCP_SENDFILE UDP_STREAM"
 
+    - ethtool: install setup unattended_install.cdrom
+        type = ethtool
+        filesize = 512
+        nic_mode = tap
+
     - physical_resources_check: install setup unattended_install.cdrom
         type = physical_resources_check
         catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'
@@ -556,10 +561,15 @@ variants:
         nic_model = e1000
         jumbo:
             mtu = 16110
+        ethtool:
+                # gso gro lro is only supported by latest kernel
+                supported_features = "tx rx sg tso gso gro lro"
     - virtio:
         nic_model = virtio
         jumbo:
             mtu = 65520
+        ethtool:
+            supported_features = "tx sg tso gso"
 
 
 # Guests
@@ -1113,7 +1123,7 @@ variants:
 
     # Windows section
     - @Windows:
-        no autotest linux_s3 vlan ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc multicast mac_change
+        no autotest linux_s3 vlan ioquit unattended_install.(url|nfs|remote_ks) jumbo file_transfer nicdriver_unload nic_promisc multicast mac_change ethtool
         shutdown_command = shutdown /s /f /t 0
         reboot_command = shutdown /r /f /t 0
         status_test_command = echo %errorlevel%


^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2010-08-23  8:51 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-23  8:51 [PATCH v2 00/17] Patchset of network related subtests Amos Kong
2010-08-23  8:51 ` [PATCH v2 01/17] KVM-test: Add a new macaddress pool algorithm Amos Kong
2010-08-23  8:52 ` [PATCH v2 02/17] Add a get_ifname function Amos Kong
2010-08-23  8:52 ` [PATCH v2 03/17] KVM Test: Add a function get_interface_name() to kvm_test_utils.py Amos Kong
2010-08-23  8:52 ` [PATCH v2 04/17] KVM Test: Add a common ping module for network related tests Amos Kong
2010-08-23  8:52 ` [PATCH v2 05/17] KVM-test: Add a new subtest ping Amos Kong
2010-08-23  8:52 ` [PATCH v2 06/17] KVM-test: Add a subtest jumbo Amos Kong
2010-08-23  8:52 ` [PATCH v2 07/17] KVM-test: Add basic file transfer test Amos Kong
2010-08-23  8:52 ` [PATCH v2 08/17] KVM-test: Add a subtest of load/unload nic driver Amos Kong
2010-08-23  8:53 ` [PATCH v2 09/17] KVM-test: Add a subtest of nic promisc Amos Kong
2010-08-23  8:53 ` [PATCH v2 10/17] KVM-test: Add a subtest of multicast Amos Kong
2010-08-23  8:53 ` [PATCH v2 11/17] KVM-test: Add a subtest of pxe Amos Kong
2010-08-23  8:53 ` [PATCH v2 12/17] KVM-test: Add a subtest of changing mac address Amos Kong
2010-08-23  8:53 ` [PATCH v2 13/17] KVM-test: Add a subtest of netperf Amos Kong
2010-08-23  8:53 ` [PATCH v2 14/17] Add support of check if remote port free Amos Kong
2010-08-23  8:53 ` [PATCH v2 15/17] KVM-test: Improve vlan subtest Amos Kong
2010-08-23  8:54 ` [PATCH v2 16/17] Vlan: Replace extra_params '-snapshot' with image_snapshot Amos Kong
2010-08-23  8:54 ` [PATCH v2 17/17] KVM-test: Add subtest of testing offload by ethtool Amos Kong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.