Skip to content

Commit

Permalink
Netkvm: use WinDump for capture and Wireshark for analysis
Browse files Browse the repository at this point in the history
Replace tshark.exe with WinDump.exe for capturing network traffic. This
resolves the issue where enabling netkvm driver TxLSO results in no packet
length >= 1514 after file transfer, identified as a Wireshark problem.

Signed-off-by: wji <[email protected]>
  • Loading branch information
heywji committed Nov 18, 2024
1 parent 21d9934 commit 7bd62fb
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 56 deletions.
17 changes: 11 additions & 6 deletions qemu/tests/cfg/enable_scatter_windows.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@
driver_verifier = netkvm
Win2016, Win2019, Win8..1, Win2012..r2:
driver_verifier += " ndis"
installed_path = "C:\Program Files\Wireshark\tshark.exe"
check_installed_cmd = 'dir "${installed_path}"|findstr /I tshark.exe'
windump_name = "WinDump.exe"
windump_installed_path = "C:\${windump_name}"
check_windump_installed_cmd = 'dir "${windump_installed_path}"'
windump_install_cmd = "xcopy WIN_UTILS:\${windump_name} c:\ /y"
x86_64:
wireshark_name = "Wireshark-win64-1.10.1.exe"
i386, i686:
wireshark_name = "Wireshark-win32-1.10.1.exe"
install_wireshark_cmd = "xcopy WIN_UTILS:\${wireshark_name} c:\ /y && c:\${wireshark_name} /S"
wireshark_installed_path = "C:\Program Files\Wireshark\tshark.exe"
check_wireshark_installed_cmd = 'dir "${wireshark_installed_path}"'
wireshark_installation_cmd = "xcopy WIN_UTILS:\${wireshark_name} c:\ /y && c:\${wireshark_name} /S"

autoit_name = "AutoIt3_%PROCESSOR_ARCHITECTURE%.exe"
install_winpcap_cmd = "WIN_UTILS:\${autoit_name} WIN_UTILS:\install_winpcap.au3"
Expand All @@ -27,6 +31,7 @@
query_version_cmd += "where (DeviceName like 'Red Hat VirtIO Ethernet Adapter') "
query_version_cmd += "get DriverVersion /format:list"

run_wireshark_temp = 'start "" "${installed_path}" -n -w c:\temp.pcapng tcp and dst %s and src %s'
stop_wireshark_cmd = "taskkill /im tshark.exe /f"
parse_log_temp = '"${installed_path}" -2 -r c:\temp.pcapng -R "%s"'
pcap_file = c:\temp.pcap
run_windump_temp = 'start "" "${windump_installed_path}" -n -w "${pcap_file}" tcp and dst %s and src %s'
stop_windump_cmd = "taskkill /im ${windump_name} /f"
parse_log_temp = '"${wireshark_installed_path}" -2 -r "${pcap_file}" -R "%s"'
132 changes: 82 additions & 50 deletions qemu/tests/enable_scatter_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,41 +39,45 @@ def _is_process_finished(session, process_name):
return False
return process_name not in output

def _start_wireshark_session():
def _start_windump_session():
"""
Start a wireshark session and log network traffic to a file
Start a WinDump session and log network traffic to a file
"""
error_context.context("Start wireshark session", test.log.info)
error_context.context("Start WinDump session", test.log.info)
session_serial = vm.wait_for_serial_login(timeout=timeout)
guest_ip = vm.get_address()
try:
run_wireshark_cmd = run_wireshark_temp % (host_ip, guest_ip)
run_windump_cmd = run_windump_temp % (host_ip, guest_ip)
status, output = session_serial.cmd_status_output(
run_wireshark_cmd, timeout=timeout
run_windump_cmd, timeout=timeout
)

if status:
test.error(
"Failed to start wireshark session, "
"status=%s, output=%s" % (status, output)
"Failed to start WinDump session, status=%s, output=%s"
% (status, output)
)
is_started = utils_misc.wait_for(
lambda: not _is_process_finished(session_serial, "tshark.exe"), 20, 5, 1
lambda: not _is_process_finished(
session_serial, params.get("windump_name")
),
20,
5,
1,
)
if not is_started:
test.error("Timeout when wait for wireshark start")
test.error("Timeout when waiting for WinDump to start")
finally:
session_serial.close()

def _stop_wireshark_session():
def _stop_windump_session():
"""
Stop the running wireshark session
Stop the running WinDump session
"""
error_context.context("Stop wireshark", test.log.info)
status, output = session.cmd_status_output(stop_wireshark_cmd, timeout=timeout)
error_context.context("Stop WinDump", test.log.info)
status, output = session.cmd_status_output(stop_windump_cmd, timeout=timeout)
if status:
test.error(
"Failed to stop wireshark: status=%s, output=%s" % (status, output)
"Failed to stop WinDump: status=%s, output=%s" % (status, output)
)

def _parse_log_file(packet_filter):
Expand All @@ -83,29 +87,29 @@ def _parse_log_file(packet_filter):
param packet_filter: the filter to apply when dump packets
return: the output of the parse result
"""
error_context.context("Parse wireshark log file", test.log.info)
error_context.context("Parse captured packets using Wireshark", test.log.info)
parse_log_cmd = parse_log_temp % packet_filter
status, output = session.cmd_status_output(parse_log_cmd, timeout=timeout)
if status:
if status != 0:
test.error(
"Failed to parse session log file,"
" status=%s, output=%s" % (status, output)
"Failed to parse session log file, status=%s, output=%s"
% (status, output)
)
return output

def _get_traffic_log(packet_filter):
"""
Use wireshark to log the file transfer network traffic,
and return the packets dump output.
Use WinDump to capture the file transfer network traffic,
and return the packet analysis output.
param packet_filter: the filter to apply when dump packets
return: the output of the parse result
:param packet_filter: The filter to apply when analyzing packets
:return: The output of the parse result
"""
_start_wireshark_session()
_start_windump_session()
error_context.context("Start file transfer", test.log.info)
utils_test.run_file_transfer(test, params, env)
time.sleep(30)
_stop_wireshark_session()
_stop_windump_session()
return _parse_log_file(packet_filter)

def _set_driver_param(index):
Expand All @@ -129,11 +133,11 @@ def _get_driver_version(session):
version = version_str.split(".")[-1][0:3]
return int(version)

timeout = params.get("timeout", 360)
timeout = int(params.get("timeout", 360))
driver_verifier = params["driver_verifier"]
wireshark_name = params.get("wireshark_name")
run_wireshark_temp = params.get("run_wireshark_temp")
stop_wireshark_cmd = params.get("stop_wireshark_cmd")
autoit_name = params.get("autoit_name")
run_windump_temp = params.get("run_windump_temp")
stop_windump_cmd = params.get("stop_windump_cmd")
check_proc_temp = params.get("check_proc_temp")
parse_log_temp = params.get("parse_log_temp")
param_names = params.get("param_names").split()
Expand Down Expand Up @@ -172,28 +176,56 @@ def _get_driver_version(session):
lambda: _is_process_finished(session, autoit_name), timeout, 20, 3
)

error_context.context("Check if wireshark is installed", test.log.info)
check_installed_cmd = params.get("check_installed_cmd")
check_result = session.cmd_output(check_installed_cmd)
if "tshark" not in check_result:
error_context.context("Install wireshark", test.log.info)
install_wireshark_cmd = params.get("install_wireshark_cmd")
install_wireshark_cmd = utils_misc.set_winutils_letter(
session, install_wireshark_cmd
)
status, output = session.cmd_status_output(
install_wireshark_cmd, timeout=timeout
)
if status:
test.error(
"Failed to install wireshark, status=%s, output=%s" % (status, output)
tools = {
"windump": {
"check_cmd": params.get("check_windump_installed_cmd"),
"install_cmd": utils_misc.set_winutils_letter(
session, params.get("windump_install_cmd")
),
"process_name": params.get("windump_name"),
},
"wireshark": {
"check_cmd": params.get("check_wireshark_installed_cmd"),
"install_cmd": utils_misc.set_winutils_letter(
session, params.get("wireshark_installation_cmd")
),
"process_name": "tshark",
},
}

for tool_name, tool_info in tools.items():
is_installed = False

error_context.context(f"Check if {tool_name} is installed", test.log.info)
check_result = session.cmd_output(tool_info["check_cmd"])
is_installed = tool_info["process_name"] in check_result

if not is_installed:
error_context.context(f"Install {tool_name}", test.log.info)
status, output = session.cmd_status_output(
tool_info["install_cmd"], timeout=timeout
)
test.log.info("Wait for wireshark installation to complete")
utils_misc.wait_for(
lambda: _is_process_finished(session, wireshark_name), timeout, 20, 3
)
else:
test.log.info("Wireshark is already installed")
if status != 0:
test.error(
f"Failed to install {tool_name}, status={status}, output={output}"
)

check_result = session.cmd_output(tool_info["check_cmd"])
if tool_info["process_name"] not in check_result:
test.error(f"{tool_name} installation failed to verify.")

if tool_name == "wireshark":
test.log.info("Wait for wireshark installation to complete")
utils_misc.wait_for(
lambda: _is_process_finished(session, tool_info["process_name"]),
timeout,
20,
3,
)
test.log.info("%s installed successfully.", tool_name)
else:
test.log.info("%s is already installed", tool_name)

session.close()

virtio_win.prepare_netkvmco(vm)
Expand Down

0 comments on commit 7bd62fb

Please sign in to comment.