Vhost庫實現了一個用戶空間virtio網絡服務器,允許用戶直接操作virtio。 換句話說,它允許用戶通過VM virtio網絡設備獲取/發送數據包。 爲了達到這個功能,一個vhost庫需要實現:
訪問guest內存:
- 對於QEMU,這是通過使用 -object memory-backend-file,share=on,… 選項實現的。這意味着QEMU將創建一個文件作爲guest RAM。 選項 share=on 允許另一個進程映射該文件,這意味着該進程可以訪問這個guest RAM。
知道關於vring所有必要的信息:
- 諸如可用環形存儲鏈表的存儲空間。Vhost定義了一些消息(通過Unix套接字傳遞)來告訴後端所有需要知道如何操作vring的信息。
1、vhost API 概述
以下是一些關鍵的Vhost API函數概述:
-
rte_vhost_driver_register(path, flags)
此函數將vhost驅動程序註冊到系統中。path 指定Unix套接字的文件路徑。
當前支持的flags包括:-
RTE_VHOST_USER_CLIENT
當使用該flag時,DPDK vhost-user 作爲客戶端。 請參閱以下說明。 -
RTE_VHOST_USER_NO_RECONNECT
當 DPDK vhost-user 作爲客戶端時,它將不斷嘗試連接到服務端(QEMU),知道成功。 這在以下兩個情況中是非常有用的:- 當 QEMU 還沒啓動時
- 當 QEMU 重啓時(如guset OS 重啓)
這個重新連接選項是默認啓用的,但是,可以通過設置這個標誌來關閉它。
-
RTE_VHOST_USER_DEQUEUE_ZERO_COPY
設置此flag時將啓用出隊了零複製。默認情況下是禁用的。
在設置此標誌時,需要知道以下原則:- 零拷貝對於小數據包(小於512)是不好的。
- 零拷貝對VM2VM情況比較好。對於兩個虛擬機之間的ipref,提升性能可能高達70%(當TSO使能時).
- 對於VM2NIC情況,nb_tx_desc 必須足夠小:如果未啓動virtio間接特性則 <=64,否則 <= 128。
這是因爲,當啓用出隊列零拷貝時,只有當相應的mbuf被釋放時,客戶端TX使用的vring纔會被更新。 因此,nb_tx_desc必須足夠小,以便PMD驅動程序將耗盡可用的TX描述符,並及時釋放mbufs。 否則,guset TX vring將無mbuf使用。 - Guest的內存應該使用應該使用huge page支持以獲得更好的性能。最好使用1G大小的頁面。
當啓用出隊零拷貝時,必須建立guest 物理地址和host物理地址之間的映射。 使用non-huge page則意味着更多的頁面細分。 爲了簡單起見,DPDK vhost對這些段進行了線性搜索,因此,段越少,我們得到的映射就越快。 注意:將來我們可能使用樹搜索來提升速度。
-
-
rte_vhost_driver_set_features(path, features)
此函數設置vhost-user驅動支持的功能位。 vhost-user驅動可以是vhost-user net,但也可以是其他的,例如vhost-user SCSI。 -
rte_vhost_driver_callback_register(path, vhost_device_ops)
此函數註冊一組回調函數,以便在發生某些事件時讓DPDK應用程序採取適當的操作。 目前支持以下事件:-
new_device(int vid)
這個回調在virtio設備準備就緒時調用,vid 是虛擬設備ID。 -
destroy_device(int vid)
當virtio設備關閉時(或vhost連接中斷),調用此函數處理。 -
vring_state_changed(int vid, uint16_t queue_id, int enable)
當特定隊列的狀態發生改變,如啓用或禁用,將調用此回調。 -
features_changed(int vid, uint64_t features)
這個函數在feature改變時被調用。例如,VHOST_F_LOG_ALL 將分別在實時遷移的開始/結束時設置/清除。
-
-
rte_vhost_driver_disable/enable_features(path, features))
該函數禁用或啓用某些功能。例如,可以使用它來禁用可合併的緩衝區和TSO功能,這兩個功能默認都是啓用的。 -
rte_vhost_driver_start(path)
這個函數觸發vhost-user協商。它應該在初始化一個vhost-user驅動程序結束時被調用。 -
rte_vhost_enqueue_burst(vid, queue_id, pkts, count)
傳輸(入隊)從host到guest的 count 包。 -
rte_vhost_dequeue_burst(vid, queue_id, mbuf_pool, pkts, count)
接收(出隊)來自guest的 count 包,並將它們存儲在 pkts。
2、vhost-user 實現
vhost-user 使用Unix套接字來傳遞消息。這意味着DPDK vhost-user的實現具有兩種角色:
- DPDK vhost-user作爲server: DPDK 將創建一個Unix套接字服務器文件,並監聽來自前端的連接。
注意,這是默認模式,也是DPDK v16.07之前的唯一模式。 - DPDK vhost-user最爲client: 與服務器模式不同,此模式不會創建套接字文件;
它只是試圖連接到服務器(而不是創建文件的響應)。 - 當DPDK vhost-user應用程序重新啓動時,DPDK vhost-user將嘗試再次連接到服務器。這是“重新連接”功能的工作原理。
注意:“重連” 功能需要 QEMU v2.7 及以上的版本。
vhost支持的功能在重新啓動之前和之後必須完全相同。例如,如果TSO被禁用,但是重啓之後被啓用了,將導致未定義的錯誤。
無論使用哪種模式,建立連接之後,DPDK vhost-user 都將開始接收和處理來自QEMU的vhost消息。
對於帶有文件描述符的消息,文件描述符可以直接在vhost進程中使用,因爲它已經被Unix套接字安裝了。
當前支持的vhost 消息包括:
- VHOST_SET_MEM_TABLE
- VHOST_SET_VRING_KICK
- VHOST_SET_VRING_CALL
- VHOST_SET_LOG_FD
- VHOST_SET_VRING_ERR
對於 VHOST_SET_MEM_TABLE 消息,QEMU將在消息的輔助數據中爲每個存儲區域及其文件描述符發送信息。 文件描述符用於映射該區域。
VHOST_SET_VRING_KICK 用作將vhost設備放入數據面的信號, VHOST_GET_VRING_BASE 用作從數據面移除vhost設備的信號。
當套接字連接關閉,vhost將銷燬設備。
3、支持vhost的vSwitch
有關更多vhost詳細信息以及如何在vSwitch中支持vhost,請參閱《DPDK Sample Applications Guide》。