我安装 Debian 虚拟机的virt-install
方式是让来宾获得一个名为 的以太网接口vnet0
:
$ virsh domiflist git-server
Interface Type Source Model MAC
-------------------------------------------------------
vnet0 bridge br-ext rtl8139 52:54:00:a8:32:d7
$
这可以在检查命令行时确认qemu
:
-netdev tap,fd=27,id=hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:a8:32:d7,bus=pci.0,addr=0x2
但是,主机中有一个同名的 TAP 设备vnet0
:
$ ethtool -i vnet0
driver: tun
version: 1.6
firmware-version:
expansion-rom-version:
bus-info: tap
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
$
..但具有不同的MAC地址:
$ ip l sh vnet0
56: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br-ext state UNKNOWN mode DEFAULT group default qlen 1000
link/ether fe:54:00:a8:32:d7 brd ff:ff:ff:ff:ff:ff
$
虚拟机接口和主机中的TAP设备到底是如何连接的?或者只有一台 TAP 设备?如果是,那么 MAC 地址有何不同?
答案1
虚拟机接口和主机中的TAP设备到底是如何连接的?
qemu
(或启动的包装程序qemu
或另一个模拟器)首先打开/dev/net/tun
设备复用器。它返回一个文件描述符,可以通过ioctl(TUNSETIFF)
在字段中使用 TAP 接口的名称调用该 fd 将其附加到 TAP接口ifreq->ifr.name
。
如果具有该名称的 TAP 接口已以这种方式附加,则该操作将会失败。
然后,fd 可用于写入将出现在 TAP 接口上的数据包,就像从远程端接收到的一样,并读取由内核通过 TAP 接口路由的数据包。
如果调用进程具有该CAP_NET_ADMIN
功能(例如,是root
),并且具有该名称的 TAP 接口尚不存在,则会自动创建该接口。如果未给出名称,则将使用第一个自由名称。
事实上,它/dev/net/tun
是一个多路复用器,这意味着open()
每次它都会将句柄返回到不同的“远程一半”。该“远程一半”可以连接到单个 TAP 接口。
此外,就像任何其他文件描述符一样,如果该程序能够以这种方式使用它(与其qemu
选项一样-netdev tap,fd=FD
),则可以将其传递给另一个程序。
opentap
请参阅此中一个非常简单的函数的示例回答。
更多详细信息+示例代码在通塔普.txt来自内核文档。
或者只有一台 TAP 设备?如果是,那么 MAC 地址有何不同?
不,每个客户端都有一个单独的设备。将多个 TAP 设备连接到同一接口的方法是使用主机上的网桥。
但是,主机中有一个具有相同 vnet0 名称的 TAP 设备......但具有不同的 MAC 地址:
Host端和Guest端的界面完全不同;将其视为虚拟 UTP 电缆——两端的每个设备都有自己的 MAC。
设置-device ...,mac=...
模拟设备的硬件地址客人,而不是主机上的 TAP 设备的。