Skip to content

Commit b870293

Browse files
committed
add case for vm transfer packet to remote host by udp
xxxx-300100:[virtual network][virtual-nic-device]The local VM can transfer length 1473-1480 packets to remote host through UDP Signed-off-by: nanli <[email protected]>
1 parent d4a34d0 commit b870293

File tree

6 files changed

+713
-0
lines changed

6 files changed

+713
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
- virtual_network.qemu_test.transfer_packets_to_remote_host_through_UDP:
2+
type = transfer_packets_to_remote_host_through_UDP
3+
take_regular_screendumps = "no"
4+
start_vm = "no"
5+
status_error = "no"
6+
#remote_host = "EXAMPLE.DEST.HOST"
7+
remote_host = "dell-per740-41.lab.eng.pek2.redhat.com"
8+
remote_user = "root"
9+
remote_passwd = "redhat"
10+
local_passwd = "redhat"
11+
# Network configuration
12+
udp_packet_size = 1473
13+
netperf_timeout = 120
14+
netperf_version = "netperf-2.7.1"
15+
netperf_linux = './../../../../../provider/virtual_network/deps/${netperf_version}.tar.bz2'
16+
netperf_windows = './../../../../../provider/virtual_network/deps/netperf.exe'
17+
tap_name = "tap0"
18+
tap_flag = "multi_queue"
19+
bridge_name = 'virbr0'
20+
iface_attrs = {'type_name': 'ethernet', 'target': {'dev': '%s', 'managed': 'no'},'model': 'virtio', 'driver': {'driver_attr': {'name': 'vhost', 'queues': '4'}}}
21+
variants:
22+
- linux_guest:
23+
guest_os_type = "linux"
24+
firewall_cmd = "systemctl stop firewalld"
25+
- windows_guest:
26+
guest_os_type = "windows"
27+
firewall_cmd = "netsh firewall set opmode mode=disable"
Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
import os
2+
import re
3+
import logging as log
4+
5+
from avocado.utils import process
6+
7+
from virttest import utils_misc
8+
from virttest import utils_net
9+
from virttest import utils_package
10+
from virttest import remote
11+
from virttest.libvirt_xml import vm_xml
12+
from virttest.utils_libvirt import libvirt_vmxml
13+
from provider.virtual_network import network_base
14+
15+
from provider.virtual_network import utils_win
16+
17+
18+
logging = log.getLogger('avocado.' + __name__)
19+
20+
21+
def run(test, params, env):
22+
"""
23+
Test UDP packet transfer from VM to remote host.
24+
25+
1. Setup VM and remote host environment
26+
2. Install and configure netperf on remote host and VM
27+
3. Start packet capture on remote host
28+
4. Run UDP transfer test from VM to remote host
29+
5. Verify packets are captured correctly
30+
6. Clean up environment
31+
"""
32+
33+
def disable_firewall(session, params, guest_os_type="linux"):
34+
"""
35+
Disable firewall on the target system.
36+
:param session: Session object for executing commands
37+
:param params: Params object
38+
:param guest_os_type: OS type ("linux" or "windows")
39+
"""
40+
firewall_cmd = params.get("firewall_cmd")
41+
42+
if guest_os_type == "linux":
43+
status = session.cmd_status(firewall_cmd)
44+
if status != 0:
45+
test.log.debug("Failed to disable firewall or already disabled")
46+
else:
47+
output = session.cmd_output(firewall_cmd)
48+
test.log.debug("Windows firewall disabled: %s", output)
49+
50+
51+
def transfer_netperf(guest_session, guest_os_type, src_guest_ip, src_host_ip, password, netperf_install_path='C:\\Program Files'):
52+
"""
53+
Transfer and install netperf.
54+
55+
:param guest_session: Guest session object
56+
:param guest_os_type: Guest OS type ("linux" or "windows")
57+
:param src_guest_ip: Source guest IP address
58+
:param src_host_ip: Source host IP address
59+
:param password: Password for authentication
60+
:param netperf_install_path: Installation path for Windows netperf
61+
"""
62+
if guest_os_type == 'linux':
63+
test.log.debug('Transfer netperf tar to guest')
64+
list_cmd = 'ls -ld /home/%s' % netperf_version
65+
status, output = guest_session.cmd_status_output(list_cmd)
66+
if r'No such file or directory' not in output:
67+
guest_session.cmd('rm -rf /home/%s' % netperf_version)
68+
69+
out = process.run('scp %s root@%s:/home' % (netperf_linux_path, src_guest_ip))
70+
test.log.debug("44444444444444444444:%s", out)
71+
72+
test.log.debug('Install netperf in guest')
73+
guest_session.cmd("yum -y install automake autoconf libtool")
74+
install_cmd = ('tar jxf /home/%s.tar.bz2 -C /home/ && '
75+
'cd /home/%s && export CFLAGS="-D_GNU_SOURCE" && ./autogen.sh && '
76+
'./configure && make && make install')
77+
78+
guest_session.cmd(install_cmd % (netperf_version, netperf_version), timeout=600)
79+
80+
status, output = guest_session.cmd_status_output(list_cmd)
81+
if r'No such file or directory' in output:
82+
test.fail('Fail to install netperf in guest')
83+
else:
84+
utils_win.pscp_file(guest_session, netperf_windows_path,
85+
netperf_install_path, src_host_ip, 'root', password)
86+
check_installed_cmd = 'dir "%s"|findstr /I netperf' % netperf_install_path
87+
output = guest_session.cmd_output(check_installed_cmd)
88+
if 'netperf' in output:
89+
test.log.debug('Success to transfer netperf.exe from '
90+
'src host to guest')
91+
else:
92+
test.fail('Fail to transfer netperf.exe from '
93+
'src host to guest')
94+
95+
96+
def run_netserver(host_session):
97+
"""
98+
Install and run netserver.
99+
100+
:param host_session: Host session object for executing commands
101+
"""
102+
test.log.debug('Install netserver on remote host firstly')
103+
remote_host = params.get("remote_host")
104+
remote_user = params.get("remote_user", "root")
105+
remote_passwd = params.get("remote_passwd")
106+
107+
test.log.debug('Scp netperf to remote host.')
108+
utils_misc.make_dirs(os.path.dirname(netperf_linux_path), host_session)
109+
remote.copy_files_to(remote_host, 'scp', remote_user, remote_passwd,
110+
'22', netperf_linux_path, netperf_linux_path)
111+
112+
list_cmd = 'ls -ld /home/%s' % netperf_version
113+
if r'No such file or directory' not in \
114+
host_session.cmd_output(list_cmd):
115+
host_session.cmd_output('rm -rf /home/%s' % netperf_version)
116+
117+
host_session.cmd_output("yum -y install automake autoconf libtool")
118+
install_cmd = 'tar jxf %s -C /home/ && ' \
119+
'cd /home/%s && export CFLAGS="-D_GNU_SOURCE" && ./autogen.sh && ' \
120+
'./configure && make && make install' % (netperf_linux_path, netperf_version)
121+
output = host_session.cmd_output(cmd=install_cmd)
122+
test.log.debug("3333333333333333333333:%s", output)
123+
if r'No such file or directory' in host_session.cmd_output(
124+
list_cmd):
125+
test.fail('Fail to install netperf on host')
126+
o = host_session.cmd_output('netstat -anp |grep 12865')
127+
if o:
128+
used_pid = o.split('LISTEN')[1].strip().split('/')[0]
129+
host_session.cmd_output('kill -9 %s' % used_pid)
130+
output = host_session.cmd_output('netserver')
131+
else:
132+
output = host_session.cmd_output('netserver')
133+
if re.search(r'libsctp', output):
134+
host_session.cmd_output('yum install -y libsctp*')
135+
output = host_session.cmd_output('netserver')
136+
if 'netserver' not in host_session.cmd_output(
137+
'pgrep -xl netserver') or ('Starting netserver' not in output):
138+
test.fail("Fail to start netserver")
139+
140+
141+
def run_netperf(guest_session, dst_host_ip, guest_os_type, packet_size, netperf_install_path='C:\\Program Files'):
142+
"""
143+
Run netperf UDP test using tp-libvirt session methods.
144+
:param guest_session: Guest session object
145+
:param dst_host_ip: Destination host IP address
146+
:param guest_os_type: Guest OS type ("linux" or "windows")
147+
:param packet_size: UDP packet size for netperf test
148+
:param netperf_install_path: Installation path for Windows netperf
149+
:return: netperf log filename
150+
"""
151+
netperf_log = 'netperf_log_%s' % utils_misc.generate_random_string(6)
152+
if guest_os_type == 'linux':
153+
guest_session.cmd('cd /home')
154+
guest_session.cmd('netperf -H %s -t UDP_STREAM -- -m %s > %s &' %
155+
(dst_host_ip, packet_size, netperf_log))
156+
else:
157+
guest_session.cmd('cd %s' % netperf_install_path)
158+
guest_session.cmd('netperf.exe -H %s -t UDP_STREAM -- -m %s > %s &' %
159+
(dst_host_ip, packet_size, netperf_log))
160+
return netperf_log
161+
162+
163+
def check_netperf_log(guest_session, netperf_log, guest_os_type, packet_size, netperf_install_path='C:\\Program Files'):
164+
"""
165+
Check netperf log results using tp-libvirt session methods.
166+
:param guest_session: Guest session object
167+
:param netperf_log: Netperf log filename to check
168+
:param guest_os_type: Guest OS type ("linux" or "windows")
169+
:param packet_size: Expected UDP packet size in log
170+
:param netperf_install_path: Installation path for Windows netperf
171+
:return: netperf log filename
172+
"""
173+
if guest_os_type == 'linux':
174+
if utils_misc.wait_for(
175+
lambda: 'netperf' not in guest_session.cmd_output('pgrep -xl netperf'), 120, step=3.0):
176+
test.log.debug('Finish to execute netperf in guest')
177+
else:
178+
test.fail('Timeout to execute netperf in guest under 120s')
179+
else:
180+
cmd = 'tasklist /FI "imagename eq netperf.exe"'
181+
guest_session.cmd('cd %s' % netperf_install_path)
182+
if utils_misc.wait_for(lambda: not re.search(
183+
r'netperf.exe', guest_session.cmd_output(cmd)), 120, step=3.0):
184+
test.log.debug('Finish to execute netperf in guest')
185+
else:
186+
test.fail('Timeout to execute netperf in guest under 120s')
187+
data_match = 'UDP STREAM TEST from'
188+
viewlog_cmd = 'cat /home/%s' % netperf_log
189+
if guest_os_type == 'windows':
190+
viewlog_cmd = 'type %s' % netperf_log
191+
output = guest_session.cmd_output(viewlog_cmd)
192+
if data_match and str(packet_size) in output:
193+
test.log.debug('The log of netperf checking is PASS')
194+
else:
195+
test.fail("The log of netperf isn't right:%s" % output)
196+
return netperf_log
197+
198+
199+
vm_name = params.get("main_vm")
200+
vm = env.get_vm(vm_name)
201+
netperf_version = params.get("netperf_version")
202+
203+
# Handle variable substitution in paths
204+
netperf_linux_rel = params.get('netperf_linux').replace('${netperf_version}', netperf_version)
205+
netperf_linux_path = os.path.join(os.path.dirname(__file__), netperf_linux_rel)
206+
netperf_windows_path = os.path.join(os.path.dirname(__file__), params.get('netperf_windows'))
207+
208+
remote_host = params.get("remote_host")
209+
remote_ip = params.get("remote_ip")
210+
remote_user = params.get("remote_user", "root")
211+
remote_passwd = params.get("remote_passwd")
212+
local_passwd = params.get("local_passwd")
213+
guest_os_type = params.get("guest_os_type", "linux")
214+
packet_size = params.get("udp_packet_size")
215+
tcpdump_log = "/tmp/udp_capture.log"
216+
217+
vm_mac = utils_net.generate_mac_address_simple()
218+
tap_name = params.get("tap_name")
219+
bridge_name = params.get("bridge_name")
220+
tap_flag = params.get("tap_flag")
221+
iface_attrs = eval(params.get("iface_attrs", "[]") % tap_name)
222+
iface_attrs.update({'mac_address': vm_mac})
223+
guest_passwd = params.get("password")
224+
backup_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
225+
226+
# Initialize variables to avoid reference errors in cleanup
227+
vm_session = None
228+
remote_session = None
229+
tcpdump_log_file = None
230+
host_iface = None
231+
232+
try:
233+
test.log.debug("TEST_STEP1: Boot up a guest on src host")
234+
host_iface = network_base.get_host_iface(test)
235+
utils_net.create_linux_bridge_tmux(bridge_name, host_iface)
236+
237+
network_base.create_tap(tap_name, bridge_name, 'root', flag=tap_flag)
238+
vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
239+
libvirt_vmxml.modify_vm_device(vmxml, 'interface', iface_attrs)
240+
if not vm.is_alive():
241+
vm.start()
242+
vm_session = vm.wait_for_serial_login()
243+
test.log.debug("Guest xml:\n%s", vm_xml.VMXML.new_from_dumpxml(vm_name))
244+
245+
vm_ip = network_base.get_vm_ip(vm_session, vm_mac)
246+
test.log.debug("VM IP: %s", vm_ip)
247+
test.log.debug("Remote host: %s", remote_host)
248+
remote_session = remote.remote_login(
249+
"ssh", remote_host, "22", remote_user, remote_passwd, r"[\#\$]\s*$")
250+
251+
# Install and run netserver on remote host
252+
test.log.debug("TEST_STEP2: Start netperf server on remote host")
253+
# Setup SSH keys for Linux guests
254+
if guest_os_type == 'linux':
255+
remote_session.cmd_output('sshpass -p %s ssh-copy-id -o '
256+
'"StrictHostKeyChecking no" -i '
257+
'/root/.ssh/id_rsa.pub root@%s' % (guest_passwd, vm_ip))
258+
run_netserver(remote_session)
259+
260+
# Start packet capture on remote host
261+
test.log.debug("TEST_STEP3: Capture the packet from guest")
262+
if not utils_package.package_install('tcpdump', session=remote_session):
263+
test.fail("tcpdump package install failed")
264+
tcpdump_log_file = '/tmp/UDP_tcpdump.log'
265+
remote_session.sendline('tcpdump -n udp and src %s > %s 2>&1 &'
266+
% (vm_ip, tcpdump_log_file))
267+
268+
test.log.debug("TEST_STEP4: Run netperf client command in the guest")
269+
# Stop firewall for guest
270+
if guest_os_type == 'linux':
271+
process.run("yum -y install sshpass")
272+
process.run('sshpass -p %s ssh-copy-id -o "StrictHostKeyChecking no" -i '
273+
'/root/.ssh/id_rsa.pub root@%s' % (local_passwd, vm_ip))
274+
disable_firewall(vm_session, params, guest_os_type)
275+
disable_firewall(remote_session, params, "linux")
276+
277+
# Transfer and install netperf in guest.
278+
transfer_netperf(vm_session, guest_os_type, vm_ip,
279+
remote_host, guest_passwd)
280+
281+
try:
282+
netperf_log = run_netperf(vm_session, remote_host, guest_os_type, packet_size)
283+
check_netperf_log(vm_session, netperf_log, guest_os_type, packet_size)
284+
285+
finally:
286+
if guest_os_type == 'linux':
287+
vm_session.sendline('rm -rf /home/netperf_log*')
288+
else:
289+
vm_session.sendline('del netperf_log*')
290+
291+
test.log.debug("TEST_STEP5: Verify packet capture")
292+
# Use grep to search for expected packets in the large log file
293+
expected_pattern = r'IP %s\.\d+ > %s\.\d+: UDP, length %s' % (vm_ip, remote_ip, packet_size)
294+
test.log.debug("Expected regex pattern: %s", expected_pattern)
295+
test.log.debug("vm_ip: %s, remote_ip: %s, packet_size: %s", vm_ip, remote_ip, packet_size)
296+
297+
# Use grep to find matching packets efficiently
298+
grep_cmd = 'grep -E "IP %s\\.[0-9]+ > %s\\.[0-9]+: UDP, length %s" %s | head -5' % (
299+
vm_ip, remote_ip, packet_size, tcpdump_log_file)
300+
test.log.debug("Grep command: %s", grep_cmd)
301+
302+
try:
303+
grep_output = remote_session.cmd_output(grep_cmd)
304+
if grep_output.strip():
305+
test.log.debug("Found matching packets:")
306+
for line in grep_output.strip().split('\n')[:3]: # Show first 3 matches
307+
test.log.debug(" %s", line.strip())
308+
test.log.debug('Captured packets on the remote host match the expectation')
309+
packet_found = True
310+
else:
311+
test.log.debug("No matching packets found")
312+
packet_found = False
313+
except Exception as e:
314+
test.log.debug("Grep command failed: %s", str(e))
315+
packet_found = False
316+
317+
if not packet_found:
318+
# Show some sample lines from the log for debugging
319+
test.log.debug("Showing first 10 lines of tcpdump log for debugging:")
320+
sample_cmd = 'head -10 %s' % tcpdump_log_file
321+
try:
322+
sample_output = remote_session.cmd_output(sample_cmd)
323+
test.log.debug("Sample log content:\n%s", sample_output)
324+
except Exception:
325+
test.log.debug("Could not read sample log content")
326+
327+
test.fail('Captured packet on the remote host does not'
328+
' match the expectation')
329+
330+
test.log.debug("UDP transfer test completed successfully")
331+
332+
finally:
333+
test.log.debug("Clean up env")
334+
if vm_session is not None:
335+
if guest_os_type == 'linux':
336+
vm_session.cmd_status('rm -rf /home/netperf_log*')
337+
else:
338+
vm_session.cmd_status('del netperf_log*')
339+
340+
if remote_session is not None:
341+
# Stop tcpdump
342+
remote_session.cmd_status("pkill tcpdump")
343+
# Stop netserver
344+
remote_session.cmd_status("pkill netserver")
345+
# Remove log file
346+
remote_session.cmd_status(f"rm -f {tcpdump_log}")
347+
if tcpdump_log_file is not None:
348+
remote_session.cmd_status(f"rm -f {tcpdump_log_file}")
349+
remote_session.close()
350+
351+
if host_iface is not None:
352+
utils_net.delete_linux_bridge_tmux(bridge_name, host_iface)
353+
network_base.delete_tap(tap_name)
354+
backup_xml.sync()
1.48 MB
Binary file not shown.
131 KB
Binary file not shown.

0 commit comments

Comments
 (0)