我正在尝试创建可以互相看到和托管的虚拟机。它们由 qemu/kvm 托管并通过 libvirt 管理。虚拟机的网络适配器是使用 macvtap(VEPA 模式)创建的,以提高性能。
开启hairpin
over switch之后,无论VM之间,还是VM与Host之间的单播流均正常。
然而,当涉及到多播时,我遇到了问题。我发现主机无法 ping 通每个虚拟机。使用 tcpdump,我观察到ff02::1:ff00:212
我的虚拟机没有收到来自主机的多播地址的邻居请求数据包,其 ipv6 地址为2001:da8:a0:600::212/64
。显然,这个多播数据包应该由 macvtap 传递给虚拟机。
由于多播问题,所有 IPv6 数据包都丢失,导致邻居发现无法正常工作。
我确信交换机没有问题,因为当我通过物理网络适配器运行 tcpdump 时,我可以看到每秒两次邻居请求,一次出,一次进。
在我将主机上的 macvtap 接口设置为混杂模式后,虚拟机会收到邻居请求数据包以及一些其他应该由 macvtap 过滤的多播数据包,但没有发送到其他虚拟机的单播数据包,即使我同时在主机上 ping 6 个其他虚拟机也是如此。
因此,我认为在所有 macvtap 接口上启用混杂模式是一种可接受的解决方法,但并不优雅。
我的所有主机和虚拟机都是 CentOS 7.0。我尝试在我的主机上从 elrepo 安装 kernel-ml(linux 4.1.3),但没有什么区别。
所以:
- 每次通过 libvirt 启动时,如何将所有 macvtap 接口设置为混杂模式?
- 我对网络驱动程序不太熟悉。但根据http://www.makelinux.net/ldd3/chp-17-sect-14,我怀疑 macvlan 的驱动程序中存在一些错误,导致内核无法正确设置接口的多播列表。但是,linux/driver/net/{macvlan.c,macvtap.c} 中没有 set_multicast_list。在哪里可以找到正确的帮助?
答案1
libvirt 的 macvlan 已获得对多播的支持。遗憾的是,默认设置禁用了该功能trustGuestRxFilters="no"
,并且文档未明确说明这会破坏多播。正如您所观察到的,破坏多播也会破坏 IPv6。
https://bugzilla.redhat.com/show_bug.cgi?id=1035253#c15
您可以通过手动设置来解决这个问题trustGuestRxFilters="yes"
。有一个限制:“支持取决于客户网络设备型号,以及主机上的连接类型”。“目前仅支持virtio
设备型号和macvtap
主机上的连接”。
https://libvirt.org/formatdomain.html#elementsNICS
我认为,自然模型是默认允许多播。在你认为直接连接的网络上阻止多播接收是一个令人不快的意外。尤其是因为macvtap
似乎仍然允许发送多播数据包(以及欺骗的 MAC 源地址!)。
答案2
sourcejedi 的答案包含解决方案,但可能不够明确。使用“virsh edit”,trustGuestRxFilters
在网络设备上设置属性:
<interface type='direct' trustGuestRxFilters='yes'>
看libvirt 文档. 同样的方法适用于libvirt 网络上的所有接口。
答案3
遇到了与 macvtap 相同的问题。我找到了一种修复方法,但我不知道如何在 virsh 中自动执行它。sudo ip link set dev macvtap0 allmulticast on
答案4
这确实是邪恶的,但如果你不想启用所有多播,这似乎可以在主机上工作:
bridge fdb add 33:33:ff:<lower 24 bits of v6 address> dev <macvtap if>
(仅允许接收特定 v6 地址的请求节点多播组)