天天看點

qemu前後端features協商過程分析(vhost_user後端)

 約定:  1)協商過程涉及的核心是:dpdk(ovs)vhost_user,qemu:vhost_user,qemu:virtio_net,guest virtio_net,共4個子產品,每個子產品都有自己的feature;

qemu前後端features協商過程分析(vhost_user後端)

       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裝置。

繼續閱讀