QEMU 无法在 Windows 10 主机中打开 Tap 设备
QEMU Cannot Open Tap Device in Windows 10 Host
我正在尝试将我的 QEMU VM 桥接到我的 Windows 10 主机中的本地适配器,但 QEMU 抱怨 ifname
选项提供的接口名称到 -netdev
参数无法打开。我遵循了 https://superuser.com/questions/1317652/how-to-set-up-nat-for-qemu-with-tap-backend-windows-10 中的答案,但没有成功。我已经从源代码交叉编译 QEMU 来调试此行为,以确定是否可以检测到接口名称,显然 QEMU 可以找到适配器的名称,但不能找到 TAP 设备文件。为了进一步解释我的观点,这里有一段来自 QEMU 4.2.0 源代码(撰写本文时的最新版本)net/tap-win32.c:595
的代码片段,特别是 tap_win32_open
函数,我将突出显示失败的地方在此函数中(查找 // THIS IS WHERE IT WILL FAIL.
评论):
- 正在使用正确的现有网络接口进行测试:
static int tap_win32_open(tap_win32_overlapped_t **phandle,
const char *preferred_name)
{
...
rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
if (rc)
return -1;
snprintf (device_path, sizeof(device_path), "%s%s%s",
USERMODEDEVICEDIR,
device_guid,
TAPSUFFIX);
handle = CreateFile (
device_path,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
0 );
if (handle == INVALID_HANDLE_VALUE) {
return -1; // THIS IS WHERE IT WILL FAIL.
}
...
- 使用不正确(不存在)的网络接口进行测试:
static int tap_win32_open(tap_win32_overlapped_t **phandle,
const char *preferred_name)
{
...
rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
if (rc)
return -1; // THIS IS WHERE IT WILL FAIL.
snprintf (device_path, sizeof(device_path), "%s%s%s",
USERMODEDEVICEDIR,
device_guid,
TAPSUFFIX);
handle = CreateFile (
device_path,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
0 );
if (handle == INVALID_HANDLE_VALUE) {
return -1;
}
...
QEMU 使用设备 GUID 的前缀 USERMODEDEVICEDIR
,即 \.\Global\
和后缀 .tap
,在 Windows 中创建设备路径。例如,我正在处理的网络适配器在以下设备路径中产生:\.\Global\{990DA322-3986-4854-AE93-1D6FB0BFA137}.tap
。知道为什么 CreateFile
总是在设备路径上导致 INVALID_HANDLE_VALUE
吗?顺便说一句,GetLastError()
returns 2
,其中docs.microsoft.com
的意思如下:
...
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
...
对不起。我连接到一个非 TAP 适配器,认为它会从中获取地址,就像 VirtualBox 一样。我之前在 QEMU 中并不完全理解桥接的概念,但现在我应该附加到一个 TAP 适配器,并将该适配器桥接到另一个首选适配器。
我正在尝试将我的 QEMU VM 桥接到我的 Windows 10 主机中的本地适配器,但 QEMU 抱怨 ifname
选项提供的接口名称到 -netdev
参数无法打开。我遵循了 https://superuser.com/questions/1317652/how-to-set-up-nat-for-qemu-with-tap-backend-windows-10 中的答案,但没有成功。我已经从源代码交叉编译 QEMU 来调试此行为,以确定是否可以检测到接口名称,显然 QEMU 可以找到适配器的名称,但不能找到 TAP 设备文件。为了进一步解释我的观点,这里有一段来自 QEMU 4.2.0 源代码(撰写本文时的最新版本)net/tap-win32.c:595
的代码片段,特别是 tap_win32_open
函数,我将突出显示失败的地方在此函数中(查找 // THIS IS WHERE IT WILL FAIL.
评论):
- 正在使用正确的现有网络接口进行测试:
static int tap_win32_open(tap_win32_overlapped_t **phandle,
const char *preferred_name)
{
...
rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
if (rc)
return -1;
snprintf (device_path, sizeof(device_path), "%s%s%s",
USERMODEDEVICEDIR,
device_guid,
TAPSUFFIX);
handle = CreateFile (
device_path,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
0 );
if (handle == INVALID_HANDLE_VALUE) {
return -1; // THIS IS WHERE IT WILL FAIL.
}
...
- 使用不正确(不存在)的网络接口进行测试:
static int tap_win32_open(tap_win32_overlapped_t **phandle,
const char *preferred_name)
{
...
rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
if (rc)
return -1; // THIS IS WHERE IT WILL FAIL.
snprintf (device_path, sizeof(device_path), "%s%s%s",
USERMODEDEVICEDIR,
device_guid,
TAPSUFFIX);
handle = CreateFile (
device_path,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
0 );
if (handle == INVALID_HANDLE_VALUE) {
return -1;
}
...
QEMU 使用设备 GUID 的前缀 USERMODEDEVICEDIR
,即 \.\Global\
和后缀 .tap
,在 Windows 中创建设备路径。例如,我正在处理的网络适配器在以下设备路径中产生:\.\Global\{990DA322-3986-4854-AE93-1D6FB0BFA137}.tap
。知道为什么 CreateFile
总是在设备路径上导致 INVALID_HANDLE_VALUE
吗?顺便说一句,GetLastError()
returns 2
,其中docs.microsoft.com
的意思如下:
...
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
...
对不起。我连接到一个非 TAP 适配器,认为它会从中获取地址,就像 VirtualBox 一样。我之前在 QEMU 中并不完全理解桥接的概念,但现在我应该附加到一个 TAP 适配器,并将该适配器桥接到另一个首选适配器。