0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

淺談vhost的數(shù)據(jù)路徑硬件化 DPDK中的vDPA實(shí)現(xiàn)方案

454398 ? 來(lái)源: Chinaunix ? 作者:lvyilong316 ? 2020-09-25 15:32 ? 次閱讀

vDPA就是VHOST DATA PATH ACCELERATION,即將vhost的數(shù)據(jù)路徑硬件化,如下圖所示。

只把dataplane硬件化對(duì)于網(wǎng)卡廠商要相對(duì)容易實(shí)現(xiàn),否則如果要求dataplane和controlplane都需要硬件支持,這就要求硬件的dataringlayout需要和virtio一致,還需要controlplane的PCIbar和virtiospec一致,而硬件廠商通常有自己定制的pcibar。不過(guò)在智能網(wǎng)卡的裸金屬服務(wù)器場(chǎng)景,廠商也在做full emulation,即控制面也相對(duì)硬件化的方案,我們這只討論正常的dataplane硬件化。

對(duì)于kernel的vDPA方案如下圖所示。

這里面有幾個(gè)關(guān)鍵組件需要介紹一下。

vhost-mdev

在介紹vhost-mdev前需要先介紹virtio-mdev框架,說(shuō)起virtio-mdev又不得不先講vfio-mdev。

vfio-mdev

先快速對(duì)vfio的概念進(jìn)行掃盲。這個(gè)掃盲的目的不是詳細(xì)介紹什么是VFIO,而是給對(duì)沒(méi)有vfio的讀者一個(gè)入門(mén)的指引。

vfio是Linux Kernel UIO特性的升級(jí)版本。UIO的作用是把一個(gè)設(shè)備的IO和中斷能力暴露給用戶態(tài),從而實(shí)現(xiàn)在用戶態(tài)對(duì)硬件的直接訪問(wèn)。它的基本實(shí)現(xiàn)方法是,當(dāng)我們probe一個(gè)設(shè)備的時(shí)候,通過(guò)uio_register_device()注冊(cè)為一個(gè)字符設(shè)備/dev/uioN,用戶程序通過(guò)對(duì)這個(gè)設(shè)備mmap訪問(wèn)它的IO空間,通過(guò)read/select等接口等待中斷。

UIO的缺點(diǎn)在于,用戶態(tài)的虛擬地址無(wú)法直接用于做設(shè)備的DMA地址(因?yàn)樵谟脩魬B(tài)無(wú)法知道DMA內(nèi)存的物理地址),這樣限制了UIO的使用范圍。我們有人通過(guò)UIO設(shè)備自己的ioctl來(lái)提供求物理地址的機(jī)制,從而實(shí)現(xiàn)DMA,但這種方案是有風(fēng)險(xiǎn)的。這里提到的UIO的缺點(diǎn),基本上拒絕了大流量IO設(shè)備使用該機(jī)制提供用戶空間訪問(wèn)的能力了。

vfio通過(guò)IOMMU的能力來(lái)解決這個(gè)問(wèn)題。IOMMU可以為設(shè)備直接翻譯虛擬地址,這樣我們?cè)谔峁┨摂M地址給設(shè)備前,把地址映射提供給vfio,vfio就可以為這個(gè)設(shè)備提供頁(yè)表映射,從而實(shí)現(xiàn)用戶程序的DMA操作。背負(fù)提供DMA操作這個(gè)使命,VFIO要解決一個(gè)更大的問(wèn)題,就是要把設(shè)備隔離掉。在Linux的概念中,內(nèi)核是可信任的,用戶程序是不可信任的,如果我們?cè)试S用戶程序?qū)υO(shè)備做DMA,那么設(shè)備也是不可信任的,我們不能允許設(shè)備訪問(wèn)程序的全部地址空間(這會(huì)包括內(nèi)核),所以,每個(gè)設(shè)備,針對(duì)每個(gè)應(yīng)用,必須有獨(dú)立的頁(yè)表。這個(gè)頁(yè)表,通過(guò)iommu_group承載(iommu_group.domain),和進(jìn)程的頁(yè)表相互獨(dú)立。進(jìn)程必須主動(dòng)做DMA映射,才能把對(duì)應(yīng)的地址映射寫(xiě)進(jìn)去。

所以vfio的概念空間是container和group,前者代表設(shè)備iommu的格式,后者代表一個(gè)獨(dú)立的iommu_group(vfio中用vfio_group代表),我們先創(chuàng)建container,然后把物理的iommu_group綁定到container上,讓container解釋group,之后我們基于group訪問(wèn)設(shè)備(IO,中斷,DMA等等)即可。

這個(gè)邏輯空間其實(shí)是有破綻的,iommu_group是基于設(shè)備來(lái)創(chuàng)建的,一個(gè)設(shè)備有一個(gè)iommu_group(或者如果這個(gè)設(shè)備和其他設(shè)備共享同一個(gè)IOMMU硬件,是幾個(gè)設(shè)備才有一個(gè)iommu_group),那如果我兩個(gè)進(jìn)程要一起使用同一個(gè)設(shè)備呢?基于現(xiàn)在的架構(gòu),你只能通過(guò)比如VF(Virtual Function,虛擬設(shè)備),在物理上先把一個(gè)設(shè)備拆成多個(gè),然后還是一個(gè)進(jìn)程使用一個(gè)設(shè)備。這用于虛擬機(jī)還可以,但如果用于其他功能,基本上是沒(méi)戲了。

再說(shuō),VF功能基本都依賴(lài)SR-IOV這樣的實(shí)現(xiàn),也不是你想用就能用的。這我們就要引出vfio-mdev(以下簡(jiǎn)稱(chēng)mdev)了。

mdev本質(zhì)上是在vfio層面實(shí)現(xiàn)VF功能。在mdev的模型中,通過(guò)mdev_register_device()注冊(cè)到mdev中的設(shè)備稱(chēng)為父設(shè)備(parent_dev),但你用的時(shí)候不使用父設(shè)備,而是通過(guò)父設(shè)備提供的機(jī)制(在sysfs中,后面會(huì)詳細(xì)談這個(gè))創(chuàng)建一個(gè)mdev,這個(gè)mdev自帶一個(gè)iommu_group,這樣,你有多個(gè)進(jìn)程要訪問(wèn)這個(gè)父設(shè)備的功能,每個(gè)都可以有獨(dú)立的設(shè)備頁(yè)表,而且互相不受影響。

所以,整個(gè)mdev框架包括兩個(gè)基本概念,一個(gè)是pdev(父設(shè)備),一個(gè)是mdev(注意,我們這里mdev有時(shí)指整個(gè)vfio-mdev的框架,有時(shí)指基于一個(gè)pdev的device,請(qǐng)注意區(qū)分上下文)。前者提供設(shè)備硬件支持,后者支持針對(duì)一個(gè)獨(dú)立地址空間的請(qǐng)求。

兩者都是device(struct device),前者的總線是真實(shí)的物理總線,后者屬于虛擬總線mdev,mdev上只有一個(gè)驅(qū)動(dòng)vfio_mdev,當(dāng)你通過(guò)pdev創(chuàng)建一個(gè)mdev的時(shí)候,這個(gè)mdev和vfio_mdev驅(qū)動(dòng)匹配,從而給用戶態(tài)暴露一個(gè)普通vfio設(shè)備的接口(比如platform_device或者pci_device)的接口。

換句話說(shuō),如果一個(gè)設(shè)備需要給多個(gè)進(jìn)程提供用戶態(tài)驅(qū)動(dòng)的訪問(wèn)能力,這個(gè)設(shè)備在probe的時(shí)候可以注冊(cè)到mdev框架中,成為一個(gè)mdev框架的pdev。之后,用戶程序可以通過(guò)sysfs創(chuàng)建這個(gè)pdev的mdev。

pdev注冊(cè)需要提供如下參數(shù)

點(diǎn)擊(此處)折疊或打開(kāi)

struct mdev_parent_ops{

struct module*owner;

conststruct attribute_group**dev_attr_groups;

conststruct attribute_group**mdev_attr_groups;

struct attribute_group**supported_type_groups;

int(*create)(struct kobject*kobj,struct mdev_device*mdev);

int(*remove)(struct mdev_device*mdev);

int(*open)(struct mdev_device*mdev);

void(*release)(struct mdev_device*mdev);

ssize_t(*read)(struct mdev_device*mdev,char __user*buf,

size_t count,loff_t*ppos);

ssize_t(*write)(struct mdev_device*mdev,constchar __user*buf,

size_t count,loff_t*ppos);

long(*ioctl)(struct mdev_device*mdev,unsignedintcmd,

unsigned long arg);

int(*mmap)(struct mdev_device*mdev,struct vm_area_struct*vma);

};

其中三個(gè)attribute_group都用于在sysfs中增加一組屬性。device本身根據(jù)它的bus_type,就會(huì)產(chǎn)生一個(gè)sysfs的屬性組(所謂屬性組就是sysfs中的一個(gè)目錄,里面每個(gè)文件就是一個(gè)“屬性”,文件名就是屬性名,內(nèi)容就是屬性的值),假設(shè)你的pdev是/sys/bus/platform/devices/abc.0,那么這三個(gè)attribute_group產(chǎn)生的屬性分別在:

dev_attr_groups:/sys/bus/platform/devices/abc.0下

mdev_attr_groups:/sys/bus/platform/devices/abc.0/下,/sys/bus/mdev/devices中有這個(gè)設(shè)備的鏈接

supported_type_groups:/sys/bus/platform/devices/abc.0/mdev_supported_types/下,里面有什么屬性是框架規(guī)定的,包括:

1)name:設(shè)備名稱(chēng)

2)available_instances:還可以創(chuàng)建多少個(gè)實(shí)例

3)device_api:設(shè)備對(duì)外的接口API標(biāo)識(shí)

這些參數(shù)支持具體用戶態(tài)驅(qū)動(dòng)如何訪問(wèn)這個(gè)設(shè)備,pdev的驅(qū)動(dòng)當(dāng)然可以增加更多。mdev框架在這個(gè)目錄中還增加如下屬性:

1)devices:這是一個(gè)目錄,鏈接向所有被創(chuàng)建的mdev

2)create:向這個(gè)文件中寫(xiě)入一個(gè)uuid就可以創(chuàng)建一個(gè)新的mdev,實(shí)際上產(chǎn)生對(duì)mdev_parent_ops.create()的回調(diào);

mdev這個(gè)模型建得最不好的地方是,create的時(shí)候只能傳進(jìn)去一個(gè)uuid,不能傳進(jìn)去參數(shù),這樣如果我創(chuàng)建的設(shè)備需要參數(shù)怎么辦呢?那就只能創(chuàng)建以后再設(shè)置了,這增加了“創(chuàng)建以后沒(méi)有足夠資源提供”的可能性),不過(guò)看起來(lái),大部分情況我們是可以接受這個(gè)限制的。

virtio-mdev

說(shuō)完了vfio-mdev再來(lái)看看virtio-mdev。我們?yōu)槭裁匆雟fio-mdev,因?yàn)闉榱似帘尾煌瑥S商的配置接口差異需要一個(gè)中間層,而這個(gè)中間層就是基于vfio-mdev的virtio-mdev。virtio-mdev框架的主要目的是提供給不同的vDPA網(wǎng)卡廠家一個(gè)標(biāo)準(zhǔn)的API來(lái)實(shí)現(xiàn)他們自己的控制路徑。mdev提供的框架可以支持vDPA實(shí)現(xiàn)數(shù)據(jù)和控制路徑的分離。數(shù)據(jù)路徑硬化,控制路徑在軟件實(shí)現(xiàn)。

這個(gè)驅(qū)動(dòng)可以是用戶態(tài)基于VFIO,也可以是內(nèi)核態(tài)基于virtio的。在目前這個(gè)系列,主要關(guān)注基于vfio的用戶態(tài)驅(qū)動(dòng),但是在未來(lái)也會(huì)討論基于virtio的內(nèi)核態(tài)驅(qū)動(dòng),比如支持AF_VIRTIO。

這個(gè)驅(qū)動(dòng)的實(shí)現(xiàn)也比較簡(jiǎn)單,本質(zhì)上就是一些列的virtio-mdev的API。主要包含:

1)set/get設(shè)備的配置空間

2)set/get virtqueue的元數(shù)據(jù):vring地址,大小和基地址

3)kick一個(gè)特定的virtqueue

4)為一個(gè)特定的virtqueue注冊(cè)回調(diào)中斷

5)協(xié)商功能

6)set/get臟頁(yè)日志

7)啟動(dòng)/重置設(shè)備

可以看到這就是virtio消息處理的功能,所以virtio-mdev就是一個(gè)抽象層,對(duì)上提供統(tǒng)一的接口來(lái)支持virtio的配置,對(duì)下屏蔽不同廠商的差異,每個(gè)廠商實(shí)現(xiàn)自己的這些接口注冊(cè)進(jìn)來(lái)。

vhost-mdev

vhost-mdev是一個(gè)kernel的模塊,主要功能是:

(1)轉(zhuǎn)發(fā)用戶空間的virtio命令到virtio mdev的API(這里看出vhost-mdev是在virtio-mdev之上的);

(2)復(fù)用VFIO的框架來(lái)準(zhǔn)備DMA映射和解映射的用戶空間請(qǐng)求。

vhost-mdev相當(dāng)于一個(gè)直接和qemu對(duì)接的,類(lèi)似于vhost-net的角色,不過(guò)它只是一個(gè)轉(zhuǎn)換的作用,將qemu發(fā)過(guò)來(lái)的virtio命令轉(zhuǎn)換為virtio mdev的標(biāo)準(zhǔn)API調(diào)用(如set_feature,get_feature)。

vhost-mdev通常的工作流程如下:

(1)把自己注冊(cè)成一個(gè)新類(lèi)型的mdev驅(qū)動(dòng)

(2)對(duì)外提供和vhost-net兼容的ioctl接口,用戶空間的VFIO驅(qū)動(dòng)可以傳遞virtio的命令

(3)翻譯好的virtio命令以virtio mdev API的形式通過(guò)mdev bus傳遞給virtio-mdev設(shè)備。

(4)當(dāng)一個(gè)新的mdev設(shè)備創(chuàng)建時(shí),kernel總是廠商去加載驅(qū)動(dòng)

(5)在加載過(guò)程中,vhost-mdev會(huì)把virtio mdev設(shè)備連接在VFIO的群組,因此DMA請(qǐng)求就可以通過(guò)VFIO的文件描述符。

vhost-mdev是連接用戶空間驅(qū)動(dòng)和virtio-mdev設(shè)備的關(guān)鍵。它為用戶空間驅(qū)動(dòng)提供兩個(gè)文件描述符:

1)vhost-mdev FD:從用戶空間接受vhost的控制命令

2)VFIO container FD:用戶空間驅(qū)動(dòng)用來(lái)設(shè)置DMA

vhost-vfio

vhost-vfio從QEMU的觀點(diǎn)來(lái)看,vhost-vfio就是一個(gè)新類(lèi)型的QEMU網(wǎng)路后端用來(lái)支持virtio-net的設(shè)備。(注意,vhost-vfio是在qemu側(cè)工作的)它的主要作用是:

(1)設(shè)置vhost-mdev設(shè)備:打開(kāi)vhost-mdev的設(shè)備文件,用來(lái)傳遞vhost的命令到設(shè)備去,得到vhost-mdev設(shè)備的container,用來(lái)傳遞DMAsetup的命令到VFIO container。

(2)從virtio-net設(shè)備接收數(shù)據(jù)路徑卸載的命令(set/get virtqueue狀態(tài),set臟頁(yè)日志,功能協(xié)商等等),并把他們翻譯vhost-mdev的ioctl。

(3)接受vIOMMU map和umap的命令并同VFIO DMA的ioctl執(zhí)行。

最后我們?cè)僖韵聢D總結(jié)一下vDPA實(shí)現(xiàn)的關(guān)鍵,vDPA只將dataplan硬件化,所以重點(diǎn)要考慮的是control plan。設(shè)備的PCI配置空間等還是有qemu模擬,但qemu收到Guest寫(xiě)寄存器的中斷時(shí)的處理不能再像對(duì)待vhost-net一樣了,所以qemu引入了vhost-vfio模塊用來(lái)和后端協(xié)商。

而vhost-mdev則作為kernel處理后端協(xié)商的代理,接收來(lái)自qemu的控制消息,并將消息轉(zhuǎn)文化virtio-mdev的標(biāo)準(zhǔn)接口調(diào)用。Virtio-mdev是一個(gè)抽象層,抽象了virtio的常用處理函數(shù)接口,同時(shí)又基于vfio-mdev框架對(duì)接不同硬件設(shè)備,而不同的硬件廠商只需要實(shí)現(xiàn)virtio-mdev的標(biāo)準(zhǔn)接口,同時(shí)支持vfio-mdev即可。這樣控制通道就從qemu到廠商硬件打通了。

DPDK中的vDPA實(shí)現(xiàn)

下面我們看一下在DPDK中是如何實(shí)現(xiàn)對(duì)vDPA的支持的,我們的分析代碼是基于DPDK release 20.02版本的,因?yàn)檎窃谶@個(gè)版本增加了基于Mellanox設(shè)備的vDPA PMD(回想當(dāng)初寫(xiě)第一篇關(guān)于DPDK的文章還是release 16.07)。Mellanox支持vDPA的網(wǎng)卡有ConnectX-6,Mellanox ConnectX-6 Dx以及Mellanox BlueField。在DPDK的example中有一個(gè)vDPA的使用例子,這個(gè)是在18.11版本加入的,其使用方式可以參考https://mp.weixin.qq.com/s/YspEKL5fRmoJJbHlyPz9IA。這里我們就從這個(gè)example入手分析下DPDK中關(guān)于vDPA的實(shí)現(xiàn)。

這個(gè)程序的啟動(dòng)命令是類(lèi)似如下的方式:

./ vdpa -c 0x2 -n 4 --socket-mem 1024,1024 -w 0000:06:00.3,vdpa=1 -w 0000:06:00.4,vdpa=1

vDPA的設(shè)備初始化

所以首先一定是通過(guò)-w指定的PCI設(shè)備加載對(duì)應(yīng)的驅(qū)動(dòng),我們以Mellanox的vDPA驅(qū)動(dòng)(mlx5_vdpa_driver)為例分析,注意其相關(guān)代碼和Mellanox正常mlx5驅(qū)動(dòng)不在一起,而是在drivers/vdpa的專(zhuān)門(mén)路徑中。

下面就看一下mlx5_vdpa_driver的注冊(cè)過(guò)程。

點(diǎn)擊(此處)折疊或打開(kāi)

static struct rte_pci_driver mlx5_vdpa_driver={

.driver={

.name="mlx5_vdpa",

},

.id_table=mlx5_vdpa_pci_id_map,

.probe=mlx5_vdpa_pci_probe,

.remove=mlx5_vdpa_pci_remove,

.drv_flags=0,

};

其核心是驅(qū)動(dòng)加載函數(shù):mlx5_vdpa_pci_probe

lmlx5_vdpa_pci_probe

點(diǎn)擊(此處)折疊或打開(kāi)

/**

*DPDK callbacktoregister a PCI device.

*

*Thisfunctionspawns vdpa device out of a given PCI device.

*

*@param[in]pci_drv

*PCI driver structure(mlx5_vpda_driver).

*@param[in]pci_dev

*PCI device information.

*

*@return

*0onsuccess,1toskip this driver,a negative errno value otherwise

*andrte_errnoisset.

*/

staticint

mlx5_vdpa_pci_probe(struct rte_pci_driver*pci_drv __rte_unused,

struct rte_pci_device*pci_dev __rte_unused)

{

struct ibv_device*ibv;

struct mlx5_vdpa_priv*priv=NULL;

struct ibv_context*ctx=NULL;

struct mlx5_hca_attr attr;

intret;

/*......*/

ctx=mlx5_glue->dv_open_device(ibv);

priv=rte_zmalloc("mlx5 vDPA device private",sizeof(*priv),

RTE_CACHE_LINE_SIZE);

ret=mlx5_devx_cmd_query_hca_attr(ctx,&attr);

if(ret){

DRV_LOG(ERR,"Unable to read HCA capabilities.");

rte_errno=ENOTSUP;

gotoerror;

}else{

if(!attr.vdpa.valid||!attr.vdpa.max_num_virtio_queues){

DRV_LOG(ERR,"Not enough capabilities to support vdpa,"

" maybe old FW/OFED version?");

rte_errno=ENOTSUP;

gotoerror;

}

priv->caps=attr.vdpa;

priv->log_max_rqt_size=attr.log_max_rqt_size;

}

priv->ctx=ctx;

priv->dev_addr.pci_addr=pci_dev->addr;

priv->dev_addr.type=PCI_ADDR;

priv->id=rte_vdpa_register_device(&priv->dev_addr,&mlx5_vdpa_ops);

if(priv->id

DRV_LOG(ERR,"Failed to register vDPA device.");

rte_errno=rte_errno?rte_errno:EINVAL;

gotoerror;

}

SLIST_INIT(&priv->mr_list);

SLIST_INIT(&priv->virtq_list);

pthread_mutex_lock(&priv_list_lock);

TAILQ_INSERT_TAIL(&priv_list,priv,next);

pthread_mutex_unlock(&priv_list_lock);

return 0;

error:

if(priv)

rte_free(priv);

if(ctx)

mlx5_glue->close_device(ctx);

return-rte_errno;

}

這個(gè)函數(shù)首先分配mlx的vDPA設(shè)備私有結(jié)構(gòu)struct mlx5_vdpa_priv,然后通過(guò)mlx5_devx_cmd_query_hca_attr函數(shù)獲取當(dāng)前設(shè)備的屬性并初始化這個(gè)vDPA私有結(jié)構(gòu)。其中關(guān)鍵的一步是通過(guò)rte_vdpa_register_device函數(shù)申請(qǐng)vDPA通用結(jié)構(gòu)struct rte_vdpa_device,并將mlx的vDPA ops函數(shù)結(jié)合mlx5_vdpa_ops設(shè)置為其ops。

lrte_vdpa_register_device

點(diǎn)擊(此處)折疊或打開(kāi)

int

rte_vdpa_register_device(struct rte_vdpa_dev_addr*addr,

struct rte_vdpa_dev_ops*ops)

{

struct rte_vdpa_device*dev;

char device_name[MAX_VDPA_NAME_LEN];

inti;

if(vdpa_device_num>=MAX_VHOST_DEVICE||addr==NULL||ops==NULL)

return-1;

for(i=0;i

dev=vdpa_devices[i];

if(dev&&is_same_vdpa_device(&dev->addr,addr))

return-1;

}

for(i=0;i

if(vdpa_devices[i]==NULL)

break;

}

if(i==MAX_VHOST_DEVICE)

return-1;

snprintf(device_name,sizeof(device_name),"vdpa-dev-%d",i);

dev=rte_zmalloc(device_name,sizeof(struct rte_vdpa_device),

RTE_CACHE_LINE_SIZE);

if(!dev)

return-1;

memcpy(&dev->addr,addr,sizeof(struct rte_vdpa_dev_addr));

dev->ops=ops;/*設(shè)置ops為設(shè)備廠商的具體實(shí)現(xiàn)*/

vdpa_devices[i]=dev;

vdpa_device_num++;/*全局變量,記錄vDPA設(shè)備的個(gè)數(shù)*/

return i;

}

rte_vdpa_register_device中關(guān)鍵工作就是分配一個(gè)vDPA通用結(jié)構(gòu)struct rte_vdpa_device,并將mlx vDPA的實(shí)現(xiàn)操作mlx5_vdpa_ops關(guān)聯(lián)上。而rte_vdpa_device結(jié)構(gòu)又是一個(gè)全局?jǐn)?shù)組,其數(shù)組index就是vDPA的設(shè)備id,也就是struct mlx5_vdpa_priv中的id。

另外mlx5_vdpa_ops的具體成員和實(shí)現(xiàn)結(jié)合如下??梢钥吹竭@里的函數(shù)和vhost-user的消息處理函數(shù)很多是對(duì)應(yīng)的。

點(diǎn)擊(此處)折疊或打開(kāi)

static struct rte_vdpa_dev_ops mlx5_vdpa_ops={

.get_queue_num=mlx5_vdpa_get_queue_num,

.get_features=mlx5_vdpa_get_vdpa_features,

.get_protocol_features=mlx5_vdpa_get_protocol_features,

.dev_conf=mlx5_vdpa_dev_config,

.dev_close=mlx5_vdpa_dev_close,

.set_vring_state=mlx5_vdpa_set_vring_state,

.set_features=mlx5_vdpa_features_set,

.migration_done=NULL,

.get_vfio_group_fd=NULL,

.get_vfio_device_fd=NULL,

.get_notify_area=NULL,

};

這樣就完成了Mellanox側(cè)的vDPA設(shè)備初始化,產(chǎn)生的相關(guān)數(shù)據(jù)結(jié)構(gòu)如下圖所示。

vDPA和vhost-uesr關(guān)聯(lián)

廠商定制化的vDPA部分以及初始化完畢,下面我們看下vhost-user和vDPA是怎么關(guān)聯(lián)的。參考的是vDPA example中的start_vdpa函數(shù),具體如下

lstart_vdpa

點(diǎn)擊(此處)折疊或打開(kāi)

staticint

start_vdpa(struct vdpa_port*vport)

{

intret;

char*socket_path=vport->ifname;

intdid=vport->did;/*vDPA設(shè)備id*/

if(client_mode)

vport->flags|=RTE_VHOST_USER_CLIENT;

if(access(socket_path,F_OK)!=-1&&!client_mode){

RTE_LOG(ERR,VDPA,

"%s exists, please remove it or specify another file and try again. ",

socket_path);

return-1;

}

ret=rte_vhost_driver_register(socket_path,vport->flags);/*初始化vsocket結(jié)構(gòu),創(chuàng)建vhost-user后端重連線程*/

if(ret!=0)

rte_exit(EXIT_FAILURE,

"register driver failed: %s ",

socket_path);

ret=rte_vhost_driver_callback_register(socket_path,

&vdpa_sample_devops);/*注冊(cè)自定義的vsocket->notify_ops*/

if(ret!=0)

rte_exit(EXIT_FAILURE,

"register driver ops failed: %s ",

socket_path);

ret=rte_vhost_driver_attach_vdpa_device(socket_path,did);/*將vsocket結(jié)構(gòu)和vDPA設(shè)備關(guān)聯(lián)*/

if(ret!=0)

rte_exit(EXIT_FAILURE,

"attach vdpa device failed: %s ",

socket_path);

if(rte_vhost_driver_start(socket_path)

rte_exit(EXIT_FAILURE,

"start vhost driver failed: %s ",

socket_path);

return 0;

}

這個(gè)函數(shù)關(guān)鍵執(zhí)行了4步操作:

(1)rte_vhost_driver_register:初始化vsocket結(jié)構(gòu),創(chuàng)建vhost-user后端重連線程;

(2)rte_vhost_driver_callback_register:注冊(cè)自定義的vsocket->notify_ops;

(3)rte_vhost_driver_attach_vdpa_device:將vsocket結(jié)構(gòu)和vDPA設(shè)備關(guān)聯(lián)

(4)rte_vhost_driver_start:創(chuàng)建vhost控制面消息處理線程,將vsocket加入重連鏈表;

其中(1)(2)(4)都是vhost-user設(shè)備的常規(guī)操作,這里不再展開(kāi),其中關(guān)鍵的是(3)。

lrte_vhost_driver_attach_vdpa_device

點(diǎn)擊(此處)折疊或打開(kāi)

int

rte_vhost_driver_attach_vdpa_device(constchar*path,intdid)

{

struct vhost_user_socket*vsocket;

if(rte_vdpa_get_device(did)==NULL||path==NULL)

return-1;

pthread_mutex_lock(&vhost_user.mutex);

vsocket=find_vhost_user_socket(path);

if(vsocket)

vsocket->vdpa_dev_id=did;

pthread_mutex_unlock(&vhost_user.mutex);

return vsocket?0:-1;

}

這個(gè)函數(shù)將vDPA的deviceid記錄在vsocket結(jié)構(gòu)中,這樣就將vhost和vDPA設(shè)備關(guān)聯(lián)起來(lái)了。

vhost控制面的vDPA初始化

前面說(shuō)到通過(guò)vhost-user的vsocket結(jié)構(gòu)中的vDPA deviceid將vhost-user和vDPA關(guān)聯(lián)起來(lái),那么下面就來(lái)看一下vhost-user進(jìn)行初始化時(shí)怎么將對(duì)應(yīng)vDPA設(shè)備初始化的。

首先,vhost-user前后端建立連接后會(huì)調(diào)用vhost_user_add_connection,而vhost_user_add_connection中則會(huì)調(diào)用vhost_new_device()分配struct virtio_net結(jié)構(gòu),而virtio_net中也有一個(gè)vdpa_dev_id,在調(diào)用vhost_attach_vdpa_device時(shí)將vsocket的vdpa_dev_id賦值給virtio_net的vdpa_dev_id。

點(diǎn)擊(此處)折疊或打開(kāi)

static void

vhost_user_add_connection(intfd,struct vhost_user_socket*vsocket)

{

intvid;

size_t size;

struct vhost_user_connection*conn;

intret;

/*......*/

vid=vhost_new_device();

if(vid==-1){

gotoerr;

}

/*......*/

vhost_attach_vdpa_device(vid,vsocket->vdpa_dev_id);

/*......*/

}

有了這個(gè)關(guān)聯(lián)以后,后續(xù)所有vhost-user的消息處理就可以找到對(duì)應(yīng)的vDPA設(shè)備,進(jìn)而找到廠商關(guān)聯(lián)的vDPA ops函數(shù)?;貞浨懊嬖O(shè)備初始化時(shí)將Mellanox的mlx5_vdpa_ops注冊(cè)到的vDPA設(shè)備上,其實(shí)這是一個(gè)struct rte_vdpa_dev_ops結(jié)構(gòu),如下所示:

點(diǎn)擊(此處)折疊或打開(kāi)

/**

*vdpa device operations

*/

struct rte_vdpa_dev_ops{

/**Getcapabilities of this device*/

int(*get_queue_num)(intdid,uint32_t*queue_num);

/**Getsupported features of this device*/

int(*get_features)(intdid,uint64_t*features);

/**Getsupported protocol features of this device*/

int(*get_protocol_features)(intdid,uint64_t*protocol_features);

/**Driver configure/close the device*/

int(*dev_conf)(intvid);

int(*dev_close)(intvid);

/**Enable/disable this vring*/

int(*set_vring_state)(intvid,intvring,intstate);

/**Setfeatures when changed*/

int(*set_features)(intvid);

/**Destination operations when migration done*/

int(*migration_done)(intvid);

/**Getthe vfio group fd*/

int(*get_vfio_group_fd)(intvid);

/**Getthe vfio device fd*/

int(*get_vfio_device_fd)(intvid);

/**Getthe notify area info of the queue*/

int(*get_notify_area)(intvid,intqid,

uint64_t*offset,uint64_t*size);

/**Reservedforfuture extension*/

void*reserved[5];

};

可以看到他和我們的vhost-user消息處理函數(shù)很多都是對(duì)應(yīng)的,這也是前面我們提到過(guò)的virtio-mdev在DPDK的表現(xiàn)。所以很自然的相當(dāng)在vhost-user處理后端消息時(shí)會(huì)調(diào)用對(duì)應(yīng)的vDPA處理函數(shù)。以vhost_user_set_features為例,其中調(diào)用了rte_vdpa_get_device通過(guò)virtio-net的vdpa_dev_id獲取到對(duì)應(yīng)的vDPA設(shè)備,并調(diào)用對(duì)應(yīng)的vDPA的set_features函數(shù)。

點(diǎn)擊(此處)折疊或打開(kāi)

staticint

vhost_user_set_features(struct virtio_net**pdev,struct VhostUserMsg*msg,

intmain_fd __rte_unused)

{

/*......*/

did=dev->vdpa_dev_id;

vdpa_dev=rte_vdpa_get_device(did);

if(vdpa_dev&&vdpa_dev->ops->set_features)

vdpa_dev->ops->set_features(dev->vid);

return RTE_VHOST_MSG_RESULT_OK;

}

其他函數(shù)也是類(lèi)似的,我們可以搜索一下vdpa_dev_id關(guān)鍵字確認(rèn)。

整個(gè)vDPA在DPDK的工作方式可以用下圖來(lái)表示。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    12

    文章

    9165

    瀏覽量

    85436
  • dma
    dma
    +關(guān)注

    關(guān)注

    3

    文章

    561

    瀏覽量

    100588
  • 數(shù)據(jù)路徑
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    6303
  • DPDK
    +關(guān)注

    關(guān)注

    0

    文章

    13

    瀏覽量

    1725
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    淺談基于物聯(lián)網(wǎng)的智能路燈系統(tǒng)-盾華電子智慧路燈解決方案

    淺談基于物聯(lián)網(wǎng)的智能路燈系統(tǒng)-盾華電子智慧路燈解決方案
    的頭像 發(fā)表于 10-11 10:08 ?388次閱讀
    <b class='flag-5'>淺談</b>基于物聯(lián)網(wǎng)的智能路燈系統(tǒng)-盾華電子智慧路燈解決<b class='flag-5'>方案</b>

    SD-WAN技術(shù)在直播網(wǎng)絡(luò)如何實(shí)現(xiàn)智能路徑選擇?

    SD-WAN技術(shù)在直播網(wǎng)絡(luò)實(shí)現(xiàn)智能路徑選擇主要通過(guò)以下幾個(gè)步驟: 1、實(shí)時(shí)網(wǎng)絡(luò)監(jiān)控:SD-WAN系統(tǒng)持續(xù)監(jiān)控所有可用的網(wǎng)絡(luò)路徑,包括它們的帶寬、延遲、丟包率和抖動(dòng)等關(guān)鍵性能指標(biāo)。 2
    的頭像 發(fā)表于 09-09 14:39 ?306次閱讀

    淺談國(guó)產(chǎn)異構(gòu)雙核RISC-V+FPGA處理器AG32VF407的優(yōu)勢(shì)和應(yīng)用場(chǎng)景

    任務(wù)優(yōu)化計(jì)算資源,提高整體計(jì)算效率。 靈活性與可擴(kuò)展性 : FPGA的靈活性允許用戶根據(jù)需求重新配置硬件邏輯,實(shí)現(xiàn)高度定制的解決方案。結(jié)合RISC-V的開(kāi)放架構(gòu),用戶可以更容易地根
    發(fā)表于 08-31 08:32

    適用于數(shù)據(jù)中心應(yīng)用硬件加速器的直流/直流轉(zhuǎn)換器解決方案

    電子發(fā)燒友網(wǎng)站提供《適用于數(shù)據(jù)中心應(yīng)用硬件加速器的直流/直流轉(zhuǎn)換器解決方案.pdf》資料免費(fèi)下載
    發(fā)表于 08-26 09:38 ?0次下載
    適用于<b class='flag-5'>數(shù)據(jù)</b>中心應(yīng)用<b class='flag-5'>中</b>的<b class='flag-5'>硬件</b>加速器的直流/直流轉(zhuǎn)換器解決<b class='flag-5'>方案</b>

    智慧校園如何實(shí)現(xiàn)管理智能

    智慧校園 是利用現(xiàn)代科技手段,通過(guò)信息、智能的方式對(duì)校園管理進(jìn)行全面優(yōu)化和升級(jí)的綜合解決方案。實(shí)現(xiàn)校園管理智能需要涵蓋多個(gè)方面,以下是
    的頭像 發(fā)表于 06-18 15:45 ?655次閱讀

    數(shù)據(jù)臺(tái):企業(yè)數(shù)字轉(zhuǎn)型的驅(qū)動(dòng)力量

    在當(dāng)今數(shù)字快速發(fā)展的時(shí)代,企業(yè)正積極尋求轉(zhuǎn)型升級(jí)的新路徑。在這個(gè)過(guò)程數(shù)據(jù)臺(tái)以其獨(dú)特的功能和價(jià)值,逐漸成為了企業(yè)數(shù)字
    的頭像 發(fā)表于 05-08 17:00 ?300次閱讀

    淺談光伏電站數(shù)據(jù)通訊管理機(jī)的設(shè)計(jì)與應(yīng)用

    淺談光伏電站數(shù)據(jù)通訊管理機(jī)的設(shè)計(jì)與應(yīng)用 張穎姣 江蘇安科瑞電器制造有限公司江蘇江陰214405 摘要 :設(shè)計(jì)了一種分布式光伏電站數(shù)據(jù)通訊管理機(jī),包括硬件系統(tǒng)和軟件系統(tǒng).
    的頭像 發(fā)表于 03-14 10:23 ?575次閱讀
    <b class='flag-5'>淺談</b>光伏電站<b class='flag-5'>數(shù)據(jù)</b>通訊管理機(jī)的設(shè)計(jì)與應(yīng)用

    淺談建筑電氣設(shè)計(jì)的火災(zāi)隱患及其對(duì)策方案

    淺談建筑電氣設(shè)計(jì)的火災(zāi)隱患及其對(duì)策方案 張穎姣 安科瑞電氣股份有限公司?上海嘉定201801 摘要:隨著我國(guó)城市發(fā)展水平的不斷提升,建筑體系已經(jīng)逐步成熟,而電氣設(shè)計(jì)能夠滿足建筑日常用電需求,同時(shí)也
    的頭像 發(fā)表于 03-12 10:28 ?361次閱讀
    <b class='flag-5'>淺談</b>建筑電氣設(shè)計(jì)<b class='flag-5'>中</b>的火災(zāi)隱患及其對(duì)策<b class='flag-5'>方案</b>

    數(shù)智轉(zhuǎn)型的新篇章:企業(yè)如何在「數(shù)據(jù)飛輪」理念尋求增長(zhǎng)?

    在當(dāng)今的數(shù)字浪潮,企業(yè)對(duì)數(shù)據(jù)的渴求與日俱增。數(shù)據(jù)不再僅是輔助決策的工具,而是成為推動(dòng)業(yè)務(wù)增長(zhǎng)的核心動(dòng)力。自從「數(shù)據(jù)
    的頭像 發(fā)表于 03-06 16:01 ?627次閱讀

    關(guān)于DPDK的一些常見(jiàn)問(wèn)題

    對(duì)于單核多CPU部署,一個(gè)CPU分配給操作系統(tǒng),另一個(gè)分配給基于DPDK的應(yīng)用程序。對(duì)于多核部署,無(wú)論是否使用超線程,都可以為每個(gè)端口分配多個(gè)內(nèi)核。
    的頭像 發(fā)表于 03-05 11:44 ?849次閱讀
    關(guān)于<b class='flag-5'>DPDK</b>的一些常見(jiàn)問(wèn)題

    DPDK在AI驅(qū)動(dòng)的高效數(shù)據(jù)包處理應(yīng)用

    傳統(tǒng)的數(shù)據(jù)包處理方式是數(shù)據(jù)包先到內(nèi)核最后再到用戶層進(jìn)行處理。這種方式會(huì)增加額外的延遲和CPU開(kāi)銷(xiāo),嚴(yán)重影響數(shù)據(jù)包處理的性能。 DPDK 繞過(guò)內(nèi)核,在用戶空間中
    的頭像 發(fā)表于 02-25 11:28 ?948次閱讀
    <b class='flag-5'>DPDK</b>在AI驅(qū)動(dòng)的高效<b class='flag-5'>數(shù)據(jù)</b>包處理應(yīng)用

    淺談公網(wǎng)無(wú)信號(hào)區(qū)域遠(yuǎn)程抄表問(wèn)題解決方案及產(chǎn)品選型

    淺談公網(wǎng)無(wú)信號(hào)區(qū)域遠(yuǎn)程抄表問(wèn)題解決方案及產(chǎn)品選型 張穎姣 安科瑞電氣股份有限公司 上海嘉定 201801 摘要:隨著計(jì)量自動(dòng)系統(tǒng)的逐步完善,電網(wǎng)全用戶表碼信息采集成為系統(tǒng)數(shù)據(jù)得以深化
    的頭像 發(fā)表于 02-20 15:34 ?566次閱讀
    <b class='flag-5'>淺談</b>公網(wǎng)無(wú)信號(hào)區(qū)域遠(yuǎn)程抄表問(wèn)題解決<b class='flag-5'>方案</b>及產(chǎn)品選型

    建設(shè)工業(yè)數(shù)據(jù)臺(tái)可以實(shí)現(xiàn)哪些功能

    工業(yè)數(shù)據(jù)臺(tái)是一個(gè)讓工業(yè)數(shù)據(jù)可持續(xù)利用起來(lái)的中間層平臺(tái),能夠持續(xù)不斷將數(shù)據(jù)變成重要資產(chǎn)并落地于執(zhí)行業(yè)務(wù)
    的頭像 發(fā)表于 02-01 17:16 ?378次閱讀

    數(shù)據(jù)臺(tái)助力數(shù)據(jù)可視智能治理

    隨著數(shù)字轉(zhuǎn)型的不斷推進(jìn),數(shù)據(jù)已經(jīng)成為企業(yè)核心競(jìng)爭(zhēng)力的重要組成部分。如何將海量數(shù)據(jù)轉(zhuǎn)化為有價(jià)值的信息,為企業(yè)決策提供有力支持,運(yùn)用高效便捷的方式進(jìn)行管理,成為每個(gè)企業(yè)必須面對(duì)的挑戰(zhàn)。數(shù)據(jù)
    的頭像 發(fā)表于 02-01 13:41 ?317次閱讀
    <b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>中</b>臺(tái)助力<b class='flag-5'>數(shù)據(jù)</b>可視<b class='flag-5'>化</b>智能治理

    硬件到數(shù)智控30年鑄就流程工業(yè)“大國(guó)重器”

    杭州2024年1月1日?/美通社/ --?控歷經(jīng)?30?年的發(fā)展,在數(shù)字轉(zhuǎn)型的浪潮,從硬件提供商逐步轉(zhuǎn)型為助力流程工業(yè)企業(yè)實(shí)現(xiàn)“安全、
    的頭像 發(fā)表于 01-02 09:13 ?483次閱讀
    從<b class='flag-5'>硬件</b>到數(shù)智<b class='flag-5'>化</b>:<b class='flag-5'>中</b>控30年鑄就流程工業(yè)“大國(guó)重器”