DPDK技术介绍
DPDK是INTEL公司開發(fā)的一款高性能的網(wǎng)絡(luò)驅(qū)動組件,旨在為數(shù)據(jù)面應(yīng)用程序提供一個簡單方便的,完整的,快速的數(shù)據(jù)包處理解決方案,主要技術(shù)有用戶態(tài)、輪詢?nèi)〈袛唷⒘憧截悺⒕W(wǎng)卡RSS、訪存DirectIO等。
一、主要特點
1、UIO(Linux Userspace I/O)
提供應(yīng)用空間下驅(qū)動程序的支持,也就是說網(wǎng)卡驅(qū)動是運行在用戶空間的,減下了報文在用戶空間和應(yīng)用空間的多次拷貝。如圖:DPDK繞過了Linux內(nèi)核的網(wǎng)絡(luò)驅(qū)動模塊,直接從網(wǎng)絡(luò)硬件到達(dá)用戶空間,不需要進(jìn)行頻繁的內(nèi)存拷貝和系統(tǒng)調(diào)用。根據(jù)官方給出的數(shù)據(jù),DPDK裸包反彈每個包需要80個時鐘周期,而傳統(tǒng)Linux內(nèi)核協(xié)議棧每包需要2k~4k個時鐘周期。DPDK能顯著提升虛擬化網(wǎng)絡(luò)設(shè)備的數(shù)據(jù)采集效率。
?
下圖為UIO技術(shù)的工作原理圖
?
UIO技術(shù)將設(shè)備驅(qū)動分為用戶空間驅(qū)動和內(nèi)核空間驅(qū)動兩部分,內(nèi)核空間驅(qū)動主要負(fù)責(zé)設(shè)備資源分配、UIO設(shè)備注冊以及小部分中斷響應(yīng)函數(shù),驅(qū)動的大部分工作在用戶空間的驅(qū)動程序下完成。通過UIO框架提供的API接口將UIO的驅(qū)動注冊到內(nèi)核,注冊完成后將生成存有設(shè)備物理地址等信息的map文件,用戶態(tài)進(jìn)程訪問該文件將設(shè)備對應(yīng)的內(nèi)存空間地址映射到用戶空間,即可直接操作設(shè)備的內(nèi)存空間,UIO技術(shù)使得應(yīng)用程序可以通過用戶空間驅(qū)動直接操作設(shè)備的內(nèi)存空間,避免了數(shù)據(jù)在內(nèi)核緩沖區(qū)和應(yīng)用程序緩沖區(qū)的多次拷貝,提供數(shù)據(jù)處理效率。
簡單地說,DPDK使高速數(shù)據(jù)包網(wǎng)絡(luò)應(yīng)用程序的開發(fā)變得更快,這意味著它允許構(gòu)建能夠更快地處理數(shù)據(jù)包的應(yīng)用程序,這多虧了內(nèi)核的繞過。實際上,它使用了快速路徑,而不是正常的網(wǎng)絡(luò)層路徑和上下文切換路徑。包被直接傳遞到用戶空間(作為原始包)。如下圖為linux內(nèi)核包處理和dpdk包處理的區(qū)別。
linux內(nèi)核處理包:
?
dpdk處理包:
?
下圖為slow路徑和fast路徑比較:
?
2、用戶空間輪詢模式(PMD)
傳統(tǒng)中斷模式: 傳統(tǒng)Linux系統(tǒng)中,當(dāng)網(wǎng)絡(luò)設(shè)備檢測到數(shù)據(jù)幀過來的時候,會使用DMA(直接內(nèi)存訪問)將幀發(fā)送到預(yù)先分配好的內(nèi)核緩沖區(qū)里面,然后更新相應(yīng)的接收描述符環(huán),之后產(chǎn)生中斷通知有數(shù)據(jù)幀過來。Linux系統(tǒng)會進(jìn)行相應(yīng)的響應(yīng),然后更新相應(yīng)的描述符環(huán),再將接收到的數(shù)據(jù)幀交給內(nèi)核中的網(wǎng)絡(luò)堆棧進(jìn)行處理,網(wǎng)絡(luò)堆棧處理完之后會將相應(yīng)的數(shù)據(jù)拷貝到相應(yīng)的套接字,從而數(shù)據(jù)就被復(fù)制到了用戶空間,應(yīng)用程序就可以使用這些數(shù)據(jù)了,數(shù)據(jù)幀的接收過程如圖:
?
在發(fā)送的時候,一旦用戶程序處理完了數(shù)據(jù),會通過一個系統(tǒng)調(diào)用將數(shù)據(jù)寫入到套接字,將數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間的緩沖區(qū),交由網(wǎng)絡(luò)堆棧進(jìn)行處理,網(wǎng)絡(luò)堆棧根據(jù)需要對數(shù)據(jù)進(jìn)行封裝并調(diào)用網(wǎng)卡設(shè)備的驅(qū)動程序,網(wǎng)卡設(shè)備驅(qū)動程序會更新傳輸描述符環(huán),然后向網(wǎng)卡設(shè)備告知有數(shù)據(jù)幀需要傳輸。網(wǎng)卡設(shè)備會將數(shù)據(jù)幀從內(nèi)核中的緩沖區(qū)拷貝到自己的緩沖區(qū)中并發(fā)送到網(wǎng)絡(luò)鏈路上,傳送到鏈路上之后,網(wǎng)卡設(shè)備會通過一個中斷告知成功發(fā)送,然后內(nèi)核會釋放相應(yīng)的緩沖區(qū)。數(shù)據(jù)的發(fā)送如圖:
?
由于linux系統(tǒng)是通過中斷的方式告知CPU有數(shù)據(jù)包過來的,當(dāng)網(wǎng)絡(luò)的流量越來越大,linux系統(tǒng)會浪費越來越多的時間去處理中斷,當(dāng)流量速率達(dá)到10G的時候,linux系統(tǒng)可能會被中斷淹沒,浪費很多CPU資源。
DPDK用戶空間的輪詢模式驅(qū)動:用戶空間驅(qū)動使得應(yīng)用程序不需要經(jīng)過linux內(nèi)核就可以訪問網(wǎng)絡(luò)設(shè)備卡。網(wǎng)卡設(shè)備可以通過DMA方式將數(shù)據(jù)包傳輸?shù)绞孪确峙浜玫木彌_區(qū),這個緩沖區(qū)位于用戶空間,應(yīng)用程序通過不斷輪詢的方式可以讀取數(shù)據(jù)包并在原地址上直接處理,不需要中斷,而且也省去了內(nèi)核到應(yīng)用層的數(shù)據(jù)包拷貝過程。
因此相對于linux系統(tǒng)傳統(tǒng)中斷方式,Intel DPDK避免了中斷處理、上下文切換、系統(tǒng)調(diào)用、數(shù)據(jù)復(fù)制帶來的性能上的消耗,大大提升了數(shù)據(jù)包的處理性能。同時由于Intel DPDK在用戶空間就可以開發(fā)驅(qū)動,與傳統(tǒng)的在內(nèi)核中開發(fā)驅(qū)動相比,安全系數(shù)大大降低。因為內(nèi)核層權(quán)限比較高,操作相對比較危險,可能因為小的代碼bug就會導(dǎo)致系統(tǒng)崩潰,需要仔細(xì)的開發(fā)和廣泛的測試。而在應(yīng)用層則相反,比較安全,且在應(yīng)用層調(diào)試代碼要方便的多。
3、大頁內(nèi)存
Linux操作系統(tǒng)通過查找TLB來實現(xiàn)快速的虛擬地址到物理地址的轉(zhuǎn)化。由于TLB是一塊高速緩沖cache,容量比較小,容易發(fā)生沒有命中。當(dāng)沒有命中的時候,會觸發(fā)一個中斷,然后會訪問內(nèi)存來刷新頁表,這樣會造成比較大的時延,降低性能。Linux操作系統(tǒng)的頁大小只有4K,所以當(dāng)應(yīng)用程序占用的內(nèi)存比較大的時候,會需要較多的頁表,開銷比較大,而且容易造成未命中。相比于linux系統(tǒng)的4KB頁,Intel DPDK緩沖區(qū)管理庫提供了Hugepage大頁內(nèi)存,大小有2MB和1GB頁面兩種,可以得到明顯性能的提升,因為采用大頁內(nèi)存的話,可以需要更少的頁,從而需要更少的TLB,這樣就減少了虛擬頁地址到物理頁地址的轉(zhuǎn)換時間。‘
DPDK中的內(nèi)存管理如圖,最下面是連續(xù)的物理內(nèi)存,這些物理內(nèi)存是由2MB的大頁組成,連續(xù)的物理內(nèi)存上面是內(nèi)存段,內(nèi)存段之上則是內(nèi)存區(qū),我們分配的基本單元對象是在內(nèi)存區(qū)中分配的,內(nèi)存區(qū)包含了ring隊列,內(nèi)存池、LPM路由表還有其他一些高性能的關(guān)鍵結(jié)構(gòu)。
?
4、CPU親和性
CPU的親和性(CPU affinity),它是多核CPU發(fā)展的結(jié)果。隨著核心的數(shù)量越來越多,為了提高程序工作的效率必須使用多線程。但是隨著CPU的核心的數(shù)目的增長,Linux的核心間的調(diào)度和共享內(nèi)存爭用會嚴(yán)重影響性能。利用Intel DPDK的CPU affinity可以將各個線程綁定到不同的cpu,可以省去來回反復(fù)調(diào)度帶來的性能上的消耗。
在一個多核處理器的機(jī)器上,每個CPU核心本身都存在自己的緩存,緩沖區(qū)里存放著線程使用的信息。如果線程沒有綁定CPU核,那么線程可能被Linux系統(tǒng)調(diào)度到其他的CPU上,這樣的話,CPU的cache命中率就降低了。利用CPU的affinity技術(shù),一旦線程綁定到某個CPU后,線程就會一直在指定的CPU上運行,操作系統(tǒng)不會將其調(diào)度到其他的CPU上,節(jié)省了調(diào)度的性能消耗,從而提升了程序執(zhí)行的效率。
多核輪詢模式:多核輪詢模式有兩種,分別是IO獨占式和流水線式。IO獨占式是指每個核獨立完成數(shù)據(jù)包的接收、處理和發(fā)送過程,核之間相互獨立,其優(yōu)點是其中一個核出現(xiàn)問題時不影響其他核的數(shù)據(jù)收發(fā)。流水線式則采用多核合作的方式處理數(shù)據(jù)包,數(shù)據(jù)包的接收、處理和發(fā)送由不同的核完成。流水線式適合面向流的數(shù)據(jù)處理,其優(yōu)點是可對數(shù)據(jù)包按照接收的順序有序進(jìn)行處理,缺點是當(dāng)某個環(huán)境(例如接收)所涉及的核出現(xiàn)阻塞,則會造成收發(fā)中斷。
IO獨占式多核輪詢模式中每個網(wǎng)卡只分配給一個邏輯核進(jìn)行處理。每個邏輯核給所接管的網(wǎng)卡分別分配一個發(fā)送隊列和一個接收隊列,并且獨立完成數(shù)據(jù)包的接收、處理和發(fā)送的過程,核與核之間相互獨立。系統(tǒng)數(shù)據(jù)包的處理由多個邏輯核同時進(jìn)行,每個網(wǎng)卡的收發(fā)包隊列只能由一個邏輯核提供。當(dāng)數(shù)據(jù)包進(jìn)入網(wǎng)卡的硬件緩存區(qū),用戶空間提供的網(wǎng)卡驅(qū)動通過輪詢得知網(wǎng)卡收到數(shù)據(jù)包,從硬件緩沖區(qū)中取出數(shù)據(jù)包,并將數(shù)據(jù)包存入邏輯核提供的收包隊列中,邏輯核取出收包隊列中的數(shù)據(jù)包進(jìn)行處理,處理完畢后將數(shù)據(jù)包存入邏輯核提供的發(fā)包隊列,然后由網(wǎng)卡驅(qū)動取出發(fā)往網(wǎng)卡,最終發(fā)送到網(wǎng)絡(luò)中。
IO獨占式多核輪詢模式架構(gòu)圖:
?
5、內(nèi)存池和無鎖環(huán)形緩存管理
此外Intel DPDK將庫和API優(yōu)化成了無鎖,比如無鎖隊列,可以防止多線程程序發(fā)生死鎖。然后對緩沖區(qū)等數(shù)據(jù)結(jié)構(gòu)進(jìn)行了cache對齊。如果沒有cache對齊,則可能在內(nèi)存訪問的時候多讀寫一次內(nèi)存和cache。
內(nèi)存池緩存區(qū)的申請和釋放采用的是生產(chǎn)者-消費者模式無鎖緩存隊列進(jìn)行管理,避免隊列中鎖的開銷,在緩存區(qū)的使用過程中提高了緩沖區(qū)申請釋放的效率。
無鎖環(huán)形隊列生產(chǎn)過程:
?
無鎖環(huán)形隊列消費過程:
?
如圖所示,生產(chǎn)者往隊列里存放內(nèi)容的方向和消費者從隊列里取內(nèi)容的方向一致,均以順時針方向進(jìn)行。當(dāng)緩存區(qū)向內(nèi)存池申請內(nèi)存塊,或者應(yīng)用程序進(jìn)行內(nèi)存塊的釋放時,緩存區(qū)的無鎖環(huán)形隊列的生產(chǎn)者指針順時針移動,往隊列中存入內(nèi)存塊地址信息,進(jìn)行緩存隊列的生產(chǎn)過程。當(dāng)應(yīng)用程序需要向緩沖區(qū)申請內(nèi)存塊使用時,緩沖區(qū)的無鎖環(huán)形隊列的消費者指針以順時針的方向取出隊列的內(nèi)存塊地址,分配給應(yīng)用程序使用,該過程為緩存隊列的消費過程。
生產(chǎn)n個對象過程:首先生產(chǎn)者頭指針往順時針方向移n個位置獲得新的頭指針,然后從生產(chǎn)者尾指針指的區(qū)域開始逐個存入n個對象,最后生產(chǎn)者尾指針順時針移動n個位置獲得新的生產(chǎn)者尾指針
消費n個對象過程:首先消費者頭指針順時針移動n個位置獲得新的消費者頭指針,然后從消費者尾指針處開始逐個讀取n個對象,最后消費者尾指針順時針移動n個位置獲得新的消費者尾指針。
6、網(wǎng)絡(luò)存儲優(yōu)化
二、架構(gòu)與核心組件
1、 DPDK總體架構(gòu)
?
?
2、核心組件
DPDK主要有六個核心組件
1、 環(huán)境抽象層(EAL):為DPDK其他組件和應(yīng)用程序提供一個屏蔽具體平臺特性的統(tǒng)一接口,環(huán)境抽象層提供的功能主要有:DPDK加載和啟動;支持多核和多線程執(zhí)行類型;CPU核親和性處理;原子操作和鎖操作接口;時鐘參考;PCI總線訪問接口;跟蹤和調(diào)試接口;CPU特性采集接口;中斷和告警接口等。
2、 堆內(nèi)存管理組件(Malloc lib):堆內(nèi)存管理組件為應(yīng)用程序提供從大頁內(nèi)存分配對內(nèi)存的接口。當(dāng)需要分配大量內(nèi)存小塊時,使用這些接口可以減少TLB缺頁。
3、 環(huán)緩沖區(qū)管理組件(Ring lib):環(huán)緩沖區(qū)管理組件為應(yīng)用程序和其他組件提供一個無鎖的多生產(chǎn)者多消費者FIFO隊列API:Ring。Ring是借鑒了Linux內(nèi)核kfifo無鎖隊列,可以無鎖出入對,支持多消費/生產(chǎn)者同時出入隊。
4、 內(nèi)存池管理組件(Mem pool lib):為應(yīng)用程序和其他組件提供分配內(nèi)存池的接口,內(nèi)存池是一個由固定大小的多個內(nèi)存塊組成的內(nèi)存容器,可用于存儲相同對象實體,如報文緩存塊等。內(nèi)存池由內(nèi)存池的名稱來唯一標(biāo)識,它由一個環(huán)緩沖區(qū)和一組核本地緩存隊列組成,每個核從自己的緩存隊列分配內(nèi)存塊,當(dāng)本地緩存隊列減少到一定程度時,從內(nèi)存緩沖區(qū)中申請內(nèi)存塊來補(bǔ)充本地隊列。
5、 網(wǎng)絡(luò)報文緩存塊管理組件(Mbuf lib):提供應(yīng)用程序創(chuàng)建和釋放用于存儲報文信息的緩存塊的接口,這些MBUF存儲在內(nèi)存池中。提供兩種類型的MBUF,一種用于存儲一般信息,一種用于存儲報文信息。
6、 定時器組件(Timer lib):提供一些異步周期執(zhí)行的接口(也可以只執(zhí)行一次),可以指定某個函數(shù)在規(guī)定的時間異步的執(zhí)行,就像LIBC中的timer定時器,但是這里的定時器需要應(yīng)用程序在主循環(huán)中周期調(diào)用rte_timer_manage來使定時器得到執(zhí)行。定時器組件的時間參考來自EAL層提供的時間接口。
除了以上六個核心組件外,DPDK還提供以下功能:
1) 以太網(wǎng)輪詢模式驅(qū)動(PMD)架構(gòu):把以太網(wǎng)驅(qū)動從內(nèi)核移到應(yīng)用層,采用同步輪詢機(jī)制而不是內(nèi)核態(tài)的異步中斷機(jī)制來提高報文的接收和發(fā)送效率。
2)報文轉(zhuǎn)發(fā)算法支持:Hash 庫和LPM庫為報文轉(zhuǎn)發(fā)算法提供支持。
3) 網(wǎng)絡(luò)協(xié)議定義和相關(guān)宏定義:基于FreeBSD IP協(xié)議棧的相關(guān)定義如:TCP、UDP、SCTP等協(xié)議頭定義。
4)報文QOS調(diào)度庫:支持隨機(jī)早檢測、流量整形、嚴(yán)格優(yōu)先級和加權(quán)隨機(jī)循環(huán)優(yōu)先級調(diào)度等相關(guān)QOS 功能。
5)內(nèi)核網(wǎng)絡(luò)接口庫(KNI):提供一種DPDK應(yīng)用程序與內(nèi)核協(xié)議棧的通信的方法、類似普通Linux的TUN/TAP接口,但比TUN/TAP接口效率高。每個物理網(wǎng)口可以虛擬出多個KNI接口。
?
3、KNI組件
KNI是DPDK平臺提供的用于將數(shù)據(jù)重入內(nèi)核協(xié)議棧的一個組件,其目的是充分運用傳統(tǒng)內(nèi)核協(xié)議棧已實現(xiàn)的較穩(wěn)定的協(xié)議處理功能。DPDK平臺對數(shù)據(jù)包的處理繞過了內(nèi)核協(xié)議棧,直接交給用戶空間處理,而用戶空間沒有完善的協(xié)議處理棧,如果讓開發(fā)人員在用戶空間實現(xiàn)完整獨立的協(xié)議棧,開發(fā)工作是非常復(fù)雜的,因此DPDK平臺提供了KNI組件,開發(fā)人員可以在用戶空間實現(xiàn)一些特殊的協(xié)議處理功能,再通過KNI重入內(nèi)核協(xié)議棧功能將普通常見的協(xié)議交由傳統(tǒng)內(nèi)核協(xié)議棧處理。KNI通信機(jī)制如下:
?
KNI組件通過創(chuàng)建KNI虛擬接口設(shè)備,將數(shù)據(jù)包經(jīng)過虛擬接口實現(xiàn)用戶空間和內(nèi)核協(xié)議棧間的通信。當(dāng)網(wǎng)卡接收到數(shù)據(jù)包時,應(yīng)用程序通過用戶空間驅(qū)動將數(shù)據(jù)包獲取到用戶空間,KNI組件將需要數(shù)據(jù)包發(fā)送至KNI虛擬接口,由KNI虛擬接口交給內(nèi)核協(xié)議棧處理,處理后若有響應(yīng)報文,則再交給KNI虛擬接口返回給應(yīng)用程序。其中發(fā)送數(shù)據(jù)包至內(nèi)核協(xié)議棧以及接收內(nèi)核協(xié)議棧回復(fù)的數(shù)據(jù)包,是由兩個不同的邏輯核分別進(jìn)行處理,不阻塞應(yīng)用程序讓內(nèi)核協(xié)議棧發(fā)送數(shù)據(jù)包或從內(nèi)核協(xié)議棧接收數(shù)據(jù)包的過程。
KNI接口實際上是一個虛擬出來的設(shè)備,該虛擬設(shè)備定義了四個隊列,分別是接收隊列(rx_q)、發(fā)送隊列(tx_q)、已分配內(nèi)存塊隊列(alloc_q)、待釋放內(nèi)存塊隊列(free_q)。接收隊列用于存放用戶空間程序發(fā)往KNI虛擬設(shè)備的報文,發(fā)送隊列用于存放內(nèi)核協(xié)議棧要往KNI虛擬設(shè)備的報文。已分配內(nèi)存塊隊列存放已向內(nèi)存中申請的內(nèi)存塊,供內(nèi)核協(xié)議棧發(fā)送報文時取出使用。待釋放內(nèi)存塊隊列用于記錄KNI虛擬設(shè)備從用戶空間程序處接收到報文后將不再使用的內(nèi)存塊,然后將該隊列中的內(nèi)存塊釋放回內(nèi)存。用戶空間程序從網(wǎng)卡接收到報文時,將報文發(fā)送給KNI虛擬設(shè)備,KNI虛擬設(shè)備接收到用戶空間程序發(fā)來的報文后,交給內(nèi)核協(xié)議棧進(jìn)行協(xié)議解析。發(fā)送報文時,原始數(shù)據(jù)先由內(nèi)核協(xié)議棧進(jìn)行協(xié)議封裝,然后將報文發(fā)送給KNI虛擬設(shè)備,KNI虛擬設(shè)備接收到報文后,再將報文發(fā)送給用戶空間程序。
?
————————————————
原文鏈接:https://blog.csdn.net/qq_20817327/article/details/105587309
總結(jié)
- 上一篇: DPDK技术简介
- 下一篇: 初学者也能看懂的DPDK解析