Skip to content

Commit d410739

Browse files
committed
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 <[email protected]>
1 parent 3f60e13 commit d410739

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
- netkvm_buffer_shortage:
2+
virt_test_type = qemu
3+
type = netkvm_buffer_shortage
4+
only Windows
5+
only virtio_net
6+
vhost = on
7+
timeout = 360
8+
cdroms += " virtio"
9+
vms += " vm2"
10+
image_snapshot = yes
11+
start_vm = yes
12+
start_vm_vm2 = no
13+
smp = 2
14+
queues = ${smp}
15+
vectors = 1024
16+
copy_dest = "C:"
17+
nic_extra_params_nic1 = ",rx_queue_size=1024,tx_queue_size=256"
18+
nic_extra_params_type = "{'rx_queue_size': 'int', 'tx_queue_size': 'int'}"
19+
i386:
20+
psutil_whl = "psutil-6.1.1-cp37-abi3-win32.whl"
21+
x86_64:
22+
psutil_whl = "psutil-6.1.1-cp37-abi3-win_amd64.whl"
23+
s_py = '.\server.py'
24+
c_py = '.\client.py'
25+
c_pip_copy_cmd = 'xcopy "WIN_UTILS:\packet_loss_scripts\${psutil_whl}" ${copy_dest}'
26+
c_pip_cmd = "pushd ${copy_dest} & start py -m pip install ${psutil_whl}"
27+
s_py_copy_cmd = 'xcopy "WIN_UTILS:\packet_loss_scripts\${s_py}" ${copy_dest}'
28+
s_py_cmd = "pushd ${copy_dest} & start py ${s_py} 12345"
29+
c_py_copy_cmd = 'xcopy "WIN_UTILS:\packet_loss_scripts\${c_py}" ${copy_dest}'
30+
c_py_cmd = "pushd ${copy_dest} & start py ${c_py} 99999 %s 12345"
31+
param_name = "MinRxBufferPercent"
32+
param_values = "0 25 50 75 100"

qemu/tests/netkvm_buffer_shortage.py

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import re
2+
3+
from virttest import env_process, error_context, utils_misc, utils_net
4+
from virttest.utils_windows import virtio_win
5+
6+
7+
@error_context.context_aware
8+
def run(test, params, env):
9+
"""
10+
Simulate high packet rate between host and device by running Python scripts
11+
on both server and client side. This test is executed on two VM guests:
12+
13+
1) Start a VM guest as the server.
14+
2) Start a VM guest as the client.
15+
3) Simulate buffer allocation issues on the server node.
16+
4) Use a Python script to connect the client to the server.
17+
5) Adjust the MinRxBufferPercent parameter to work around the issue.
18+
6) Ensure no BSOD occurs on the client node.
19+
20+
:param test: QEMU test object.
21+
:param params: Dictionary of test parameters.
22+
:param env: Dictionary of test environment details.
23+
"""
24+
25+
def analyze_ping_results(session=None, dest=None, count=None, timeout=None):
26+
"""
27+
conduct a ping test to check the packet loss on slow memory buffer reallocation
28+
29+
:param session: Local executon hint or session to execute the ping command.
30+
:param dest: Destination address.
31+
:param count: Count of icmp packet.
32+
:param timeout: Timeout for the ping command.
33+
"""
34+
35+
status, output = utils_net.ping(
36+
s_vm_ip, session=c_session, count=count, timeout=timeout
37+
)
38+
if status != 0:
39+
test.fail("Ping failed, status: %s," " output: %s" % (status, output))
40+
pattern = r"(\d+)% loss"
41+
match = re.search(pattern, output)
42+
if match:
43+
return match.group(1)
44+
45+
def modify_and_analyze_params_result(vm=None, netkvmco_name=None, value=None):
46+
"""
47+
First set netkvm driver parameter 'param_name'
48+
to value 'param_value'. Then read the current and compare
49+
to 'param_value' to check identity Raised exception when
50+
checking netkvmco.exe setup was unsuccessful if something is wrong.
51+
52+
param vm: the selected vm
53+
param netkvmco_name: the netkvm driver parameter to modify
54+
param value: the value to set to
55+
"""
56+
virtio_win.prepare_netkvmco(vm)
57+
utils_net.set_netkvm_param_value(vm, netkvmco_name, value)
58+
cur_value = utils_net.get_netkvm_param_value(vm, netkvmco_name)
59+
if cur_value != value:
60+
test.fail(f"Current value '{cur_value}' was not equires '{value}'")
61+
62+
timeout = params.get_numeric("login_timeout", 360)
63+
s_py_copy_cmd = params.get("s_py_copy_cmd")
64+
s_py_cmd = params.get("s_py_cmd")
65+
c_py_copy_cmd = params.get("c_py_copy_cmd")
66+
c_py_cmd = params.get("c_py_cmd")
67+
c_pip_copy_cmd = params.get("c_pip_copy_cmd")
68+
c_pip_cmd = params.get("c_pip_cmd")
69+
param_name = params.get("param_name")
70+
param_values = params.get("param_values")
71+
72+
s_vm_name = params["vms"].split()[0]
73+
s_vm = env.get_vm(s_vm_name)
74+
s_vm.verify_alive()
75+
s_session = s_vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
76+
s_vm_ip = s_vm.get_address()
77+
78+
c_vm_name = params["vms"].split(s_vm_name)[1].strip()
79+
c_vm_params = params.object_params(c_vm_name)
80+
c_vm_params["nic_extra_params_nic1"] = ""
81+
c_vm_params["start_vm"] = "yes"
82+
env_process.preprocess_vm(test, c_vm_params, env, c_vm_name)
83+
c_vm = env.get_vm(c_vm_name)
84+
c_vm.verify_alive()
85+
c_session = c_vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
86+
87+
c_pip_copy_cmd = utils_misc.set_winutils_letter(c_session, c_pip_copy_cmd)
88+
c_session.cmd(c_pip_copy_cmd)
89+
c_session.cmd(c_pip_cmd)
90+
s_py_copy_cmd = utils_misc.set_winutils_letter(s_session, s_py_copy_cmd)
91+
s_session.cmd(s_py_copy_cmd)
92+
s_session.cmd(s_py_cmd)
93+
c_py_copy_cmd = utils_misc.set_winutils_letter(c_session, c_py_copy_cmd)
94+
c_session.cmd(c_py_copy_cmd)
95+
c_session.cmd(c_py_cmd % s_vm_ip)
96+
97+
ping_results = []
98+
for value in param_values.split(" "):
99+
modify_and_analyze_params_result(vm=s_vm, netkvmco_name=param_name, value=value)
100+
ping_results.append(
101+
int(analyze_ping_results(session=c_session, count=100, timeout=timeout))
102+
)
103+
104+
if sum(ping_results) != 0:
105+
if not all(
106+
ping_results[i] > ping_results[i + 1] for i in range(len(ping_results) - 1)
107+
):
108+
test.fail(
109+
"With the MinRxBufferPercent parameter, "
110+
"the number of lost packets should be less than without "
111+
"the MinRxBufferPercent parameter."
112+
)
113+
114+
for value in param_values.split(" "):
115+
modify_and_analyze_params_result(vm=c_vm, netkvmco_name=param_name, value=value)

0 commit comments

Comments
 (0)