LWN: 讓 TCP packet size 大大增加!
關(guān)注了就能看到更多這么棒的文章哦~
Going big with TCP packets
By Jonathan Corbet
February 14, 2022
DeepL assisted translation
https://lwn.net/Articles/884104/
計(jì)算領(lǐng)域的大多數(shù)組件都跟網(wǎng)絡(luò)硬件一樣,會(huì)隨著時(shí)間的推移穩(wěn)步演進(jìn)。事實(shí)上,今天的高端的網(wǎng)絡(luò)接口設(shè)備的數(shù)據(jù)傳輸速度往往比它們所連接的系統(tǒng)能對(duì)數(shù)據(jù)進(jìn)行處理的速度還要快。網(wǎng)絡(luò)開發(fā)人員多年來一直在努力提高網(wǎng)絡(luò)子系統(tǒng)中的可擴(kuò)展性;目前就有 Eric Dumazet 和 Coco Li 的 BIG TCP 這組 patch set 是與此相關(guān)的。BIG TCP 并不適合所有人,但它有可能在某些情況下大幅提高網(wǎng)絡(luò)性能。
舉例來說,如果你希望完全利用好一個(gè) 100Gb/s 的網(wǎng)絡(luò)適配器,那么正如網(wǎng)絡(luò)開發(fā)人員 Jesper Brouer 在 2015 年所描述的那樣,如果仍然按我們長(zhǎng)期以來一直在用的 1538 字節(jié)作為數(shù)據(jù)包的最大 size,那么網(wǎng)卡全速運(yùn)行時(shí)就意味著每秒要處理超過 800 萬個(gè)數(shù)據(jù)包。按這個(gè)速度來算的話,CPU 處理每個(gè)數(shù)據(jù)包僅有大約 120 納秒的時(shí)間,這個(gè)時(shí)間非常短了,只要發(fā)生一次 cache miss 就可能會(huì)耗費(fèi)這么多時(shí)間。
不過,如果減少數(shù)據(jù)包的數(shù)量的話,情況就會(huì)好轉(zhuǎn)。要做到這一點(diǎn)僅僅需要增大數(shù)據(jù)包的 size 就好。因此,高性能的網(wǎng)絡(luò)設(shè)施,尤其是那些把全部設(shè)備都當(dāng)作一個(gè)網(wǎng)絡(luò)單元來統(tǒng)一協(xié)作的局域網(wǎng),通常都會(huì)使用較大的數(shù)據(jù)包 size。在適當(dāng)配置之后就可以使用高達(dá) 64KB 的數(shù)據(jù)包 size,就能大大改善這種情況。但是,在那些需要處理 MB 級(jí)別或 GB 級(jí)別的數(shù)據(jù)(還有更多的,畢竟貓咪視頻也都一直在變大)的環(huán)境中,系統(tǒng)仍然有大量的數(shù)據(jù)包需要處理。
數(shù)據(jù)包數(shù)量太多會(huì)導(dǎo)致影響很多方面的性能。每一個(gè)流經(jīng)此系統(tǒng)的數(shù)據(jù)包都有顯著的固定開銷。每個(gè)數(shù)據(jù)包都必須通過網(wǎng)絡(luò)堆棧的處理,從上層協(xié)議層到網(wǎng)絡(luò)接口的設(shè)備驅(qū)動(dòng)(或按此路徑返回),找到自己該去哪里。更多的數(shù)據(jù)包就意味著來自網(wǎng)絡(luò)適配器的更多中斷。在內(nèi)核中用來表示數(shù)據(jù)包的 sk_buff 結(jié)構(gòu)("SKB")是一個(gè)龐大復(fù)雜的結(jié)構(gòu),因?yàn)樗仨毮軌蛑С秩魏斡锌赡軙?huì)在使用的網(wǎng)絡(luò)功能。這就導(dǎo)致了每個(gè)數(shù)據(jù)包都使用大量?jī)?nèi)存,以及提高了相關(guān)的內(nèi)存管理成本。因此,很希望能夠以更少、且更大的數(shù)據(jù)包為單位來移動(dòng)數(shù)據(jù),至少對(duì)于某些類型的應(yīng)用來說是希望這樣的。
IP 數(shù)據(jù)包的長(zhǎng)度存儲(chǔ)在 IP 頭中;對(duì)于 IPv4 和 IPv6,該長(zhǎng)度存放在一個(gè) 16 bit 的字段中,將數(shù)據(jù)包的最大尺寸限制在了 64KB。在設(shè)計(jì)這些協(xié)議的時(shí)候,一個(gè) 64KB 的數(shù)據(jù)包在當(dāng)時(shí)的骨干互聯(lián)網(wǎng)鏈路(backbone internet links)上可能需要很多秒的時(shí)間來傳輸,所以當(dāng)時(shí)看起來已經(jīng)是一個(gè)非常大的數(shù)字了;其實(shí)那個(gè)時(shí)代任何一個(gè)有理性的人都不會(huì)使用 64KB 來放單個(gè)數(shù)據(jù)包的。但是,時(shí)代變了,64KB 現(xiàn)在看起來是一個(gè)令人沮喪的過低限制。
并不是最近才認(rèn)識(shí)到這個(gè)問題的:在 1999 年通過的 RFC 2675 中可以找到一個(gè)解決方案(至少對(duì) IPv6 而言)。IPv6 規(guī)范允許放置帶有額外信息的 "hop-by-hop" header 頭;顧名思義,hop-by-hop header 會(huì)用來在兩個(gè)直接連接起來的系統(tǒng)之間進(jìn)行 option 選項(xiàng)的交流。RFC 2675 對(duì)協(xié)議進(jìn)行了一些調(diào)整,使得可能支持大型數(shù)據(jù)包了。為了發(fā)送一個(gè) "jumbo" 數(shù)據(jù)包,系統(tǒng)必須將(16 位的)IP payload length 字段設(shè)置為零,并添加一個(gè)包含了真正的 payload length 的 hop-by-hop header。這個(gè) hop-by-hop header 中的 length 字段是 32 位的,這意味著一個(gè) jumbo packet 就可以包含多達(dá) 4GB 的數(shù)據(jù)了,這對(duì)每個(gè)人來說肯定是足夠了。
BIG TCP 這組 patch set 添加了相關(guān)的代碼邏輯,這樣就能在連接的最大傳輸單元(MTU)被設(shè)置得足夠高時(shí)可以生成和接受 jumbo packet。不出所料,這里有許多細(xì)節(jié)需要處理,以便能讓其真正工作起來。其中一個(gè)更重要的問題是,這一系列數(shù)據(jù)包可能就不是存放在物理連續(xù)的內(nèi)存中了,因?yàn)橛袝r(shí)候很難分配到想要的連續(xù)內(nèi)存空間。對(duì)于 zero-copy 操作來說,buffer 是來自用戶空間的,這些數(shù)據(jù)包必定是分散在物理內(nèi)存中各個(gè)地方的。因此,數(shù)據(jù)包經(jīng)常是一組 fragment 片段,每個(gè)片段可能最短會(huì)是一個(gè) 4KB 的 page;網(wǎng)絡(luò)接口在處理數(shù)據(jù)傳輸時(shí)會(huì)負(fù)責(zé)將數(shù)據(jù)包從 fragment 片段組合起來(或在收到網(wǎng)絡(luò)數(shù)據(jù)時(shí)分割成多個(gè) fragment)。
目前的內(nèi)核里將一個(gè) SKB 中存儲(chǔ)的 fragment 數(shù)量限制在了 17 個(gè),這足以將一個(gè) 64KB 的數(shù)據(jù)包用多個(gè) 4KB 的小塊內(nèi)存拼接起來。但是在使用更大 size 的數(shù)據(jù)包的時(shí)候,這個(gè)限制顯然會(huì)導(dǎo)致干擾了,所以 patch set 提高了 fragment 的最大數(shù)量(提升到 45)。但是,正如 Alexander Duyck 所指出的,許多網(wǎng)絡(luò)接口驅(qū)動(dòng)程序?qū)σ粋€(gè)數(shù)據(jù)包可能被分割成的最大 fragment 數(shù)量在代碼中就想當(dāng)然地處理了。他說,在沒有修復(fù)驅(qū)動(dòng)程序的情況下提升這個(gè)上限值可能會(huì)導(dǎo)致性能倒退,甚至導(dǎo)致硬件不可用了。
經(jīng)過一些討論,Dumazet 建議通過增加一個(gè)配置選項(xiàng)來解決這個(gè)問題,用它來控制各個(gè)數(shù)據(jù)包所允許的最大 fragment 數(shù)量。這對(duì)那些自己會(huì)構(gòu)建自己的內(nèi)核的網(wǎng)站來說足夠用了,那些可能會(huì)使用這個(gè)功能的潛在用戶相對(duì)來說可能會(huì)配置成這樣。但是,這對(duì)發(fā)行版提供商來說幫助不大,他們必須要為他們的所有用戶來決定這個(gè)選項(xiàng)的值。
無論如何,都會(huì)有許多驅(qū)動(dòng)程序需要進(jìn)行更新,才能處理 jumbo packet。現(xiàn)代網(wǎng)絡(luò)接口還會(huì)進(jìn)行 segmentation offloading,意味著創(chuàng)建一個(gè)數(shù)據(jù)包的大部分工作是由接口硬件本身來完成的。要想讓 segmentation offloading 跟 jumbo packet 能配合起來,還會(huì)需要進(jìn)行少量調(diào)整,因此在 patch set 中也修改了一些驅(qū)動(dòng)程序的代碼。
還有一個(gè)小問題與 RFC 2675 hop-by-hop header 的位置有關(guān)。根據(jù) IPv6 標(biāo)準(zhǔn),這些頭被放在了 IP 頭之后,這可能會(huì)使那些 "想當(dāng)然地認(rèn)為" TCP 頭是在在數(shù)據(jù)包中的 IP 頭之后緊跟著的位置的軟件代碼失效。tcpdump 工具在這方面就有一些問題,另外,似乎在滿天飛的 BPF 程序中也有不少是含有這種假設(shè)的。因此這個(gè)原因,即使底層硬件和鏈路可以處理這些數(shù)據(jù)包,我們?nèi)匀恍枰?jumbo packet 處理功能默認(rèn)關(guān)閉掉。
Dumazet 在發(fā)布補(bǔ)丁的同時(shí)還包括一些簡(jiǎn)單基準(zhǔn)測(cè)試的結(jié)果。使用 185 KB 字節(jié)的數(shù)據(jù)包 size 之后,網(wǎng)絡(luò)吞吐量增加了近 50%,同時(shí)也大大減少了往返延遲(round-trip latency)。因此,BIG TCP 似乎是一個(gè)很有價(jià)值的可選功能,至少在那些使用了高速鏈接并能可靠地傳送大數(shù)據(jù)包的環(huán)境中(例如數(shù)據(jù)中心)是這樣的。如果未來的貓咪視頻能加載得更快一些了,也許就是得益于咱們的 BIG TCP 呢。
更多細(xì)節(jié)請(qǐng)參見 Dumazet 在 2021 年 Netdev 上的演講。
全文完
LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。
長(zhǎng)按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~
