network backend跟类型无关的实现基本都在net.c中,
全局变量:
vlans 所有vlan的链表,vlan使用VLANState结构表示
non_vlan_clients 不属于任何vlan的networkbackend链表。所有的netdev都在该链表上。
networkbackend的类型使用NetClientInfo结构来表示,其实例则使用VLanClientState表示。
当前一共定义了以下几类NetClient:
qemu_new_net_client 用于创建VLANClientState结构,其实际的结构根据net clienttype的不同而不同。
实际结构和类型的对应关系如下:
NONE
NIC
NICState
SLIRP
SlirpState
TAP
TAPState
SOCKET
NetSocketState
VDE
VDEState
DUMP
DumpState
NET_CLIENT_TYPE_NIC表示Guest中的Virtual Network Card。
NIC可以有两种attach模式,一种是attach到某个vLan上面,另外一个是attach到某个netdev上面。
在dump.c/slirp.c/tap.c/socket.c/vdc.c的初始化函数中,在调用qemu_new_net_client时,
peer参数都指定为NULL。如果在之后,有NIC在初始化时将此networkbackend指定为peer,那么
也会设置该network backend的peer为该NIC。
NIC类型的虚拟网卡则调用qemu_new_nic来创建,在其中又调用了qemu_new_net_client,其中peer
参数指定为conf->peer。
下面来看下e1000虚拟网卡的创建过程:
在系统创建完pci设备之后,会调用pci_e1000_init(PCIDevice*pci_dev)来初始化,在这其中又
调用了qemu_new_nic。
来看下对应于e1000的PCIDeviceInfo:
static PCIDeviceInfo e1000_info = {
};
其中DEFINE_NIC_PROPERTIES(E1000State, conf), 这个宏的定义如下:
#define DEFINE_NIC_PROPERTIES(_state, _conf)
\
可见,在qemu parse命令行参数的时候,会把netdev参数所指定的network backend对象赋予
E1000State.conf.peer。
结合命令行参数
-devicee1000,netdev=hostnet0,id=net0,mac=00:16:36:e3:f8:b9,bus=pci.0,addr=0x3,
这样就很明显了。
-------------------------------------
network backend的初始化流程如下:
main -> net_init_clients -> |
| ->net_client_init
->
net_client_types[i].init
net_init_client 初始化命令行上 -net 指定的network backend
net_init_netdev 初始化命令行上 -netdev 指定的network backend
qemu_del_vlan_client(vc),如果peer是NIC,那么标记peer的peer_deleted =true,并且调用qemu_cleanup_vlan_client(vc)。如果自己是NIC,如果peer_deleted ==true,那么调用qemu_free_vlan_client释放peer,然后再释放自己。