DPDK(Data Plane Development Kit)是數據平面開發工具包,由用于加速在各種CPU架構上運行的數據包處理的庫組成。


在Linux上捕獲數據包有多種方式,常見的有libpcap,pf-ring等。DPDK以高性能著稱,想必相比傳統的數據包捕獲方式,一定有其獨到之處。


本文主要就DPDK所使用的技術點進行宏觀的說明,并將其與libpcap,pf-ring進行對比,若有寫的不對的地方請幫忙指出。


參考文檔:

[1]絕對干貨!初學者也能看懂的DPDK解析

[2]Linux 設備驅動之 UIO 機制(基本概念)

[3]PF_RING學習筆記


若出現侵權請聯系作者刪除。


1.DPDK 技術特點


傳統的數據包捕獲瓶頸往往在于Linux Kernel,數據流需要經過Linux Kernel,就會帶來Kernel Spcae和User Space數據拷貝的消耗;系統調用的消耗;中斷處理的消耗等。


DPDK針對Linux Kernel傳統的數據包捕獲模式的問題,進行了一定程度的優化。DPDK的優化可以概括為:


UIO+mmap 實現零拷貝(zero copy)

UIO+PMD 減少中斷和CPU上下文切換

HugePages 減少TLB miss

其他代碼優化

2.UIO


2.1 UIO簡介


UIO(Userspace I/O)是運行在用戶空間的I/O技術。Linux系統中一般的驅動設備都是運行在內核空間,而在用戶空間用應用程序調用即可,而UIO則是將驅動的很少一部分運行在內核空間,而在用戶空間實現驅動的絕大多數功能。



圖片引自百度百科

一個設備驅動的主要任務有兩個:


存取設備的內存

處理設備產生的中斷

如上圖所示,對于存取設備的內存 ,UIO 核心實現了mmap();對于處理設備產生的中斷,內核空間有一小部分代碼用處理中斷,用戶空間通過read()接口/dev/uioX來讀取中斷。


2.2 DPDK UIO機制


采用Linux提供UIO機制,可以旁路Kernel,將所有報文處理的工作在用戶空間完成。



圖片引自參考文檔[1]

如上圖,左邊是傳統的數據包獲取方式,路徑為:

網卡 -> Kernel驅動 -> Kernel TCP/IP協議棧 -> Socket接口 -> 業務

右邊是DPDK的方式,基于UIO。數據路徑為:

網卡 -> DPDK輪詢模式-> DPDK基礎庫 -> 業務


2.3 DPDK 零拷貝(Zero Copy)


通過UIO+mmap 實現數據零拷貝(zero copy)是DPDK的特點之一。那么常規的Linux Kernel(libpcap)以及pf-ring處理數據包的流程要進行幾次數據拷貝呢?


libpcap

libpcap采用的是傳統的數據包獲取方式,如上圖左邊路徑。

網卡接收到數據包后,第一步需要把數據從網卡拷貝到主存(RX buffer)中。但是在這個拷貝的過程中使用了DMA(Direct Memory Access)技術。DMA 傳輸將數據從一個地址空間復制到另外一個地址空間。由CPU 初始化這個傳輸動作,傳輸動作本身是由 DMA 控制器來實行和完成,CPU是不需要參與,也不會產生CPU資源消耗。因此這個第一步的拷貝可以忽略。

第二步,Kernel會將網卡通過DMA傳輸進入主存(RX buffer)的內容拷貝一份進行處理,這里進行了一次數據拷貝。

第三步,由于內核空間和用戶空間的內存是不共享的,Kernel會將數據包內容再進行一次拷貝用于用戶空間使用。

綜上,傳統的數據包捕獲方式(libpcap)會進行兩次數據包拷貝。


pf-rfing

pf-ring采用mmap()將傳統的兩次拷貝減少至一次拷貝。

第一步,同樣使用DMA技術,把數據從網卡拷貝到主存(RX buffer)中。

第二步,pf-ring會將網卡通過DMA傳輸進入主存(RX buffer)的內容拷貝一份放入環形緩沖區中(ring)中,這里進行了一次數據拷貝。

第三步,使用mmap()將環形緩沖區映射至用戶空間,用戶空間可以直接訪問這個環形緩沖區中的數據。


pf-ring zc

pf-ring zc(zero copy)更是將pf-ring的一次拷貝也省去,達到了零拷貝的目的,具體的:

第一步,使用DMA技術,把數據從網卡拷貝到主存(RX buffer)中。

第二步,使用mmap()直接將RX buffer的數據映射到用戶用戶空間,使用戶空間可以直接訪問RX buffer的數據。

下圖非常清晰地展示了pf-ring zc實現零拷貝的過程:



圖片引自參考文檔[3]

DPDK

DPDK實現零拷貝的方式與pf-ring zc類似,首先通過DMA將網卡數據拷貝至主存(RX buffer);隨后使用mmap()直接將RX buffer的數據映射到用戶用戶空間,使用戶空間可以直接訪問RX buffer的數據,以此實現了零拷貝。


由上述可以看出,pf-ring zc和dpdk均可以實現數據包的零拷貝,兩者均旁路了內核,但是實現原理略有不同。pf-ring zc通過zc驅動(也在應用層)接管數據包,dpdk基于UIO實現。