-
Notifications
You must be signed in to change notification settings - Fork 173
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a case for packet loss when slowly reusing memory buffers
Under various conditions, when the host-to-device packet rate is high, we lose packets in QEMU due to a lack of guest-allocated buffers. Look also at virtio-win/kvm-guest-drivers-windows#1012 Signed-off-by: wji <wji@redhat.com>
- Loading branch information
Showing
2 changed files
with
147 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
- netkvm_buffer_shortage: | ||
virt_test_type = qemu | ||
type = netkvm_buffer_shortage | ||
only Windows | ||
only virtio_net | ||
vhost = on | ||
timeout = 360 | ||
cdroms += " virtio" | ||
vms += " vm2" | ||
image_snapshot = yes | ||
start_vm = yes | ||
start_vm_vm2 = no | ||
smp = 2 | ||
queues = ${smp} | ||
vectors = 1024 | ||
copy_dest = "C:" | ||
nic_extra_params_nic1 = ",rx_queue_size=1024,tx_queue_size=256" | ||
nic_extra_params_type = "{'rx_queue_size': int, 'tx_queue_size': int}" | ||
i386: | ||
psutil_whl = "psutil-6.1.1-cp37-abi3-win32.whl" | ||
x86_64: | ||
psutil_whl = "psutil-6.1.1-cp37-abi3-win_amd64.whl" | ||
s_py = '.\server.py' | ||
c_py = '.\client.py' | ||
c_pip_copy_cmd = 'xcopy "WIN_UTILS:\packet_loss_scripts\${psutil_whl}" ${copy_dest}' | ||
c_pip_cmd = "pushd ${copy_dest} & start py -m pip install ${psutil_whl}" | ||
s_py_copy_cmd = 'xcopy "WIN_UTILS:\packet_loss_scripts\${s_py}" ${copy_dest}' | ||
s_py_cmd = "pushd ${copy_dest} & start py ${s_py} 12345" | ||
c_py_copy_cmd = 'xcopy "WIN_UTILS:\packet_loss_scripts\${c_py}" ${copy_dest}' | ||
c_py_cmd = "pushd ${copy_dest} & start py ${c_py} 99999 %s 12345" | ||
param_name = "MinRxBufferPercent" | ||
param_values = "0 25 50 75 100" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import re | ||
|
||
from virttest import env_process, error_context, utils_misc, utils_net | ||
from virttest.utils_windows import virtio_win | ||
|
||
|
||
@error_context.context_aware | ||
def run(test, params, env): | ||
""" | ||
Simulate high packet rate between host and device by running Python scripts | ||
on both server and client side. This test is executed on two VM guests: | ||
1) Start a VM guest as the server. | ||
2) Start a VM guest as the client. | ||
3) Simulate buffer allocation issues on the server node. | ||
4) Use a Python script to connect the client to the server. | ||
5) Adjust the MinRxBufferPercent parameter to work around the issue. | ||
6) Ensure no BSOD occurs on the client node. | ||
:param test: QEMU test object. | ||
:param params: Dictionary of test parameters. | ||
:param env: Dictionary of test environment details. | ||
""" | ||
|
||
def analyze_ping_results(session=None, dest=None, count=None, timeout=None): | ||
""" | ||
conduct a ping test to check the packet loss on slow memory buffer reallocation | ||
:param session: Local executon hint or session to execute the ping command. | ||
:param dest: Destination address. | ||
:param count: Count of icmp packet. | ||
:param timeout: Timeout for the ping command. | ||
""" | ||
|
||
status, output = utils_net.ping( | ||
s_vm_ip, session=c_session, count=count, timeout=timeout | ||
) | ||
if status != 0: | ||
test.fail("Ping failed, status: %s," " output: %s" % (status, output)) | ||
pattern = r"(\d+)% loss" | ||
match = re.search(pattern, output) | ||
if match: | ||
return match.group(1) | ||
|
||
def modify_and_analyze_params_result(vm=None, netkvmco_name=None, value=None): | ||
""" | ||
First set netkvm driver parameter 'param_name' | ||
to value 'param_value'. Then read the current and compare | ||
to 'param_value' to check identity Raised exception when | ||
checking netkvmco.exe setup was unsuccessful if something is wrong. | ||
param vm: the selected vm | ||
param netkvmco_name: the netkvm driver parameter to modify | ||
param value: the value to set to | ||
""" | ||
virtio_win.prepare_netkvmco(vm) | ||
utils_net.set_netkvm_param_value(vm, netkvmco_name, value) | ||
cur_value = utils_net.get_netkvm_param_value(vm, netkvmco_name) | ||
if cur_value != value: | ||
test.fail(f"Current value '{cur_value}' was not equires '{value}'") | ||
|
||
timeout = params.get_numeric("login_timeout", 360) | ||
s_py_copy_cmd = params.get("s_py_copy_cmd") | ||
s_py_cmd = params.get("s_py_cmd") | ||
c_py_copy_cmd = params.get("c_py_copy_cmd") | ||
c_py_cmd = params.get("c_py_cmd") | ||
c_pip_copy_cmd = params.get("c_pip_copy_cmd") | ||
c_pip_cmd = params.get("c_pip_cmd") | ||
param_name = params.get("param_name") | ||
param_values = params.get("param_values") | ||
|
||
s_vm_name = params["vms"].split()[0] | ||
s_vm = env.get_vm(s_vm_name) | ||
s_vm.verify_alive() | ||
s_session = s_vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) | ||
s_vm_ip = s_vm.get_address() | ||
|
||
c_vm_name = params["vms"].split(s_vm_name)[1].strip() | ||
c_vm_params = params.object_params(c_vm_name) | ||
c_vm_params["nic_extra_params_nic1"] = "" | ||
c_vm_params["start_vm"] = "yes" | ||
env_process.preprocess_vm(test, c_vm_params, env, c_vm_name) | ||
c_vm = env.get_vm(c_vm_name) | ||
c_vm.verify_alive() | ||
c_session = c_vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) | ||
|
||
c_pip_copy_cmd = utils_misc.set_winutils_letter(c_session, c_pip_copy_cmd) | ||
c_session.cmd(c_pip_copy_cmd) | ||
c_session.cmd(c_pip_cmd) | ||
s_py_copy_cmd = utils_misc.set_winutils_letter(s_session, s_py_copy_cmd) | ||
s_session.cmd(s_py_copy_cmd) | ||
s_session.cmd(s_py_cmd) | ||
c_py_copy_cmd = utils_misc.set_winutils_letter(c_session, c_py_copy_cmd) | ||
c_session.cmd(c_py_copy_cmd) | ||
c_session.cmd(c_py_cmd % s_vm_ip) | ||
|
||
ping_results = [] | ||
for value in param_values.split(" "): | ||
modify_and_analyze_params_result(vm=s_vm, netkvmco_name=param_name, value=value) | ||
ping_results.append( | ||
int(analyze_ping_results(session=c_session, count=100, timeout=timeout)) | ||
) | ||
|
||
if sum(ping_results) != 0: | ||
if not all( | ||
ping_results[i] > ping_results[i + 1] for i in range(len(ping_results) - 1) | ||
): | ||
test.fail( | ||
"With the MinRxBufferPercent parameter, " | ||
"the number of lost packets should be less than without " | ||
"the MinRxBufferPercent parameter." | ||
) | ||
|
||
for value in param_values: | ||
modify_and_analyze_params_result(vm=c_vm, netkvmco_name=param_name, value=value) |