背景
目前,有大量的網(wǎng)絡(luò)應(yīng)用在處理數(shù)據(jù)包的時(shí)候只需要處理數(shù)據(jù)包頭,而不會(huì)操作數(shù)據(jù)負(fù)載部分,例如防火墻、TCP/IP協(xié)議棧和軟件交換機(jī)。對(duì)這類(lèi)網(wǎng)絡(luò)應(yīng)用而言, 包頭處理產(chǎn)生的開(kāi)銷(xiāo)(稱(chēng)為“per-packet overhead”)占了整體開(kāi)銷(xiāo)的大部分。因此,如何減少包頭處理開(kāi)銷(xiāo)是優(yōu)化這類(lèi)應(yīng)用性能的關(guān)鍵。
減少包頭處理開(kāi)銷(xiāo)最直接的方法:減少數(shù)據(jù)包數(shù)量
如何減少包數(shù)量?
增大Maximum Transmission Unit (MTU)。在數(shù)據(jù)量一定的情況下,使用大MTU的數(shù)據(jù)包可攜帶更多數(shù)據(jù),從而減少了包的總量。但MTU值依賴(lài)于物理鏈路,我們無(wú)法保證數(shù)據(jù)包經(jīng)過(guò)的所有鏈路均使用大MTU。
利用網(wǎng)卡特性:Large Receive Offload (LRO),UDP Fragmentation Offload (UFO)和TCP Segmentation Offload (TSO)。如圖1所示,LRO將從物理鏈路收到的TCP包(如1500B)合并為長(zhǎng)度更長(zhǎng)的TCP包(如64KB);UFO和TSO將上層應(yīng)用發(fā)送的長(zhǎng)數(shù)據(jù)負(fù)載的UDP和TCP包(如64KB)拆分成長(zhǎng)度更短的數(shù)據(jù)包(如1500B),以滿(mǎn)足物理鏈路的MTU限制。通過(guò)在網(wǎng)卡上進(jìn)行包合并和拆分,在不需要任何CPU開(kāi)銷(xiāo)的情況下,上層應(yīng)用就可以處理數(shù)量大大減少的大包。然而,LRO、TSO和UFO通常只能處理TCP和UDP包,而且并非所有的網(wǎng)卡都支持這些特性。
軟件包合并 (Generic Receive Offload,GRO)和包拆分 (Generic Segmentation Offload,GSO)。與前兩種方法相比,GRO和GSO有兩個(gè)優(yōu)點(diǎn):第一,不依賴(lài)于物理鏈路和網(wǎng)卡;第二,能夠支持更多的協(xié)議類(lèi)型,如VxLAN和GRE。
圖1. LRO、UFO和TSO工作原理
為了幫助基于DPDK的應(yīng)用程序(如Open vSwitch)減少包頭處理開(kāi)銷(xiāo),DPDK分別于17.08和17.11支持了GRO和GSO。如圖2所示, GRO和GSO是DPDK中的兩個(gè)用戶(hù)庫(kù),應(yīng)用程序直接調(diào)用它們進(jìn)行包合并和分片。
圖2. DPDK GRO和DPDK GSO
1
GRO庫(kù)和GSO庫(kù)結(jié)構(gòu)
圖3描繪了GRO庫(kù)和GSO庫(kù)的結(jié)構(gòu)。根據(jù)數(shù)據(jù)包類(lèi)型,GRO庫(kù)定義了不同的GRO類(lèi)型。每一種GRO類(lèi)型負(fù)責(zé)合并一種類(lèi)型的數(shù)據(jù)包,如TCP/IPv4 GRO處理TCP/IPv4數(shù)據(jù)包。同樣的,GSO庫(kù)也定義了不同的GSO類(lèi)型。GRO庫(kù)和GSO庫(kù)分別根據(jù)MBUF的packet_type域和ol_flags域?qū)⑤斎氲臄?shù)據(jù)包交給對(duì)應(yīng)的GRO和GSO類(lèi)型處理。
圖3. GRO庫(kù)和GSO庫(kù)的框架
2
如何使用GRO庫(kù)和GSO庫(kù)?
使用GRO和GSO庫(kù)十分簡(jiǎn)單。如圖4所示,只需要調(diào)用一個(gè)函數(shù)便可以對(duì)包進(jìn)行合并和分片。
圖4. 代碼示例
為了支持不同的用戶(hù)場(chǎng)景,GRO庫(kù)提供了兩組API:輕量模式API和重量模式API,如圖5所示。輕量模式API應(yīng)用于需要快速合并少量數(shù)據(jù)包的場(chǎng)景,而重量模式API則用于需要細(xì)粒度地控制合包并需要合并大量數(shù)據(jù)包的場(chǎng)景。
圖5. 輕量模式API和重量模式API
3
DPDK GRO的合包算法
算法挑戰(zhàn)
在高速的網(wǎng)絡(luò)環(huán)境下,高開(kāi)銷(xiāo)的合包算法很可能會(huì)導(dǎo)致網(wǎng)卡丟包。
包亂序(“Packet Reordering”)增加了合包難度。例如Linux GRO無(wú)法合并亂序的數(shù)據(jù)包。
這就要求DPDK GRO的合包算法:
足夠輕量以適應(yīng)高速的網(wǎng)絡(luò)環(huán)境
能夠合并亂序包
基于Key的合包算法
為解決上述兩點(diǎn)挑戰(zhàn),DPDK GRO采用基于Key的合包算法,其流程如圖6所示。對(duì)新到的數(shù)據(jù)包,首先按照流(“flow”)對(duì)其進(jìn)行分類(lèi),再在其所在的流中尋找相鄰的數(shù)據(jù)包(“neighbor”)進(jìn)行合并。若無(wú)法找到匹配的流,就插入一條新流并將數(shù)據(jù)包存儲(chǔ)到新流中。若無(wú)法找到鄰居,則將數(shù)據(jù)包存儲(chǔ)到對(duì)應(yīng)的流中。
基于Key的合包算法有兩個(gè)特點(diǎn)。首先,通過(guò)流分類(lèi)來(lái)加速數(shù)據(jù)包的合并是十分輕量的一種做法;其次,保存無(wú)法合并的數(shù)據(jù)包(如亂序包)使得之后對(duì)其進(jìn)行合并成為可能,故減輕了包亂序?qū)习鼛?lái)的影響。
圖6. 基于Key的合包算法流程
例如,TCP/IPv4 GRO使用源和目的Ethernet地址、IP地址、TCP端口號(hào)以及TCP Acknowledge Number定義流,使用TCP Sequence Number和IP ID決定TCP/IPv4包是否為鄰居。若兩個(gè)TCP/IPv4的數(shù)據(jù)包能夠合并,則它們必須屬于同一個(gè)流,并且TCP序號(hào)和IP ID必須連續(xù)。
4
DPDK GSO的分片策略
分片流程
如圖7所示,將一個(gè)數(shù)據(jù)包分片有3個(gè)步驟。首先,將包的數(shù)據(jù)負(fù)載分成許多長(zhǎng)度更小的部分;其次,為每一個(gè)數(shù)據(jù)負(fù)載部分添加包頭(新形成的數(shù)據(jù)包稱(chēng)為GSO Segment);最后,為每個(gè)GSO segment更新包頭(如TCP Sequence Number)。
圖7. GSO分片流程
GSO Segment的結(jié)構(gòu)
生成一個(gè)GSO Segment的最簡(jiǎn)單方法就是拷貝包頭和數(shù)據(jù)負(fù)載部分。但頻繁的數(shù)據(jù)拷貝會(huì)降低GSO性能,因此,DPDK GSO采用了一種基于零拷貝的數(shù)據(jù)結(jié)構(gòu)——Two-part MBUF——來(lái)組織GSO Segment。如圖8所示,一個(gè)Two-part MBUF由一個(gè)Direct MBUF和多個(gè)Indirect MBUF組成。Direct MBUF用來(lái)存儲(chǔ)包頭,Indirect MBUF則類(lèi)似于指針,指向數(shù)據(jù)負(fù)載部分。利用Two-part MBUF,生成一個(gè)GSO Segment僅需拷貝長(zhǎng)度較短的包頭,而不需要拷貝較長(zhǎng)的數(shù)據(jù)負(fù)載部分。
圖8. Two-part MBUF的結(jié)構(gòu)
GRO庫(kù)和GSO庫(kù)的狀態(tài)
目前,GRO庫(kù)還處于一個(gè)初期階段,僅對(duì)使用最廣泛的TCP/IPv4數(shù)據(jù)包提供了合包支持。GSO庫(kù)則支持更豐富的包類(lèi)型,包括TCP/IPv4、VxLAN和GRE。
-
cpu
+關(guān)注
關(guān)注
68文章
10698瀏覽量
209338 -
網(wǎng)卡
+關(guān)注
關(guān)注
3文章
296瀏覽量
27246 -
交換機(jī)
+關(guān)注
關(guān)注
20文章
2571瀏覽量
98242
原文標(biāo)題:怎么提高網(wǎng)絡(luò)應(yīng)用性能?讓DPDK GRO和GSO來(lái)幫你!
文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論