qemu前后端features协商过程分析(vhost_user后端)

 约定:  1)协商过程涉及的核心是:dpdk(ovs)vhost_user,qemu:vhost_user,qemu:virtio_net,guest virtio_net,共4个模块,每个模块都有自己的feature;
                  

qemu前后端features协商过程分析(vhost_user后端)_第1张图片

     
       2)由于整个协商是自后端到前端,再由前端到后端的,即dpdk(dvs)->qemu->guest->qemu->dpdk(dvs)(后面都以dpdk为例);

       3)qemu版本2.8,内核版本3.10-693,下文加黑部分为内核virtio驱动部分virtio_dev_probe函数中的实现
一:qemu层:
 1.qemu后端:vhost_user网络初始化,main-->net_init_clients-->net_init_netdev-->net_client_init-->net_client_init1-->net_client_init_fun[]-->net_init_vhost_user->net_vhost_user_init->qemu_chr_fe_set_handlers(,,net_vhost_user_event,,)
 2.vhost_user会和qemu建立vhost socket链接,连接建立成功后qemu会调用网络初始化时注册的CHR_EVENT_OPENED事件响应函数的net_vhost_user_event;
  net_vhost_user_event--->vhost_user_start
    其中:vhost_user_start-->vhost_net_init(vhost-user.c)
    1) vhost_net_init-->vhost_dev_init-->vhost_set_backend_type设置为VHOST_BACKEND_TYPE_USER模式(有二种kernel(vhost) or vhost_user),并初始化
vhost_dev *dev->vhost_opt=&user_ops(vhost使用的&kernel_ops),下面都会使用的这个函数集。
    说明:(vhost_net_init负责创建并初始化一个vhost_net,每个vhost_net对应1个vhost_dev,2个vhost_virtqueue)。
    2)                                               -->hdev->vhost_opt->vhost_set_owner-->vhost_user_set_owner--vhost_user_write->(vhost_user_one_time_request)设置后端为vhost_user模式;
    3)                                               -->hdev->vhost_opt->vhost_backend_init-->vhost_user_init-->vhost_user_get_features-->vhost_user_get_u64(msg.request:VHOST_USER_GET_FEATURES)->vhost_user_write->vhost_user_read 此步骤就是和dpdk进行协商,来获取dpdk:vhost_user使能的features,并存放到qemu:vhost_user的struct vhost_dev.feature中,此过程还可以获得protocol_feature(VHOST_USER_GET_PROTOCOL_FEATURES),并通过VHOST_USER_SET_PROTOCOL_FEATURES保证前后端协议一致,还可获得backend_features和获取支持的最大队列数。
    4)                                               -->hdev->vhost_opt->vhost_get_features-->vhost_user_get_features->vhost_user_get_features-->vhost_user_get_u64->vhost_user_write->vhost_user_read来获取feature.
    5)                                              -->vhost_virtqueue_init-->vhost_user_set_vring_call->vhost_set_vring_file(VHOST_USER_SET_VRING_CALL)->vhost_user_write。
    6)                                              -->memory_listener_register 注册memory_listener。
二:qemu:virtio_net 前端代理初始化
qemu启动过程中还会进一步对前端代理进行初始化:
virtio_net_class_init-->virtio_net_get_features-->vhost_net_get_features-->vhost_get_features,此时通过qemu前后端协商一致,后端的vhost_dev.feature传递到前端代理VirtIODevice vdev.host_feature.
三:guest启动后virtio-net驱动加载(加黑是kernel流程)
1)virtio_init->bus_register(&virtio_bus)注册virtio_bus(bus_type函数集),后期虚机根据扫描pci,来加载设备!
2)virtio_dev_probe-->dev->config->get_features(dev) -->vp_get_features->ioread32(读寄存器VIRTIO_PCI_HOST_FEATURES)
    
qemu写寄存器VIRTIO_PCI_HOST_FEATURES ,将进行以下一些操作:
    virtio_pci_config_write-->virtio_ioport_write(写寄存器,使guest获的qemu前端代理features vdev.host_feature),到此为止dpdk端vhost_user 的feature经过qemu传递就真正被guest获取到了,guest会通过qemu前端获得的features和自身驱动支持的features来设置自己生效的features。
                              virtio_finalize_features->dev->config->finalize_features(dev)-->vp_finalize_features(写寄存器VIRTIO_PCI_GUEST_FEATURES)
    VIRTIO_PCI_HOST_FEATURES寄存器被写后会被kvm捕捉传给qemu,qemu将进行以下一些操作:
     virtio_pci_config_read-->virtio_ioport_read(qemu获的guest生效的features放到qemu前端代理的features vdev.guest_feature,以及放到qemu后端vhost_dev.acked_features中)
    代码调用链:virtio_set_features-->virtio_set_features_nocheck-->virtio_net_set_features (k->set_features)--> vhost_net_ack_features,vhost_net_ack_features中
net->dev.acked_features = net->dev.backend_features;到此为止,guest OS生效的features已经被反向传递到qemu后端qemu:vhost_user。
3)驱动virtio-net设置guest OS的features(virtio_net.c)
                           drv_probe(dev)->virtnet_probe->virtio_cread_features 判断host是否支持多队列的virtio-net设备,并获得网卡设备队列数max_queue_pairs
                                                                              ->alloc_etherdev_mq 生成一个网络设备并且进行默认设置
                                                                             ->virtio_has_feature 检测一些特性,比如硬件csum,UFO,GSO等等feature,并设置到网络设备dev->hw_features ,设置mac。    
                                                                            ->init_vqs 初始化收发队列
                                                                            ->netif_set_real_num_rx(rx)_queues 设置dev真实rx、tx队列
                                                                            ->register_netdev 注册网络设备
                                                                            ->try_fill_recv提前设置接收队列
                                                                            ->register_hotcpu_notifier 注册cpu通知链
                                                                            ->netif_carrier_on 虚拟网卡链接

四:qemu features告知dpdk
        guest OS在features反向传递给qemu后端的acked_features字段后,通过以下流程触发qemu后端传递features到dpdk,
                       virtio_finalize_features->add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK) ->dev->config->get_status(dev)->vp_set_status(写寄存器VIRTIO_PCI_STATUS)
     VIRTIO_PCI_STATUS寄存器被写后会被kvm捕捉传给qemu,qemu将进行以下一些操作:
             代码调用链:virtio_set_status->virtio_net_set_status(k->status)-virtio_net_set_status->virtio_net_vhost_status->vhost_net_start->vhost_net_start_one->vhost_dev_start->vhost_dev_set_features->
dev->vhost_ops->vhost_set_features->vhost_user_set_features->vhost_user_write(VHOST_USER_SET_FEATURES),此时,qemu就将qemu前端feature设置到后端的vhost_user设备。
       
  

你可能感兴趣的:(虚拟化,qemu-kvm)