?《重識(shí)云原生系列》專題索引:?
- 第一章——不謀全局不足以謀一域
- 第二章計(jì)算第1節(jié)——計(jì)算虛擬化技術(shù)總述
- 第三章云存儲(chǔ)第1節(jié)——分布式云存儲(chǔ)總述
- 第四章云網(wǎng)絡(luò)第一節(jié)——云網(wǎng)絡(luò)技術(shù)發(fā)展簡(jiǎn)述
- 第四章云網(wǎng)絡(luò)4.2節(jié)——相關(guān)基礎(chǔ)知識(shí)準(zhǔn)備
- 第四章云網(wǎng)絡(luò)4.3節(jié)——重要網(wǎng)絡(luò)協(xié)議
- 第四章云網(wǎng)絡(luò)4.3.1節(jié)——路由技術(shù)簡(jiǎn)述
- 第四章云網(wǎng)絡(luò)4.3.2節(jié)——VLAN技術(shù)
- 第四章云網(wǎng)絡(luò)4.3.3節(jié)——RIP協(xié)議
- 第四章云網(wǎng)絡(luò)4.3.4節(jié)——OSPF協(xié)議
- 第四章云網(wǎng)絡(luò)4.3.5節(jié)——EIGRP協(xié)議
- 第四章云網(wǎng)絡(luò)4.3.6節(jié)——IS-IS協(xié)議
- 第四章云網(wǎng)絡(luò)4.3.7節(jié)——BGP協(xié)議
- 第四章云網(wǎng)絡(luò)4.3.7.2節(jié)——BGP協(xié)議概述
- 第四章云網(wǎng)絡(luò)4.3.7.3節(jié)——BGP協(xié)議實(shí)現(xiàn)原理
- 第四章云網(wǎng)絡(luò)4.3.7.4節(jié)——高級(jí)特性
- 第四章云網(wǎng)絡(luò)4.3.7.5節(jié)——實(shí)操
- 第四章云網(wǎng)絡(luò)4.3.7.6節(jié)——MP-BGP協(xié)議
- 第四章云網(wǎng)絡(luò)4.3.8節(jié)——策略路由
- 第四章云網(wǎng)絡(luò)4.3.9節(jié)——Graceful Restart(平滑重啟)技術(shù)
- 第四章云網(wǎng)絡(luò)4.3.10節(jié)——VXLAN技術(shù)
- 第四章云網(wǎng)絡(luò)4.3.10.2節(jié)——VXLAN Overlay網(wǎng)絡(luò)方案設(shè)計(jì)
- 第四章云網(wǎng)絡(luò)4.3.10.3節(jié)——VXLAN隧道機(jī)制
- 第四章云網(wǎng)絡(luò)4.3.10.4節(jié)——VXLAN報(bào)文轉(zhuǎn)發(fā)過程
- 第四章云網(wǎng)絡(luò)4.3.10.5節(jié)——VXlan組網(wǎng)架構(gòu)
- 第四章云網(wǎng)絡(luò)4.3.10.6節(jié)——VXLAN應(yīng)用部署方案
- 第四章云網(wǎng)絡(luò)4.4節(jié)——Spine-Leaf網(wǎng)絡(luò)架構(gòu)
- 第四章云網(wǎng)絡(luò)4.5節(jié)——大二層網(wǎng)絡(luò)
- 第四章云網(wǎng)絡(luò)4.6節(jié)——Underlay 和 Overlay概念
- 第四章云網(wǎng)絡(luò)4.7.1節(jié)——網(wǎng)絡(luò)虛擬化與卸載加速技術(shù)的演進(jìn)簡(jiǎn)述
- 第四章云網(wǎng)絡(luò)4.7.2節(jié)——virtio網(wǎng)絡(luò)半虛擬化簡(jiǎn)介
- 第四章云網(wǎng)絡(luò)4.7.3節(jié)——Vhost-net方案
- 第四章云網(wǎng)絡(luò)4.7.4節(jié)vhost-user方案——virtio的DPDK卸載方案
- 第四章云網(wǎng)絡(luò)4.7.5節(jié)vDPA方案——virtio的半硬件虛擬化實(shí)現(xiàn)
- 第四章云網(wǎng)絡(luò)4.7.6節(jié)——virtio-blk存儲(chǔ)虛擬化方案
- 第四章云網(wǎng)絡(luò)4.7.8節(jié)——SR-IOV方案
- 第四章云網(wǎng)絡(luò)4.7.9節(jié)——NFV
- 第四章云網(wǎng)絡(luò)4.8.1節(jié)——SDN總述
- 第四章云網(wǎng)絡(luò)4.8.2.1節(jié)——OpenFlow概述
- 第四章云網(wǎng)絡(luò)4.8.2.2節(jié)——OpenFlow協(xié)議詳解
- 第四章云網(wǎng)絡(luò)4.8.2.3節(jié)——OpenFlow運(yùn)行機(jī)制
- 第四章云網(wǎng)絡(luò)4.8.3.1節(jié)——Open vSwitch簡(jiǎn)介
- 第四章云網(wǎng)絡(luò)4.8.3.2節(jié)——Open vSwitch工作原理詳解
- 第四章云網(wǎng)絡(luò)4.8.4節(jié)——OpenStack與SDN的集成
- 第四章云網(wǎng)絡(luò)4.8.5節(jié)——OpenDayLight
- 第四章云網(wǎng)絡(luò)4.8.6節(jié)——Dragonflow
4 vhost-user
4.1 什么是 vhost-user
????????在 vhost_net 的方案中,由于 vhost_net 實(shí)現(xiàn)在內(nèi)核中,guest 與 vhost_net 的通信,相較于原生的 virtio 方式性能上有了一定程度的提升颁督,從 guest 到 kvm.ko 的交互只有一次用戶態(tài)的切換以及數(shù)據(jù)拷貝。這個(gè)方案對(duì)于不同 host 之間的通信坎穿,或者 guest 到 host nic 之間的通信是比較好的轿钠,但是對(duì)于某些用戶態(tài)進(jìn)程間的通信芭概,比如數(shù)據(jù)面的通信方案岔擂,openvswitch 和與之類似的 SDN 的解決方案位喂,guest 需要和 host 用戶態(tài)的 vswitch 進(jìn)行數(shù)據(jù)交換浪耘,如果采用 vhost_net 的方案,guest 和 host 之間又存在多次的上下文切換和數(shù)據(jù)拷貝塑崖,為了避免這種情況点待,業(yè)界就想出將 vhost_net從內(nèi)核態(tài)移到用戶態(tài)。這就是 vhost-user 的實(shí)現(xiàn)弃舒。
4.2 vhost-user 的實(shí)現(xiàn)簡(jiǎn)述
????????vhost-user 和 vhost_net 的實(shí)現(xiàn)原理是一樣,都是采用 vring 完成共享內(nèi)存状原,eventfd 機(jī)制完成事件通知聋呢。不同在于 vhost_net 實(shí)現(xiàn)在內(nèi)核中,而 vhost-user 實(shí)現(xiàn)在用戶空間中颠区,用于用戶空間中兩個(gè)進(jìn)程之間的通信削锰,其采用共享內(nèi)存的通信方式。
????????vhost-user 基于 C/S 的模式毕莱,采用 UNIX 域套接字(UNIX domain socket)來完成進(jìn)程間的事件通知和數(shù)據(jù)交互器贩,相比 vhost_net 中采用 ioctl 的方式,vhost-user 采用 socket 的方式大大簡(jiǎn)化了操作朋截。
????????vhost-user 基于 vring 這套通用的共享內(nèi)存通信方案蛹稍,只要 client 和 server 按照 vring 提供的接口實(shí)現(xiàn)所需功能即可,常見的實(shí)現(xiàn)方案是 client 實(shí)現(xiàn)在 guest OS 中部服,一般是集成在 virtio 驅(qū)動(dòng)上唆姐,server 端實(shí)現(xiàn)在 qemu 中,也可以實(shí)現(xiàn)在各種數(shù)據(jù)面中廓八,如 OVS奉芦,Snabbswitch 等虛擬交換機(jī)。
????????如果使用 qemu 作為 vhost-user 的 server 端實(shí)現(xiàn)剧蹂,在啟動(dòng) qemu 時(shí)声功,我們需要指定 -mem-path 和 -netdev 參數(shù),如:
$ qemu -m 1024 -mem-path /hugetlbfs,prealloc=on,share=on
-netdev type=vhost-user,id=net0,file=/path/to/socket
-device virtio-net-pci,netdev=net0
????????指定 -mem-path 意味著 qemu 會(huì)在 guest OS 的內(nèi)存中創(chuàng)建一個(gè)文件宠叼,share=on 選項(xiàng)允許其他進(jìn)程訪問這個(gè)文件先巴,也就意味著能訪問 guest OS 內(nèi)存,達(dá)到共享內(nèi)存的目的冒冬。
-netdev type=vhost-user 指定通信方案筹裕,file=/path/to/socket 指定 socket 文件。
????????當(dāng) qemu 啟動(dòng)之后窄驹,首先會(huì)進(jìn)行 vring 的初始化朝卒,并通過 socket 建立 C/S 的共享內(nèi)存區(qū)域和事件機(jī)制,然后 client 通過 eventfd 將 virtio kick 事件通知到 server 端乐埠,server 端同樣通過 eventfd 進(jìn)行響應(yīng)抗斤,完成整個(gè)數(shù)據(jù)交互囚企。
4.3 vhost-user使用DPDK加速
????????DPDK社區(qū)一直致力于加速數(shù)據(jù)中心的網(wǎng)絡(luò)數(shù)據(jù)平面,而virtio網(wǎng)絡(luò)作為當(dāng)今云環(huán)境下數(shù)據(jù)平面必不可少的一環(huán),自然是DPDK優(yōu)化的方向。而vhost-user就是結(jié)合DPDK的各方面優(yōu)化技術(shù)得到的用戶態(tài)virtio網(wǎng)絡(luò)后端驅(qū)動(dòng)方案扩氢。這些優(yōu)化技術(shù)包括:處理器親和性前硫、大頁(yè)內(nèi)存的使用、輪詢模式驅(qū)動(dòng)等典阵。除了vhost-user,DPDK還有自己的virtio PMD作為高性能的前端,本文將以vhost-user作為重點(diǎn)介紹黍特。
????????基于vhost協(xié)議,DPDK設(shè)計(jì)了一套新的用戶態(tài)協(xié)議锯蛀,名為vhost-user協(xié)議灭衷,這套協(xié)議允許qemu將virtio設(shè)備的網(wǎng)絡(luò)包處理offload到任何DPDK應(yīng)用中(例如OVS-DPDK)。vhost-user協(xié)議和vhost協(xié)議最大的區(qū)別其實(shí)就是通信信道的區(qū)別旁涤。Vhost協(xié)議通過對(duì)vhost-net字符設(shè)備進(jìn)行ioctl實(shí)現(xiàn)翔曲,而vhost-user協(xié)議則通過unix socket進(jìn)行實(shí)現(xiàn)。通過這個(gè)unix socket劈愚,vhost-user協(xié)議允許QEMU通過以下重要的操作來配置數(shù)據(jù)平面的offload:
- 特性協(xié)商:virtio的特性與vhost-user新定義的特性都可以通過類似的方式協(xié)商瞳遍,而所謂協(xié)商的具體實(shí)現(xiàn)就是QEMU接收vhost-user的特性,與自己支持的特性取交集菌羽。
- 內(nèi)存區(qū)域配置:QEMU配置好內(nèi)存映射區(qū)域傅蹂,vhost-user使用mmap接口來映射它們。
- Vring配置:QEMU將Virtqueue的個(gè)數(shù)與地址發(fā)送給vhost-user算凿,以便vhost-user訪問份蝴。
- 通知配置:vhost-user仍然使用eventfd來實(shí)現(xiàn)前后端通知。
????????基于DPDK的Open vSwitch(OVS-DPDK)一直以來就對(duì)vhost-user提供了支持氓轰,讀者可以通過在OVS-DPDK上創(chuàng)建vhost-user端口來使用這種高效的用戶態(tài)后端婚夫。
DPDK vhost-user架構(gòu)圖
4.4 基于DPDK/SPDK的virtio front-end\back-end設(shè)備驅(qū)動(dòng)實(shí)現(xiàn)
????????鑒于DPDK/SPDK用戶態(tài)驅(qū)動(dòng)在性能優(yōu)化方面的獨(dú)到特性,virtio front-end驅(qū)動(dòng)和back-end設(shè)備的用戶態(tài)版本署鸡,主要基于DPDK/SPDK框架來進(jìn)行開發(fā)案糙。接下來本文將從front-end驅(qū)動(dòng)和back-end設(shè)備的角度來分別介紹virtio的用戶態(tài)實(shí)現(xiàn)及其主要的代碼結(jié)構(gòu)和運(yùn)行機(jī)制。
4.4.1 virtio front-end 驅(qū)動(dòng)的用戶態(tài)實(shí)現(xiàn)
????????virtio front-end 驅(qū)動(dòng)主要工作于Guest系統(tǒng)中靴庆,對(duì)基于KVM-Qemu的VM系統(tǒng)时捌,其主要的處理對(duì)象是Qemu虛擬出來的virtio類型的pci controller;對(duì)于bare-metal模式的其他系統(tǒng)炉抒,其可以通過用戶態(tài)unix socket來與后端設(shè)備交互奢讨。目前主流的virtio front-end用戶態(tài)驅(qū)動(dòng)主要有:virtio-net、virtio-blk/virtio-scsi焰薄、virtio-user-net拿诸、virtio-user-blk/virtio-user-scsi這幾種扒袖。
4.4.1.1 virtio-net的用戶態(tài)驅(qū)動(dòng)
????????virtio-net用戶態(tài)驅(qū)動(dòng)的實(shí)現(xiàn)代碼在 “DPDK/drivers/net/virtio” 目錄下,其主要處理對(duì)象是 “Virtio network device” 的pci controller亩码。結(jié)合代碼可以大致將相關(guān)流程梳理如下:
- DPDK程序啟動(dòng)時(shí)季率,注冊(cè)支持的設(shè)備id-table 和驅(qū)動(dòng)函數(shù);
1)設(shè)備id-table通過“pci_id_virtio_map”數(shù)據(jù)結(jié)構(gòu)定義了支持的pci vendor和pci device的ID并使用RTE_PMD_REGISTER_PCI_TABLE(net_virtio, pci_id_virtio_map)進(jìn)行注冊(cè);
2)驅(qū)動(dòng)由“rte_virtio_net_pci_pmd”數(shù)據(jù)結(jié)構(gòu)定義描沟,并在 “rte_pci_register(&rte_virtio_net_pci_pmd) ”中進(jìn)行注冊(cè)飒泻。
???????2. 在DPDK初始化流程中完成設(shè)備探測(cè)匹配并加載驅(qū)動(dòng);
????????在DPDK初始化流程中主要藉由DPDK eal提供的用戶態(tài)bus吏廉、device泞遗、driver的匹配模型進(jìn)行設(shè)備探測(cè)、匹配和驅(qū)動(dòng)加載迟蜜。函數(shù)rte_eal_init會(huì)根據(jù)DPDK程序啟動(dòng)參數(shù)中指定的允許訪問的設(shè)備信息進(jìn)行設(shè)備探測(cè)和匹配(默認(rèn)情況下DPDK/SPDK均不會(huì)主動(dòng)加載通過vfio、uio驅(qū)動(dòng)管理的設(shè)備啡省,只會(huì)在參數(shù)顯示指定后進(jìn)行處理) 娜睛。當(dāng)匹配到前述已注冊(cè)的virtio-net的設(shè)備后,就會(huì)回調(diào)加載對(duì)應(yīng)注冊(cè)的驅(qū)動(dòng)并調(diào)用eth_virtio_pci_probe進(jìn)行設(shè)備初始化卦睹。
????????3. 初始化virtio network device pci controller畦戒;
????????初始化的入口函數(shù)是eth_virtio_pci_probe,除基本的pci相關(guān)的初始化外结序,其中主要可以分為兩個(gè)層面的資源處理障斋,其一是virtio設(shè)備本身層面的,如在vtpci_init函數(shù)中根據(jù)設(shè)備類型填充vtpci_ops類型的函數(shù)集徐鹤,用于執(zhí)行virtio設(shè)備的基本配置操作垃环;其二,是rte_eth_dev設(shè)備層面的返敬,在函數(shù)eth_virtio_dev_init中指定virtio-net設(shè)備關(guān)于網(wǎng)絡(luò)特性相關(guān)的eth_dev_ops函數(shù)集遂庄,用于支持rte_eth_dev的特性操作。需要注意的是在此處也會(huì)在virtio_init_device函數(shù)中根據(jù)配置創(chuàng)建virtqueue并與硬件同步劲赠。
????????4. DPDK應(yīng)用程序使用virtio-net設(shè)備相關(guān)的函數(shù)接口進(jìn)行數(shù)據(jù)收發(fā)涛目;
????????在DPDK應(yīng)用程序中執(zhí)行rte_eth_dev_start操作,設(shè)置rx\tx 處理函數(shù)凛澎、中斷處理函數(shù)霹肝,并將virtqueue的狀態(tài)通知給back-end設(shè)備。在這之后DPDK應(yīng)用程序就可以通過rte_eth_tx_burst和rte_eth_rx_burst來執(zhí)行數(shù)據(jù)的發(fā)送和接收塑煎。
????????在DPDK應(yīng)用程序啟動(dòng)時(shí)通過-a指定“Virtio network device”的pci controller的bdf地址沫换,virtio-net的用戶態(tài)驅(qū)動(dòng)會(huì)被匹配并加載。在該過程中會(huì)有如“EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:00:04.0 (socket 0)”的打印信息最铁,標(biāo)識(shí)virtio-net驅(qū)動(dòng)已初始化了virtio network device并將其注冊(cè)成為了一個(gè)DPDK框架下的eth 端口苗沧,之后可以通過RTE_ETH_FOREACH_DEV類似的函數(shù)來查找并獲取對(duì)應(yīng)的port并使用刊棕。
4.4.1.2 virtio-user的用戶態(tài)驅(qū)動(dòng)
????????virtio-user模式的front-end驅(qū)動(dòng),本質(zhì)上是為了在拋開Qemu等hypervisor的場(chǎng)景下和用戶態(tài)實(shí)現(xiàn)的vhost back-end設(shè)備進(jìn)行對(duì)接而實(shí)現(xiàn)的待逞。其主要的使用場(chǎng)景可參考在bare-metal模式下的相關(guān)應(yīng)用甥角,或者針對(duì)vhost設(shè)備的簡(jiǎn)單測(cè)試需求。目前在DPDK/SPDK代碼中所存在的virtio-user驅(qū)動(dòng)的實(shí)現(xiàn)主要是兩類识樱,其一是DPDK中的virtio-net-user驅(qū)動(dòng)嗤无,其二是SPDK中的virtio-blk-user/virtio-scsi-user驅(qū)動(dòng)。
????????virtio-user模式的front-end驅(qū)動(dòng)主要是通過unix socket來與back-end 的設(shè)備進(jìn)行控制信息的協(xié)商和交互怜庸,并且作為client的角色当犯。通信初始時(shí)會(huì)根據(jù)與vhost側(cè)約定的文件來創(chuàng)建unix socket并基于此和vhost server進(jìn)行鏈接。其二者之間的數(shù)據(jù)較互也通過內(nèi)存共享映射來完成割疾。
4.4.1.3 virtio-net-user驅(qū)動(dòng)
????????virtio-net-user驅(qū)動(dòng)代碼存在于 “DPDK/drivers/net/virtio/virtio-user” 目錄下嚎卫。其計(jì)劃支持對(duì)接的back-end的設(shè)備類型有:vhost-user、vhost-kernel宏榕、vhost-vdpa拓诸,此處僅結(jié)合vhost-user類型的back-end設(shè)備來進(jìn)行介紹。結(jié)合DPDK代碼中的實(shí)現(xiàn)麻昼,可以大致概述其相關(guān)的流程如下:
- 在rte_eal_init函數(shù)中通過傳入的參數(shù)掃描并匹配對(duì)應(yīng)virtio 類型的rte_vdev設(shè)備;
????????1)virtio-net-user驅(qū)動(dòng)作為一種rte_vdev_bus總線設(shè)備的驅(qū)動(dòng)以RTE_PMD_REGISTER_VDEV(net_virtio_user, virtio_user_driver)的方式注冊(cè)到了DPDK的vdev驅(qū)動(dòng)鏈表中奠支;
????????2)當(dāng)ret_eal_init函數(shù)執(zhí)行時(shí),其中會(huì)執(zhí)行ret_bus_scan和rte_bus_probe的操作抚芦,若DPDK的啟動(dòng)參數(shù)中指定了rte_vdev設(shè)備時(shí)倍谜,就會(huì)在rte_vdev_bus總線類型設(shè)備的probe操作中對(duì)從vdev_device_list獲取的設(shè)備依次從vdev_driver_list中查找到相對(duì)應(yīng)的驅(qū)動(dòng)并進(jìn)行加載。對(duì)于net_virtio_user類型的設(shè)備叉抡,該過程最終回調(diào)的驅(qū)動(dòng)函數(shù)就是virtio_user_pmd_probe尔崔。
????????2.調(diào)用注冊(cè)的virtio_user驅(qū)動(dòng)完成相關(guān)初始化并對(duì)外提供為通用的用戶態(tài)網(wǎng)絡(luò)設(shè)備;
????????在virtio_user_pmd_probe函數(shù)中褥民,初始化操作的類型大致也可以概述為兩個(gè)方面:其一您旁,virtio設(shè)備層面的初始化,例如指定virtio的基本操作函數(shù)集virtio_user_ops轴捎,在virtio_user_dev_init函數(shù)中初始化virtio_user_dev的virtio_user_backend_ops類型指針鹤盒,與back-end設(shè)備建立鏈接等;其二侦副,在eth_virtio_dev_init函數(shù)中初始化rte_eth_dev類型的設(shè)備侦锯,如設(shè)置其網(wǎng)絡(luò)特性的操作函數(shù)集virtio_eth_dev_ops,初始化virtqueue等秦驯。
????????3.DPDK應(yīng)用程序通過用戶態(tài)網(wǎng)絡(luò)設(shè)備訪問的函數(shù)接口完成數(shù)據(jù)的收發(fā)操作尺碰;
????????在DPDK應(yīng)用程序中執(zhí)行rte_eth_dev_start操作,設(shè)置rx\tx 處理函數(shù)、中斷處理函數(shù)亲桥,并將virtqueue的狀態(tài)通知給back-end設(shè)備洛心。在這之后DPDK應(yīng)用程序就可以通過rte_eth_tx_burst和rte_eth_rx_burst來執(zhí)行數(shù)據(jù)的發(fā)送和接收。
????????virtio-net-user用戶態(tài)驅(qū)動(dòng)可以通過testpmd程序來進(jìn)行測(cè)試题篷,由--vdev參數(shù)指定vdev驅(qū)動(dòng)的名字(形如net_virtio_user词身,或者net_virtio_user*,用于匹配virtio-net-user驅(qū)動(dòng))和用于鏈接用戶態(tài)back-end設(shè)備(vhost-net)的socket句柄文件(形如path=/var/tmp/socket0)番枚。
4.4.2 基于DPDK/SPDK的virtio back-end 驅(qū)動(dòng)的用戶態(tài)實(shí)現(xiàn)
????????virtio back-end設(shè)備用戶態(tài)實(shí)現(xiàn)邏輯工作在Host系統(tǒng)的DPDK/SPDK進(jìn)程中法严。當(dāng)前支持的back-end設(shè)備類型主要有: vhost-net、vhost-blk/vhost-scsi和vshot-vdpa葫笼。在DPDK/SPDK進(jìn)程中實(shí)現(xiàn)的virtio back-end設(shè)備一方面可以與Qemu進(jìn)程配合深啤,將實(shí)現(xiàn)的設(shè)備呈現(xiàn)為Guest系統(tǒng)下可見的pci controller供VM使用;另一方面也可以拋開Qemu直接和另外的用戶態(tài)進(jìn)程(如Container進(jìn)程等)直接通過unix socket對(duì)接路星,為bare-metal應(yīng)用提供服務(wù)溯街,此時(shí)的back-end設(shè)備所在進(jìn)程充當(dāng)server的角色。
????????virtio back-end設(shè)備用戶態(tài)實(shí)現(xiàn)的基本框架接口代碼是在 “DPDK/lib/vhost”目錄中洋丐,其主要的3個(gè)接口是:rte_vhost_driver_register呈昔、rte_vhost_driver_callback_register和rte_vhost_driver_start。對(duì)于上述幾種不同的virtio back-end設(shè)備的用戶態(tài)實(shí)現(xiàn)垫挨,都是在這個(gè)接口框架下來進(jìn)行工作韩肝。這也意味著virtio back-end設(shè)備的各種類型實(shí)現(xiàn)(其中包括vdpa)都是以vhost的形態(tài)對(duì)外提供服務(wù)触菜,或者都是在vhost 的接口框架下和front-end驅(qū)動(dòng)進(jìn)行交互九榔。
????????在rte_vhost_driver_register函數(shù)中,根據(jù)指定的文件路徑創(chuàng)建unix socket句柄涡相,并設(shè)置其為server的角色哲泊。對(duì)于各個(gè)virtio back-end的各個(gè)類型設(shè)備,其均為server的角色催蝗。對(duì)于KVM-Qemu使用場(chǎng)景下的Qemu進(jìn)程切威,其與vhost-user的back-end設(shè)備鏈接時(shí),其角色為client丙号。通過函數(shù)rte_vhost_driver_callback_register先朦,各個(gè)不同的back-end設(shè)備可以設(shè)置各自的創(chuàng)建和銷毀與一個(gè)front-end關(guān)聯(lián)關(guān)系的notify_ops操作函數(shù)集。而rte_vhost_driver_start函數(shù)的執(zhí)行則是啟動(dòng)vhost unix socket的監(jiān)聽犬缨,并設(shè)置請(qǐng)求處理的回調(diào)函數(shù)以實(shí)現(xiàn)在vhost_user_server_new_connection函數(shù)(其中可能會(huì)回調(diào)上述notify_ops中的new_connection函數(shù))中來處理從front-end驅(qū)動(dòng)發(fā)送過來的建鏈請(qǐng)求喳魏,且在其后以vhost_user_msg_handler來處理從鏈接上過來的消息(控制類消息)。
????????用戶態(tài)virtio back-end設(shè)備實(shí)現(xiàn)中怀薛,與front-end驅(qū)動(dòng)之間的virtqueue的vring對(duì)應(yīng)的內(nèi)存通過共享內(nèi)存方式來實(shí)現(xiàn)刺彩,并且由virtio front-end驅(qū)動(dòng)來分配,vhost back-end設(shè)備側(cè)根據(jù)front-end發(fā)送過來的控制消息調(diào)用vhost_user_set_mem_table函數(shù)進(jìn)行映射。
????????在vhost和vdpa的使用場(chǎng)景中创倔,推薦VM配置中添加vIOMMU以達(dá)到更安全的使用目的嗡害。
4.4.2.1 vhost-net back-end設(shè)備驅(qū)動(dòng)實(shí)現(xiàn)
????????vhost-net的back-end設(shè)備實(shí)現(xiàn)邏輯在 “DPDK/examples/vhost” 和 “DPDK/driver/net/vhost” 目錄下均有實(shí)現(xiàn),前者是實(shí)現(xiàn)了vhost-switch的功能畦攘,可以為VM提供數(shù)據(jù)轉(zhuǎn)發(fā)的功能霸妹;后者則是在DPDK框架中注冊(cè)一個(gè)eth端口,其背后實(shí)際是一個(gè)vhost-net的設(shè)備念搬,以實(shí)現(xiàn)像使用DPDK的普通eth設(shè)備(port)一樣處理virtio的數(shù)據(jù)和報(bào)文---從該eth port發(fā)送的報(bào)文被放到vritqueue中由vhost-net對(duì)應(yīng)的front-end驅(qū)動(dòng)接收抑堡,該eth port從vhost-net的virtqueue中接收來自front-ned驅(qū)動(dòng)發(fā)送過來的報(bào)文。此處以“DPDK/examples/vhost”的實(shí)現(xiàn)為例來概述vhost-net back-end設(shè)備的相關(guān)工作流程:
????????1.設(shè)置vhost back-end處理函數(shù)并開啟vhost server監(jiān)聽朗徊;
????????主要是根據(jù)用戶傳入的參數(shù)調(diào)用前述的“rte_vhost_driver_register首妖、rte_vhost_driver_callback_register和rte_vhost_driver_start” 函數(shù)來完成。需要注意的是通過rte_vhost_driver_callback_register設(shè)置的virtio_net_device_ops函數(shù)集到vsocket->notify_ops中用于處理和front-end驅(qū)動(dòng)關(guān)聯(lián)時(shí)的相應(yīng)操作爷恳。
????????2.響應(yīng)front-end驅(qū)動(dòng)的建鏈請(qǐng)求建立back-end設(shè)備與front-end驅(qū)動(dòng)的關(guān)聯(lián)有缆;
????????當(dāng)有virtio front-end驅(qū)動(dòng)鏈接vhost back-end設(shè)備時(shí),每個(gè)front-end對(duì)應(yīng)的關(guān)聯(lián)關(guān)系會(huì)在vhost_user_add_connection函數(shù)中創(chuàng)建一個(gè)virtio_net類型的數(shù)據(jù)結(jié)構(gòu)進(jìn)行標(biāo)識(shí)温亲。后續(xù)針對(duì)該virtio-front驅(qū)動(dòng)的消息處理均以此數(shù)據(jù)結(jié)構(gòu)歸集和查找棚壁。并且針對(duì)初始發(fā)送過來的數(shù)據(jù),在vhost_user_msg_handler會(huì)回調(diào)dev->notify_ops->new來進(jìn)行具體back-end定義的私有化處理栈虚。在當(dāng)前的流程中主要是進(jìn)一步創(chuàng)建了vhost_dev來跟蹤該鏈接關(guān)系袖外,并將其添加到分配的CPU核對(duì)應(yīng)的鏈表lcore_info[vdev->coreid].vdev_list中。
????????3.循環(huán)處理virtqueue中的數(shù)據(jù)魂务;
????????該程序邏輯在每個(gè)可用的CPU核上創(chuàng)建了一個(gè)線程循環(huán)運(yùn)行switch_worker函數(shù)曼验,循環(huán)處理各個(gè)vhost_dev對(duì)應(yīng)的數(shù)據(jù)收發(fā)。數(shù)據(jù)收發(fā)的過程可以分別簡(jiǎn)單歸納如下:
1)接收方向主要在drain_eth_rx函數(shù)中實(shí)現(xiàn)
????????A.通過rte_eth_rx_burst從指定的DPDK eth port收包粘姜;
????????B.通過rte_vhost_enqueue_burst將數(shù)據(jù)放入virtqueue傳給virtio front-end驅(qū)動(dòng)鬓照。
2)發(fā)送方向主要在drain_virtio_tx函數(shù)中實(shí)現(xiàn)
????????A.先通過vs_dequeue_pkts從virtqueue中接收?qǐng)?bào)文;
????????B.再通過virtio_tx_route將數(shù)據(jù)放入其他front-end設(shè)備對(duì)應(yīng)的virtqueue的接收buf或者通過指定的DPDK eth prot發(fā)送出去孤紧。
????????DPDK代碼中的這個(gè)vhost-net back-end設(shè)備的測(cè)試程序可以通過編譯DPDK時(shí)由 “-Dexamples=vhost” 來指定編譯豺裆,并參考34. Vhost Sample Application — Data Plane Development Kit 22.07.0-rc1 documentation 的說明來使用。
4.4.2.2 vhost-vdpa back-end設(shè)備
????????vhost-vdpa back-end設(shè)備的實(shí)現(xiàn)流程大體與vhost-net/vhost-blk/vhost-scsi一致号显。其主要差別在于:其一臭猜,支持vdpa的設(shè)備驅(qū)動(dòng)通過rte_vdpa_register_device函數(shù)注冊(cè)了rte_device和支持的功能接口到vdpa_device_list鏈表中,如此應(yīng)用程序可以通過rte_vhost_driver_attach_vdpa_device將其賦給vhost_user_socket并最終與標(biāo)識(shí)vhost設(shè)備的virtio_net數(shù)據(jù)結(jié)構(gòu)關(guān)聯(lián)押蚤;其二蔑歌,vdpa的vritqueue的處理均由硬件完成,因而不需要實(shí)現(xiàn)函數(shù)來周期性處理virtqueue中的數(shù)據(jù)活喊。當(dāng)前vhost-vdpa的實(shí)現(xiàn)都放在DPDK代碼中丐膝,且初步的后續(xù)計(jì)劃也是在DPDK中進(jìn)行支持量愧。vhost-vdpa的功能涉及的代碼主要是兩個(gè)部分,其一是vhost基本機(jī)制的代碼帅矗,即前以提到的“DPDK/lib/vhost” 目錄下的代碼偎肃;其二是vdpa設(shè)備驅(qū)動(dòng),主要在“DPDK/dirvers/vdpa” 目錄下浑此,該部分代碼實(shí)現(xiàn)的功能主要通過上述的rte_vdpa_register_device來對(duì)vhost 設(shè)備呈現(xiàn)并產(chǎn)生關(guān)聯(lián)累颂。vDPA的主要結(jié)構(gòu)框圖可參見圖4所示。
圖4. vDPA用戶態(tài)驅(qū)動(dòng)實(shí)現(xiàn)時(shí)的模塊關(guān)系
(IO路徑如紅色線標(biāo)識(shí))
????????DPDK代碼中現(xiàn)有支持的vdpa的設(shè)備驅(qū)動(dòng)目前主要有:ifc凛俱、mlx5和sfc這三種紊馏。這里以ifc驅(qū)動(dòng)的為例,將其主要機(jī)制概述如下:
- 匹配設(shè)備并調(diào)用vdpa設(shè)備驅(qū)動(dòng)進(jìn)行初始化蒲犬;
????????“DPDK/drivers/vdpa/ifc” 目錄下為Intel的SmartNIC的對(duì)應(yīng)vdpa驅(qū)動(dòng)朱监,其在DPDK框架中以普通的pci設(shè)備驅(qū)動(dòng)注冊(cè),如RTE_PMD_REGISTER_PCI(net_ifcvf, rte_ifcvf_vdpa)所示原叮。驅(qū)動(dòng)定義了支持的設(shè)備vendor ID和device ID赫编,當(dāng)啟動(dòng)時(shí)通過“-a”參數(shù)傳給DPDK進(jìn)程允許使用的設(shè)備被匹配到時(shí),就會(huì)調(diào)用ifcvf_pci_probe設(shè)備進(jìn)行初始化奋隶。在ifcvf_pci_probe函數(shù)中擂送,即會(huì)調(diào)用rte_vdpa_register_device來注冊(cè)vdpa設(shè)備和函數(shù)接口;
????????2. vhost機(jī)制獲取注冊(cè)的vdpa設(shè)備并在frond-end建鏈時(shí)關(guān)聯(lián)唯欣;
????????這個(gè)過程主要可以分成三個(gè)階段:
????????1) DPDK的vdpa應(yīng)用在調(diào)用前邊提到的rte_vhost_driver_start啟動(dòng)vhost server之前通過函數(shù) rte_vhost_driver_attach_vdpa_device嘹吨,將vdpa驅(qū)動(dòng)注冊(cè)的vdpa設(shè)備添加到標(biāo)識(shí)server的vhost_user_socket 句柄中描述數(shù)據(jù)結(jié)構(gòu)中;
????????2) 當(dāng)vhost server響應(yīng)front-end驅(qū)動(dòng)發(fā)起的建鏈請(qǐng)求時(shí)境氢,即會(huì)在vhost_user_add_connection中執(zhí)行vhost_attach_vdpa_device將vdpa設(shè)備復(fù)制給描述與這個(gè)front-end驅(qū)動(dòng)關(guān)系鏈接的virtio_net數(shù)據(jù)結(jié)構(gòu)中蟀拷;
????????3) 當(dāng)vhost_user_msg_handler處理front-end發(fā)送過來的控制消息時(shí),會(huì)獲取vdpa的設(shè)備产还,且第一執(zhí)行時(shí)會(huì)通過“vdpa_dev->ops->dev_conf(dev->vid, vdpa_qid)” 調(diào)用來通知硬件設(shè)備配置好virtqueue匹厘。
?? ? ? ? 3. vdpa硬件設(shè)備處理front-end驅(qū)動(dòng)的IO請(qǐng)求并進(jìn)行回應(yīng)嘀趟;
????????vdpa模式下脐区,virtqueue的數(shù)據(jù)處理由硬件完成,因而在注冊(cè)的 “notify_ops->new_device” 函數(shù)接口中她按,不需要執(zhí)行virtqueue相關(guān)的處理操作牛隅。
????????DPDK代碼中現(xiàn)可跑起來的vdpa的example在 “DPDK/examples/vdpa” 目錄下∽锰可以通過編譯DPDK時(shí)由 “-Dexamples=vdpa” 來指定編譯媒佣,并參考37. Vdpa Sample Application — Data Plane Development Kit 22.07.0-rc1 documentation 中的說明進(jìn)行使用。
參考鏈接
dpdk對(duì)虛擬化的支持調(diào)研 - allcloud - 博客園
DPDK系列之十二:基于virtio陵刹、vhost和OVS-DPDK的容器數(shù)據(jù)通道_cloudvtech的博客-CSDN博客_dpdk容器化
DPDK系列之六:qemu-kvm網(wǎng)絡(luò)后端的加速技術(shù)_cloudvtech的博客-CSDN博客_kvm加速
DPDK系列之十五:Virtio技術(shù)分析之一默伍,virtio基礎(chǔ)架構(gòu)_cloudvtech的博客-CSDN博客_virtio
從dpdk1811看virtio1.1 的實(shí)現(xiàn)—packed ring-lvyilong316-ChinaUnix博客
Qemu模擬IO和半虛擬化Virtio的區(qū)別以及I/O半虛擬化驅(qū)動(dòng)介紹_weixin_34051201的博客-CSDN博客
virtio-net - 網(wǎng)絡(luò)半虛擬化 - 知乎
DPU和CPU互聯(lián)的接口之爭(zhēng):Virtio還是SR-IOV? - 極術(shù)社區(qū) - 連接開發(fā)者與智能計(jì)算生態(tài)
virtio簡(jiǎn)介(一)—— 框架分析 - Edver - 博客園
KVM之Virtio介紹 (十五) - 程序員大本營(yíng)
虛擬化之Virtio-Net基礎(chǔ)篇-51CTO.COM
Linux Kernel Vhost 架構(gòu) - 于楊 - 博客園