從DPDK和eBPF感受一下Smart NIC


https://www.daimajiaoliu.com/daima/476145c8c100403

 

安德森先生這周從上海來過周末,小小給媽媽外婆講了剛學到的愷撒加密算法,而我,寫一篇隨筆吧。


周三晚上,我演示了Linux下一代防火牆bpfilter的一個自制簡易POC:

前天晚上在家加班處理問題,一頓操作后沒響應了,以為系統panic了,就等待重啟,遠程登錄的設備,就不知道是不是真panic了還是說僅僅網絡斷了,等待期間擼了下文里的代碼,還測通了,當再想起正事兒的時候,快一個小時過去了,系統依舊沒有恢復…讓同事幫忙帶外check,發現是在我配置vf時網卡reset了,丟了路由…這就是遠程登錄的壞處,搞搞業務代碼還行,搞網絡搞內核的還是機器在眼前,鍵盤在手邊讓人安心啊。
不過好歹我沒有干等,下文分享給大家,一起玩bpfilter和智能網卡吧。必須值得一提的,iproute2和netfilter我已經用了十來年了,前者一直在與時俱進,后者卻幾乎沒有變化,然而這並不意味着netfilter就是一無是處,在我看來5個hook點可以部署成ebpf的容器,配合以pinned map,就完美了,ebpf是瑞士軍刀,它缺個刀鞘,否則容易誤傷自己。
bpfilter是什么,讓我演示給你看:
https://blog.csdn.net/dog250/article/details/103283981

那么,這個和DPDK有什么關系。說實話,本文不該提DPDK的,應該提的是類似netmap,PF_RING的這種東西:
https://www.ntop.org/products/packet-capture/pf_ring/
只不過,DPDK太為人所熟知了,所以就用DPDK來指代這一切,但也只是指代。

本文不說DPDK的細節,因為我也不是很懂,雖然不喜歡DPDK但也不貶它,DPDK在本文中只是一個引子。

不管怎樣,先說結論,DPDK和eBPF都是在吐槽嫌棄現代操作系統內核實現的網絡協議棧。

實話實說,我也覺得網絡協議棧不應該在操作系統內核實現,它只是一個應用,而不是系統的范疇。但是30多年來,網絡協議棧一直都在各大操作系統內核中實現。

之所以這樣,是因為操作系統原初並沒有將數據處理和邏輯控制相分離,通信行業的數據面,控制面,管理面分離的理念並沒有在新生的計算機業內發展起來,人們一團糟地將一切和具體業務無關的東西都塞進了操作系統內核,當然,這也是造成宏內核的根本原因。

隨着計算機網絡技術的發展,通信技術和計算機網絡技術逐漸融合。

把網絡協議棧從操作系統剝離出來的最好方式就是 實現一個數據平面 。

DPDK似乎找到了一種正確的方法,即直接將數據包拉到用戶態來處理,繞過操作系統內核(Tilera Core以及通用的netmap當然也是這種方式)。雖然它們的實現各自不同,但整體看來,這些機制又大又重。

由於網卡功能有限,它沒有邏輯計算單元,僅負責收發數據包的IO操作以及極少量的數據包緩存,大部分的協議流程都必須由主機CPU來完成,即便繞過了操作系統內核,CPU也還是必須的,因此DPDK一般而言都是專門分配一個或者幾個CPU核心來處理數據包。

在這里插入圖片描述

既然數據包來自網卡,何不讓網卡自己去處理?給網卡賦予邏輯處理能力就可以了。

因此,ASIC以及FPGA承擔了高性能網絡處理的職責,專門的電路可以及時就地處理數據包,無需主機CPU參與,解放了CPU。

在這里插入圖片描述

但同樣是大而重的,你必須采用專用的軟件對專門的硬件進行編程,類似DPDK有一套需要學習后才能上手的SDK一樣,FPGA甚至需要專門的語言。

何不在網卡上裝一個足夠通用的CPU配備一塊足夠通用的內存呢,如此網卡就是一個五臟俱全的小型計算機了,既然是個計算機,那就可以執行通用代碼咯。

在這里插入圖片描述

和DPDK把數據包拉到用戶態的方向相反,與其把數據上拉被CPU處理,把處理數據包的代碼向下注入網卡是殊途同歸的,為了讓網卡可以執行注下去的代碼,給網卡內置幾個CPU即可,這就是智能網卡的思路。

DPDK從上面經由用戶態bypass內核協議棧,智能網卡從下面在硬件里offload協議棧的邏輯。

在這個意義上,DPDK其實就是把x86 CPU+Ringbuffer和Intel網卡一起,當成了一塊 “智能網卡”

下面的圖示展示了智能網卡的結構以及注入代碼的執行邏輯,來自netronome的Open-NFP官網:
在這里插入圖片描述
netronome開創了智能網卡新時代,netronome SmartNIC可以配備幾十個處理器同時執行網絡數據包處理的代碼,從而卸載主機CPU的勞力,這就是我們常說的硬件Offload。

那么如何把代碼注入到智能網卡呢?

你可以使用專用的模式,閱讀智能網卡廠商的指令集,然后確保最終的機器碼對應該指令集即可,但幸運的是,我們有通用的eBPF的JIT編譯,可以將eBPF中間字節碼編譯成智能網卡的機器碼。整個過程從編程到部署,非常通用:
在這里插入圖片描述

目前netronome SmartNIC已經實現了該JIT編譯器,參見Linux內核目錄樹:

1linux-source-5.xx/drivers/net/ethernet/netronome 2 3

其中,eBPF字節碼的JIT編譯器在 “nfp/bpf” 子目錄。


具體到Offload如何部署,也是很簡單。一般而言,我們要先用C語言寫一個eBPF程序,比如test.c,然后用clang指定目標體系結構為bpf,將其編譯成二進制字節碼test.o,這個時候,就差一個加載器了。

以我非常喜歡的iproute2套件為例,比方說要把test.o加載到一塊netronome網卡eth0,需要這么做即可:

1ip link set dev eth0 xdpoffload obj test.o 2 3

如此一來,test.c里面的邏輯就可以在智能網卡中被執行了,完全卸載了主機CPU的勞力。

整個操作過程,基本上也就這般。

和大而重的DPDK相比,智能網卡的eBPF小而巧,如果我們把DPDK看成是一門紅衣大炮,那么eBPF就是瑞士軍刀,雖然處理完整的TCP協議還不夠,但是做個數據包攔截,解析是綽綽有余。

eBPF和智能網卡是我們這種手藝人的福音!

編程手藝人指的就是不懂大型軟件工程流程,沒參與過大型軟件開發,不會高級編程語言,沒寫過多少代碼,不會使用發布工具,不經常用git,但也不是一點都不會編程,還是稍微懂一點編程的。不過手藝人精通計算機原理,精通操作系統的實現,精通網絡協議,所以手藝人一般可以輕松完成BUG的定位和fix工作,由於不會大段大段寫代碼,所以手藝人往往精於精准定位,一兩行代碼就能fix,比如加一個mb。所以,手藝人往往在職場工作量上吃虧,手藝人善於自己玩。

幾年前我沒事就想折騰折騰協議棧,比如優化下nf_conntrack啦,把socket指針藏進nf_conntrack啦,把路由項藏進nf_conntrack啦,在網卡層短路協議棧啦,實現一個無狀態NAT啦,在內核實現一個加密通道啦…然而最終也只是玩玩,如今,有了eBPF和XDP,並且eBPF支持了pinned map之后,以上這些都可以重玩了。有時間重新擼一遍,嗯,就這么定了!


介紹些資料:
https://lwn.net/Articles/760041/ 【netronome網卡進化路徑上的絕佳一筆,可以在單片ASIC上共享eBPF程序和map了!】
https://lwn.net/Articles/675826/ 【多端口switch模型,Linux反客為主,打破網絡設備廠商的壟斷】

通用的switchdev驅動模型之前,Linux需要廠商的專門工具套件操作交換機,控制權在廠商,switchdev之后,通用接口被實現,交換機正式納入Linux網絡設備體系,Linux至此可以用標准接口實現交換機的控制面和管理面了,至此以后,各大互聯網廠商的自研交換機才開始遍地開花!!

http://wiki.netfilter.org/pablo/netdev0.1/papers/Rocker-switchdev-prototyping-vehicle.pdf 【多端口switch設備的實例】
下面是我自己寫的一些關於eBPF的文章:
https://blog.csdn.net/dog250/article/details/103283981
https://blog.csdn.net/dog250/article/details/103245748
https://blog.csdn.net/dog250/article/details/102982948
https://blog.csdn.net/dog250/article/details/103094759
https://blog.csdn.net/dog250/article/details/103014526
https://blog.csdn.net/dog250/article/details/102884567


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM