我正在尝试使用套接字网络创建一个模拟 VLAN,而在 QEMU 中使用套接字网络连接一个网络中的多个 VM 的唯一方法是使用网络后端mcast
的多播选项socket
来创建共享总线。
但是,当我尝试在 QEMU 中使用以下参数创建多播套接字网络时:
-device e1000,netdev=sock-0 -netdev id=sock-0,mcast=230.0.0.1:1234
它失败了:
can't bind ip=230.0.0.1 to socket: Unknown error
在我的 Windows 主机中。
这是 QEMU 的错误吗,或者我在运行 QEMU 命令之前缺少先决条件(例如期望运行多播侦听器,...等)?
net/socket.c
顺便说一句,我使用的是 Windows 10,并且运行的是交叉编译的 QEMU 4.2.0。我在 QEMU 源代码的第 256 行的绑定失败之前打印了错误,然后WSAGetLastError
返回WSAEADDRNOTAVAIL
。
答案1
显然,QEMU 4.2.0 在使用多播的套接字网络中存在错误。它不使用INADDR_ANY
(或0.0.0.0
) 作为侦听套接字,而是使用用户传入的多播组地址。为了解决这个问题,我更改了以下源代码行net/socket.c
(从 256 行更改为 261 行,含):
ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
if (ret < 0) {
error_setg_errno(errp, errno, "can't bind ip=%s to socket",
inet_ntoa(mcastaddr->sin_addr));
goto fail;
}
到
struct in_addr group_addr = mcastaddr->sin_addr;
if (localaddr) {
mcastaddr->sin_addr = *localaddr;
} else {
mcastaddr->sin_addr.s_addr = htonl(INADDR_ANY);
}
ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
if (ret < 0) {
error_setg_errno(errp, errno, "can't bind ip=%s to socket",
inet_ntoa(mcastaddr->sin_addr));
goto fail;
}
mcastaddr->sin_addr = group_addr;
我将把组的地址保存在一个变量中,将套接字地址设置为INADDR_ANY
用户传入的本地地址,创建监听套接字,然后恢复为组的地址,以便我稍后可以加入该组。该解决方案适用于 Windows 构建的二进制文件,但我相信它也可以适用于其他操作系统。