最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

簡單分析Linux虛擬化KVM-Qemu之vhost-net

2023-03-01 21:34 作者:補給站Linux內(nèi)核  | 我要投稿

說明:

  1. KVM版本:5.9.1

  2. QEMU版本:5.0.0

  3. 工具:Source Insight 3.5, Visio

1. 概述

讓我們先來看看問題的引入,在之前的virtio系列文章中,網(wǎng)絡(luò)虛擬化的框架如下圖所示:

  • Qemu中的virtio-net設(shè)備數(shù)據(jù)包收發(fā),通過用戶態(tài)訪問tap設(shè)備完成的;

  • 收發(fā)過程涉及Guest OS,KVM,Qemu中的virtio-net設(shè)備,Host中的網(wǎng)絡(luò)協(xié)議棧等的交互,路徑長并且涉及的切換多,帶來了性能的損耗;

  • vhost-net的引入,就是將vitio-net后端設(shè)備的數(shù)據(jù)處理模塊下沉到Kernel中,從而提高整體的效率;

vhost-net的框架圖如下:

  • 從圖中可以看出,Guest的網(wǎng)絡(luò)數(shù)據(jù)交互直接可以通過vhost-net內(nèi)核模塊進(jìn)行處理,而不再需要從內(nèi)核態(tài)切換回用戶態(tài)的Qemu進(jìn)程中進(jìn)行處理;

  • 之前的文章分析過virtio設(shè)備與驅(qū)動,針對數(shù)據(jù)傳遵循virtio協(xié)議,因此vhost-net中需要去實現(xiàn)virtqueue的相關(guān)機制;

本文將分析vhost-net的原理,只說重點,進(jìn)入主題。

2. 數(shù)據(jù)結(jié)構(gòu)

vhost-net內(nèi)核模塊的層次結(jié)構(gòu)如下圖:

  • struct vhost_net:用于描述Vhost-Net設(shè)備。它包含幾個關(guān)鍵字段:1)struct vhost_dev,通用的vhost設(shè)備,可以類比struct device結(jié)構(gòu)體內(nèi)嵌在其他特定設(shè)備的結(jié)構(gòu)體中;2)struct vhost_net_virtqueue,實際上對struct vhost_virtqueue進(jìn)行了封裝,用于網(wǎng)絡(luò)包的數(shù)據(jù)傳輸;3)struct vhost_poll,用于socket的poll,以便在數(shù)據(jù)包接收與發(fā)送時進(jìn)行任務(wù)調(diào)度;

  • struct vhost_dev:描述通用的vhost設(shè)備,可內(nèi)嵌在基于vhost機制的其他設(shè)備結(jié)構(gòu)體中,比如struct vhost_net,struct vhost_scsi等。關(guān)鍵字段如下:1)vqs指針,指向已經(jīng)分配好的struct vhost_virtqueue,對應(yīng)數(shù)據(jù)傳輸;2)work_list,任務(wù)鏈表,用于放置需要在vhost_worker內(nèi)核線程上執(zhí)行的任務(wù);3)worker,用于指向創(chuàng)建的內(nèi)核線程,執(zhí)行任務(wù)列表中的任務(wù);

  • struct vhost_virtqueue:用于描述設(shè)備對應(yīng)的virtqueue,這部分內(nèi)容可以參考之前virtqueue機制分析,本質(zhì)上是將Qemu中virtqueue處理機制下沉到了Kernel中。關(guān)鍵字段如下:1)struct vhost_poll,用于poll eventfd對應(yīng)的文件,當(dāng)不滿足處理請求時會添加到eventfd對應(yīng)的等待隊列中,而一旦被喚醒,該結(jié)構(gòu)體中的struct vhost_work(執(zhí)行函數(shù)被初始化為handle_tx_kick,以發(fā)送為例)將被放置到內(nèi)核線程中去執(zhí)行;

? 結(jié)構(gòu)體的核心圍繞著數(shù)據(jù)和通知機制,其中數(shù)據(jù)在vhost_virtqueue中體現(xiàn),而通知主要是通過vhost_poll來實現(xiàn),具體的細(xì)節(jié)下文將進(jìn)一步描述。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)??

3. 流程分析

3.1 初始化

vhost-net為內(nèi)核模塊,注冊為misc設(shè)備,Qemu通過系統(tǒng)調(diào)用接口與內(nèi)核交互,Qemu中的初始化如下圖:

  • Qemu中tap設(shè)備初始化在net_init_tap中完成,其中net_init_tap_one打開vhost-net設(shè)備文件,用于與內(nèi)核的vhost-net交互;

  • vhost_set_backend_type:設(shè)置vhost的后端類型,以及vhost的操作函數(shù)集。目前有兩種vhost后端,一種是在內(nèi)核態(tài)實現(xiàn)的virtio后端,一種是在用戶態(tài)中實現(xiàn)的virtio后端;

  • kernel_ops:vhost的內(nèi)核操作函數(shù)集,都是一些回調(diào)函數(shù)的實現(xiàn),最終會通過vhost_kernel_call-->ioctl-->vhost-net.ko路徑,進(jìn)行配置;

ioctl系統(tǒng)調(diào)用,與驅(qū)動交互簡單來說可以分為三大類,下邊分別介紹幾個關(guān)鍵的設(shè)置:

  1. vhost net設(shè)置

    • VHOST_SET_OWNER:底層會為調(diào)用者創(chuàng)建一個內(nèi)核線程,對應(yīng)到前文中數(shù)據(jù)結(jié)構(gòu)中的vhost_worker,同時在vhost_dev結(jié)構(gòu)體中還會保存調(diào)用者線程的內(nèi)存空間數(shù)據(jù)結(jié)構(gòu);

    • VHOST_NET_SET_BACKEND:設(shè)置vhost-net的后端設(shè)備,比如Qemu往內(nèi)核態(tài)傳遞的tap設(shè)備對應(yīng)的fd,從而讓vhost-net直接與tap設(shè)備進(jìn)行通信;

  2. vhost dev設(shè)置

    從Guest OS中的虛擬地址到最終的Host上的物理地址映射關(guān)系如上圖所示,如果在Guest OS中要將數(shù)據(jù)發(fā)送出去,實際上只需要將Qemu中關(guān)于Guest OS的物理地址布局信息傳遞下去,此外再結(jié)合VHOST_SET_OWNER時傳遞的內(nèi)存空間信息,就可以根據(jù)映射關(guān)系找到Guest OS中的數(shù)據(jù)對應(yīng)到Host之上的物理地址,完成最后搬運即可;

    • VHOST_SET_MEM_TABLE:將Qemu中的虛擬機物理地址布局信息傳遞給內(nèi)核,為了解釋清楚這個問題,可以回顧一下之前內(nèi)存虛擬化中的一張圖:

  1. vhost vring設(shè)置

    • VHOST_SET_VRING_KICK:設(shè)置vhost-net模塊前端virtio驅(qū)動發(fā)送通知時觸發(fā)的eventfd,通知機制,最終觸發(fā)handle_kick函數(shù)的執(zhí)行;

    • VHOST_SET_VRING_CALL:設(shè)置vhost-net后端到虛擬機virtio前端的中斷通知,參考之前文章中的irqfd機制;

    • 此外關(guān)于vring的設(shè)備還包括vring的大小,地址信息等;

上述的這些設(shè)置的流程路徑如下,只畫出了關(guān)鍵路徑:

  • 當(dāng)Guest OS中的virtio-net驅(qū)動完成初始化后,會通過vp_set_status來設(shè)置狀態(tài),以通知后端驅(qū)動已經(jīng)ready,此時會觸發(fā)VM的退出并進(jìn)入KVM進(jìn)行異常處理,最終路由給Qemu;

  • Qemu中的vcpu線程監(jiān)測異常,當(dāng)檢測到KVM_EXIT_MMIO時,去回調(diào)注冊該IO區(qū)域的讀寫函數(shù),比如virtio_pci_common_write函數(shù),在該函數(shù)中逐級往下最終調(diào)用到vhost_net_start函數(shù);

  • vhost_net_start中最終去通過kernel_ops函數(shù)集去設(shè)置底層并交互;

初始化完成后,接下來讓我們看看數(shù)據(jù)的發(fā)送與接收,為了能將整個流程表達(dá)清楚,我會將完整的圖拆分成幾個步驟來講述。

3.2 數(shù)據(jù)發(fā)送

1)

發(fā)送前的框圖如下:

  • Guest OS中的virtio-net驅(qū)動中維護(hù)兩個virtqueue,分別用于發(fā)送和接收;

  • 圖中的datagram表示的是需要發(fā)送的數(shù)據(jù);

  • KVM模塊提供了ioeventfdirqfd用于通知機制;

  • vhost-net模塊中創(chuàng)建好了vhost_worker內(nèi)核線程,用于處理任務(wù);

2)

  • 當(dāng)數(shù)據(jù)包準(zhǔn)備好之后,通過往kick fd上觸發(fā)信號,從而喚醒vhost_worker內(nèi)核線程來調(diào)用handle_tx_kick進(jìn)行數(shù)據(jù)的發(fā)送;

  • 當(dāng)Tap/Tun不具備發(fā)送條件時,vhost_worker會poll在socket上,等待Tap/Tun的喚醒,一旦被喚醒后可以調(diào)用handle_tx_net發(fā)送;

  • 最終的handle_tx完成具體的發(fā)送;

3)


  • vhost_get_vq_desc函數(shù)在vritqueue中查找可用的buffer,并將信息存儲到iov中,以便更好的訪問;

  • sock->ops->sendmsg()函數(shù),實際調(diào)用的是tun_sendmsg函數(shù),在該函數(shù)中分配了skb結(jié)構(gòu)體,并將iov[]中的信息傳遞過來,最終如圖中所示完成數(shù)據(jù)的拷貝和發(fā)送,通過NIC發(fā)送出去;

4)

  • 數(shù)據(jù)發(fā)送完畢后,通過irqfd機制通知vcpu;

3.3 數(shù)據(jù)接收

數(shù)據(jù)的接收是發(fā)送的逆過程,流程一致:

1)

  • 初始化部分與發(fā)送過程一致;

  • Tap/Tun驅(qū)動從NIC接收到數(shù)據(jù)包,準(zhǔn)備發(fā)送給vhost-net;

2)

  • vhost-net中的vhost_worker線程也poll在兩個fd之上,與發(fā)送端類似;

  • kick fd上觸發(fā)信號時最終調(diào)用handle_rx_kick函數(shù),Tap/Tun對應(yīng)的socket上觸發(fā)信號時,調(diào)用handle_rx_net函數(shù);

  • 最終通過handle_rx來完成實際的接收;

3)

  • 接收過程中,vhost_get_vq_desc獲取virtqueue中的可用buffer,并將信息存儲到iov[]中;

  • sock->ops->recvmsg()函數(shù)實際指向tun_recvmsg函數(shù),在該函數(shù)中最終完成數(shù)據(jù)的傳遞;

4)

  • 數(shù)據(jù)接收完成后,通過irqfd機制通過vcpu,從而在Guest OS中進(jìn)行處理;

原文作者:LoyenWang





簡單分析Linux虛擬化KVM-Qemu之vhost-net的評論 (共 條)

分享到微博請遵守國家法律
兴山县| 曲阳县| 广灵县| 根河市| 七台河市| 深水埗区| 茂名市| 阳江市| 枣阳市| 明水县| 宁波市| 滦平县| 竹溪县| 界首市| 遂昌县| 平湖市| 北宁市| 察雅县| 正阳县| 阳城县| 靖西县| 休宁县| 资溪县| 吉林省| 江安县| 库伦旗| 洪江市| 涿鹿县| 古交市| 昌邑市| 克什克腾旗| 长沙市| 介休市| 安国市| 阿合奇县| 即墨市| 巍山| 长春市| 隆尧县| 吴江市| 墨竹工卡县|