问题一:虚拟机中增加两块网卡eth0和eth1,均为bridge模式,两块网卡的ip地址配置到和真实机器真实网卡的同一网段,两块虚拟机网卡的arp_ignore均设置为1,然后真实机器上ping 虚拟机的eth0,在虚拟机的两块网卡上同时抓包,可以看出,eth0回复的arp回应也能被eth1收到,这是因为当在eth0和eth1上同时抓包时,两个网卡都将成为PROMISC(混杂)模式,而这两块网卡是由真实机器的两个userif的卡口代理的,可以在/proc/vmnet中看出,hub0.0由bridge,即物理真实网卡连接,而hub0.1由userif9(或者别的数字)连接,它即是虚拟机eth0的真实机器代理,hub0.2由userif10(或者别的数字)连接,它即是虚拟机eth1的代理,它们都在一个虚拟交换机上,因此当arp回应通过userif9进入虚拟交换机的时候,虚拟交换机将在各个卡口调用其receive例程,而eth1的userif10此时已经是混杂模式,因此虽然这个arp是单播给真实机器的真实网卡的,userif10也能收到,进而虚拟机的eth1也就收到了,具体在userif的receive例程中的比较目的mac地址的判断中:
Bool VNetPacketMatch(uint8 *destAddr, // IN: destination MAC
uint8 *ifAddr, // IN: MAC of interface
uint8 *ladrf, // IN: multicast filter
uint32 flags) // IN: filter flags
{
static const uint8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
return ((flags & IFF_PROMISC) || MAC_EQ(destAddr, ifAddr) || //混杂模式的网卡完全接收
((flags & IFF_BROADCAST) && MAC_EQ(destAddr, broadcast)) ||
((destAddr[0] & 0x1) && (flags & IFF_ALLMULTI ||
(flags & IFF_MULTICAST &&
VNetMulticastFilter(destAddr, ladrf)))));
}
因此虽然这个虚拟交换机名字是交换机(Virtual Switch),然而它真实的身份却是一个hub,在源代码中,它真的没有命名为switch.c而是hub.c。
问题二:对于host-only模式的虚拟机网卡,如何访问外网?
Bool VNetPacketMatch(uint8 *destAddr, // IN: destination MAC
uint8 *ifAddr, // IN: MAC of interface
uint8 *ladrf, // IN: multicast filter
uint32 flags) // IN: filter flags
{
static const uint8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
return ((flags & IFF_PROMISC) || MAC_EQ(destAddr, ifAddr) || //混杂模式的网卡完全接收
((flags & IFF_BROADCAST) && MAC_EQ(destAddr, broadcast)) ||
((destAddr[0] & 0x1) && (flags & IFF_ALLMULTI ||
(flags & IFF_MULTICAST &&
VNetMulticastFilter(destAddr, ladrf)))));
}
因此虽然这个虚拟交换机名字是交换机(Virtual Switch),然而它真实的身份却是一个hub,在源代码中,它真的没有命名为switch.c而是hub.c。
问题二:对于host-only模式的虚拟机网卡,如何访问外网?
办法就是将虚拟机的默认网关设到真实机器的vmnet1的ip地址,然后在真实机器上将ip_forward打开,并且配置一条snat规则在真实的网卡上,对于从host-only网络来的数据包,全部进行nat。此种办法对于杀掉vmnet-natd但是使用nat模式的虚拟机网卡同样有效,要知道nat模式和host-only模式的区别就在于host-only模式少一个vmnet-natd这个进程。
本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1271127