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