network backend跟类型无关的实现基本都在net.c中,
全局变量:
vlans 所有vlan的链表,vlan使用VLANState结构表示
non_vlan_clients 不属于任何vlan的networkbackend链表。所有的netdev都在该链表上。
networkbackend的类型使用NetClientInfo结构来表示,其实例则使用VLanClientState表示。
当前一共定义了以下几类NetClient:
typedef enum {
NET_CLIENT_TYPE_NONE,
NET_CLIENT_TYPE_NIC,
NET_CLIENT_TYPE_SLIRP,
NET_CLIENT_TYPE_TAP,
NET_CLIENT_TYPE_SOCKET,
NET_CLIENT_TYPE_VDE,
NET_CLIENT_TYPE_DUMP
} net_client_type;
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 = {
.qdev.name = "e1000",
.qdev.desc = "Intel Gigabit Ethernet",
.qdev.size = sizeof(E1000State),
.qdev.reset =qdev_e1000_reset,
.qdev.vmsd = &vmstate_e1000,
.init = pci_e1000_init,
.exit = pci_e1000_uninit,
.romfile = "pxe-e1000.bin",
.qdev.props =(Property[]) {
DEFINE_NIC_PROPERTIES(E1000State, conf),
DEFINE_PROP_END_OF_LIST(),
}
};
其中DEFINE_NIC_PROPERTIES(E1000State, conf), 这个宏的定义如下:
#define DEFINE_NIC_PROPERTIES(_state, _conf) \
DEFINE_PROP_MACADDR("mac", _state,_conf.macaddr), \
DEFINE_PROP_VLAN("vlan", _state, _conf.vlan), \
DEFINE_PROP_NETDEV("netdev", _state, _conf.peer), \
DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)
可见,在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的初始化流程如下:
| ->net_init_netdev --|
main -> net_init_clients -> | | ->net_client_init
| ->net_init_client --|
-> 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,然后再释放自己。