[導(dǎo)讀]原文作者:dog250原文鏈接:https://blog.csdn.net/dog250/article/details/103301816周三晚上,我演示了Linux下一代防火墻bpfilter的一個自制簡易POC:前天晚上在家加班處理問題,一頓操作后沒響應(yīng)了,以為系統(tǒng)pani...
原文作者:dog250
原文鏈接:https://blog.csdn.net/dog250/article/details/103301816
周三晚上,我演示了Linux下一代防火墻bpfilter的一個自制簡易POC:
前天晚上在家加班處理問題,一頓操作后沒響應(yīng)了,以為系統(tǒng)panic了,就等待重啟,遠程登錄的設(shè)備,就不知道是不是真panic了還是說僅僅網(wǎng)絡(luò)斷了,等待期間擼了下文里的代碼,還測通了,當(dāng)再想起正事兒的時候,快一個小時過去了,系統(tǒng)依舊沒有恢復(fù)…讓同事幫忙帶外check,發(fā)現(xiàn)是在我配置vf時網(wǎng)卡reset了,丟了路由…這就是遠程登錄的壞處,搞搞業(yè)務(wù)代碼還行,搞網(wǎng)絡(luò)搞內(nèi)核的還是機器在眼前,鍵盤在手邊讓人安心啊。
不過好歹我沒有干等,下文分享給大家,一起玩bpfilter和智能網(wǎng)卡吧。必須值得一提的,iproute2和netfilter我已經(jīng)用了十來年了,前者一直在與時俱進,后者卻幾乎沒有變化,然而這并不意味著netfilter就是一無是處,在我看來5個hook點可以部署成ebpf的容器,配合以pinned map,就完美了,ebpf是瑞士軍刀,它缺個刀鞘,否則容易誤傷自己。
bpfilter是什么,讓我演示給你看:
https://blog.csdn.net/dog250/article/details/103283981
第一,引入虛擬地址的一個重要原因是在軟件(操作系統(tǒng))級進行頁面保護,以防止進程間相互侵犯地址空間。由于這種保護是通過頁表和翻譯旁視緩沖器(TLB)中的保護位(protectionbit)實現(xiàn)的,直接使用虛擬地址來訪問數(shù)據(jù)等于繞過了頁面保護。一個解決辦法是在緩存失效時查看TLB對應(yīng)表項的保護位以確定是否可以加載缺失的數(shù)據(jù)。
那么,這個和DPDK有什么關(guān)系。說實話,本文不該提DPDK的,應(yīng)該提的是類似netmap,PF_RING的這種東西:
https://www.ntop.org/products/packet-capture/pf_ring/
只不過,DPDK太為人所熟知了,所以就用DPDK來指代這一切,但也只是指代。
本文不說DPDK的細節(jié),因為我也不是很懂,雖然不喜歡DPDK但也不貶它,DPDK在本文中只是一個引子。
不管怎樣,先說結(jié)論,DPDK和eBPF都是在吐槽嫌棄現(xiàn)代操作系統(tǒng)內(nèi)核實現(xiàn)的網(wǎng)絡(luò)協(xié)議棧。
實話實說,我也覺得網(wǎng)絡(luò)協(xié)議棧不應(yīng)該在操作系統(tǒng)內(nèi)核實現(xiàn),它只是一個應(yīng)用,而不是系統(tǒng)的范疇。但是30多年來,網(wǎng)絡(luò)協(xié)議棧一直都在各大操作系統(tǒng)內(nèi)核中實現(xiàn)。
之所以這樣,是因為操作系統(tǒng)原初并沒有將數(shù)據(jù)處理和邏輯控制相分離,通信行業(yè)的數(shù)據(jù)面,控制面,管理面分離的理念并沒有在新生的計算機業(yè)內(nèi)發(fā)展起來,人們一團糟地將一切和具體業(yè)務(wù)無關(guān)的東西都塞進了操作系統(tǒng)內(nèi)核,當(dāng)然,這也是造成宏內(nèi)核的根本原因。
隨著計算機網(wǎng)絡(luò)技術(shù)的發(fā)展,通信技術(shù)和計算機網(wǎng)絡(luò)技術(shù)逐漸融合。
把網(wǎng)絡(luò)協(xié)議棧從操作系統(tǒng)剝離出來的最好方式就是 實現(xiàn)一個數(shù)據(jù)平面 。
DPDK似乎找到了一種正確的方法,即直接將數(shù)據(jù)包拉到用戶態(tài)來處理,繞過操作系統(tǒng)內(nèi)核(Tilera Core以及通用的netmap當(dāng)然也是這種方式)。雖然它們的實現(xiàn)各自不同,但整體看來,這些機制又大又重。
由于網(wǎng)卡功能有限,它沒有邏輯計算單元,僅負責(zé)收發(fā)數(shù)據(jù)包的IO操作以及極少量的數(shù)據(jù)包緩存,大部分的協(xié)議流程都必須由主機CPU來完成,即便繞過了操作系統(tǒng)內(nèi)核,CPU也還是必須的,因此DPDK一般而言都是專門分配一個或者幾個CPU核心來處理數(shù)據(jù)包。
既然數(shù)據(jù)包來自網(wǎng)卡,何不讓網(wǎng)卡自己去處理?給網(wǎng)卡賦予邏輯處理能力就可以了。
因此,ASIC以及FPGA承擔(dān)了高性能網(wǎng)絡(luò)處理的職責(zé),專門的電路可以及時就地處理數(shù)據(jù)包,無需主機CPU參與,解放了CPU。
但同樣是大而重的,你必須采用專用的軟件對專門的硬件進行編程,類似DPDK有一套需要學(xué)習(xí)后才能上手的SDK一樣,F(xiàn)PGA甚至需要專門的語言。
何不在網(wǎng)卡上裝一個足夠通用的CPU配備一塊足夠通用的內(nèi)存呢,如此網(wǎng)卡就是一個五臟俱全的小型計算機了,既然是個計算機,那就可以執(zhí)行通用代碼咯。
和DPDK把數(shù)據(jù)包拉到用戶態(tài)的方向相反,與其把數(shù)據(jù)上拉被CPU處理,把處理數(shù)據(jù)包的代碼向下注入網(wǎng)卡是殊途同歸的,為了讓網(wǎng)卡可以執(zhí)行注下去的代碼,給網(wǎng)卡內(nèi)置幾個CPU即可,這就是智能網(wǎng)卡的思路。
DPDK從上面經(jīng)由用戶態(tài)bypass內(nèi)核協(xié)議棧,智能網(wǎng)卡從下面在硬件里offload協(xié)議棧的邏輯。
在這個意義上,DPDK其實就是把x86 CPU Ringbuffer和Intel網(wǎng)卡一起,當(dāng)成了一塊 “智能網(wǎng)卡”
下面的圖示展示了智能網(wǎng)卡的結(jié)構(gòu)以及注入代碼的執(zhí)行邏輯,來自netronome的Open-NFP官網(wǎng):
netronome開創(chuàng)了智能網(wǎng)卡新時代,netronome SmartNIC可以配備幾十個處理器同時執(zhí)行網(wǎng)絡(luò)數(shù)據(jù)包處理的代碼,從而卸載主機CPU的勞力,這就是我們常說的硬件Offload。
那么如何把代碼注入到智能網(wǎng)卡呢?
你可以使用專用的模式,閱讀智能網(wǎng)卡廠商的指令集,然后確保最終的機器碼對應(yīng)該指令集即可,但幸運的是,我們有通用的eBPF的JIT編譯,可以將eBPF中間字節(jié)碼編譯成智能網(wǎng)卡的機器碼。整個過程從編程到部署,非常通用:
目前netronome SmartNIC已經(jīng)實現(xiàn)了該JIT編譯器,參見Linux內(nèi)核目錄樹:
1|linux-source-5.xx/drivers/net/ethernet/netronome
其中,eBPF字節(jié)碼的JIT編譯器在 “nfp/bpf” 子目錄。
具體到Offload如何部署,也是很簡單。一般而言,我們要先用C語言寫一個eBPF程序,比如test.c,然后用clang指定目標體系結(jié)構(gòu)為bpf,將其編譯成二進制字節(jié)碼test.o,這個時候,就差一個加載器了。
以我非常喜歡的iproute2套件為例,比方說要把test.o加載到一塊netronome網(wǎng)卡eth0,需要這么做即可:
1|ip link set dev eth0 xdpoffload obj test.o
如此一來,test.c里面的邏輯就可以在智能網(wǎng)卡中被執(zhí)行了,完全卸載了主機CPU的勞力。
整個操作過程,基本上也就這般。
和大而重的DPDK相比,智能網(wǎng)卡的eBPF小而巧,如果我們把DPDK看成是一門紅衣大炮,那么eBPF就是瑞士軍刀,雖然處理完整的TCP協(xié)議還不夠,但是做個數(shù)據(jù)包攔截,解析是綽綽有余。
eBPF和智能網(wǎng)卡是我們這種手藝人的福音!
編程手藝人指的就是不懂大型軟件工程流程,沒參與過大型軟件開發(fā),不會高級編程語言,沒寫過多少代碼,不會使用發(fā)布工具,不經(jīng)常用git,但也不是一點都不會編程,還是稍微懂一點編程的。不過手藝人精通計算機原理,精通操作系統(tǒng)的實現(xiàn),精通網(wǎng)絡(luò)協(xié)議,所以手藝人一般可以輕松完成BUG的定位和fix工作,由于不會大段大段寫代碼,所以手藝人往往精于精準定位,一兩行代碼就能fix,比如加一個mb。所以,手藝人往往在職場工作量上吃虧,手藝人善于自己玩。
幾年前我沒事就想折騰折騰協(xié)議棧,比如優(yōu)化下nf_conntrack啦,把socket指針藏進nf_conntrack啦,把路由項藏進nf_conntrack啦,在網(wǎng)卡層短路協(xié)議棧啦,實現(xiàn)一個無狀態(tài)NAT啦,在內(nèi)核實現(xiàn)一個加密通道啦…然而最終也只是玩玩,如今,有了eBPF和XDP,并且eBPF支持了pinned map之后,以上這些都可以重玩了。有時間重新擼一遍,嗯,就這么定了!
介紹些資料:
https://lwn.net/Articles/760041/ 【netronome網(wǎng)卡進化路徑上的絕佳一筆,可以在單片ASIC上共享eBPF程序和map了!】
https://lwn.net/Articles/675826/ 【多端口switch模型,Linux反客為主,打破網(wǎng)絡(luò)設(shè)備廠商的壟斷】
通用的switchdev驅(qū)動模型之前,Linux需要廠商的專門工具套件操作交換機,控制權(quán)在廠商,switchdev之后,通用接口被實現(xiàn),交換機正式納入Linux網(wǎng)絡(luò)設(shè)備體系,Linux至此可以用標準接口實現(xiàn)交換機的控制面和管理面了,至此以后,各大互聯(lián)網(wǎng)廠商的自研交換機才開始遍地開花??!
http://wiki.netfilter.org/pablo/netdev0.1/papers/Rocker-switchdev-prototyping-vehicle.pdf 【多端口switch設(shè)備的實例】
本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。