Patchset of network related subtests
v2 cover Patchset of network related subtests
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(-)
Signature · 1 line
Amos Kong
PATCH v2 1/17 KVM-test: Add a new macaddress pool algorithm
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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/kvm_utils.py +74 -0
@@ -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.
client/tests/kvm/kvm_vm.py +78 -5
151 lines not on this page · raw message
client/tests/kvm/tests_base.cfg.sample +1 -1
@@ -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
PATCH v2 2/17 Add a get_ifname function
In reply to Amos KongIt's more clear to use 'nic_mode + nic_index + vnc_port' than 'tap0', It's also unique for one guest.
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/kvm_vm.py +19 -1
@@ -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.
PATCH v2 3/17 KVM Test: Add a function get_interface_name() to kvm_test_utils.py
In reply to Amos KongThe function get_interface_name is used to get the interface name of linux guest through the macaddress of specified macaddress.
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/kvm_test_utils.py +17 -0
@@ -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
PATCH v2 4/17 KVM Test: Add a common ping module for network related tests
In reply to Amos KongThe 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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/kvm_test_utils.py +111 -1
@@ -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)
PATCH v2 5/17 KVM-test: Add a new subtest ping
In reply to Amos KongThis 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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/ping.py new file +71 -0
@@ -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()
client/tests/kvm/tests_base.cfg.sample +5 -0
@@ -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}'
PATCH v2 6/17 KVM-test: Add a subtest jumbo
In reply to Amos KongAccording 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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/jumbo.py new file +129 -0
@@ -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))
client/tests/kvm/tests_base.cfg.sample +10 -1
@@ -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%
PATCH v2 7/17 KVM-test: Add basic file transfer test
In reply to Amos KongThis 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()
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/file_transfer.py new file +55 -0
@@ -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()
client/tests/kvm/tests_base.cfg.sample +6 -1
@@ -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%
PATCH v2 8/17 KVM-test: Add a subtest of load/unload nic driver
In reply to Amos KongRepeatedly 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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/nicdriver_unload.py new file +115 -0
@@ -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()
client/tests/kvm/tests_base.cfg.sample +9 -1
@@ -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%
PATCH v2 9/17 KVM-test: Add a subtest of nic promisc
In reply to Amos KongThis 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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/nic_promisc.py new file +100 -0
@@ -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)))
client/tests/kvm/tests_base.cfg.sample +5 -1
@@ -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%
PATCH v2 10/17 KVM-test: Add a subtest of multicast
In reply to Amos KongUse '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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/scripts/join_mcast.py new file +29 -0
@@ -0,0 +1,29 @@ +import socket, struct, os, signal, sys +# this script is used to join machine into multicast groups +# author: Amos Kong <[email protected]> + +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()
client/tests/kvm/tests/multicast.py new file +72 -0
72 lines not on this page · raw message
client/tests/kvm/tests_base.cfg.sample +8 -1
@@ -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%
PATCH v2 11/17 KVM-test: Add a subtest of pxe
In reply to Amos KongThis 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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/pxe.py new file +30 -0
@@ -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")
client/tests/kvm/tests_base.cfg.sample +13 -0
@@ -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}'
PATCH v2 12/17 KVM-test: Add a subtest of changing mac address
In reply to Amos KongMainly 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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/mac_change.py new file +65 -0
@@ -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()
client/tests/kvm/tests_base.cfg.sample +5 -1
@@ -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%
PATCH v2 13/17 KVM-test: Add a subtest of netperf
In reply to Amos KongAdd 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.
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/netperf.py new file +55 -0
@@ -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()
client/tests/kvm/tests_base.cfg.sample +10 -0
@@ -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}'
PATCH v2 14/17 Add support of check if remote port free
In reply to Amos Kong---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/kvm_utils.py +15 -8
@@ -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
PATCH v2 15/17 KVM-test: Improve vlan subtest
In reply to Amos KongThis 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
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/vlan.py new file +181 -0
@@ -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()
client/tests/kvm/tests/vlan_tag.py deleted +0 -68
68 lines not on this page · raw message
client/tests/kvm/tests_base.cfg.sample +10 -6
@@ -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%
PATCH v2 16/17 Vlan: Replace extra_params '-snapshot' with image_snapshot
In reply to Amos KongFramework 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"
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests_base.cfg.sample +1 -2
@@ -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
PATCH v2 17/17 KVM-test: Add subtest of testing offload by ethtool
In reply to Amos KongThe 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'
---
0 files changed, 0 insertions(+), 0 deletions(-)
client/tests/kvm/tests/ethtool.py new file +205 -0
@@ -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()
client/tests/kvm/tests_base.cfg.sample +11 -1
@@ -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%