作者:韓文,單位:中國(guó)移動(dòng)智慧家庭運(yùn)營(yíng)中心安全產(chǎn)品部
談到高性能網(wǎng)絡(luò)處理,DPDK已成為用戶態(tài)網(wǎng)絡(luò)數(shù)據(jù)處理的基礎(chǔ)框架,其中最廣泛熟知的項(xiàng)目就是OVS-DPDK。然而由于DPDK完全旁路內(nèi)核,這會(huì)導(dǎo)致TCP/UDP等協(xié)議棧需要在用戶態(tài)重新實(shí)現(xiàn),且迄今還沒有較好的通用用戶態(tài)協(xié)議棧開源項(xiàng)目出現(xiàn)。在這種情況下,XDP借助于eBPF虛擬機(jī)技術(shù)在網(wǎng)卡驅(qū)動(dòng)層實(shí)現(xiàn)高性能網(wǎng)絡(luò)框架,且其原生運(yùn)行在內(nèi)核態(tài)可直通內(nèi)核TCP/UDP協(xié)議棧。XDP作為一種數(shù)據(jù)面高性能框架技術(shù)為平衡高速數(shù)據(jù)處理和協(xié)議棧兼容開辟了一個(gè)新的道路。
1、XDP的基本概念
XDP全稱eXpress Data Path,即快速數(shù)據(jù)路徑,是Linux內(nèi)核提供的高性能、可編程的網(wǎng)絡(luò)數(shù)據(jù)包處理框架。XDP會(huì)直接接管網(wǎng)卡的RX方向數(shù)據(jù)包,通過在內(nèi)核運(yùn)行eBPF指令快速的處理報(bào)文并無縫對(duì)接內(nèi)核協(xié)議棧。
XDP不是內(nèi)核旁路,是在網(wǎng)卡和內(nèi)核協(xié)議棧之間增加了一個(gè)快速數(shù)據(jù)路徑。XDP借助于eBPF技術(shù)從而繼承了其可編程、即時(shí)實(shí)現(xiàn)、安全等優(yōu)良特性。
XDP智能網(wǎng)卡是XDP概念的延伸。在支持eBPF指令的智能網(wǎng)卡上,將CPU上XDP對(duì)應(yīng)的eBPF指令下沉加載到智能網(wǎng)卡,這樣可以同時(shí)實(shí)現(xiàn)CPU資源節(jié)約和規(guī)則硬件卸載。
XDP借助eBPF技術(shù)提供了一個(gè)高性能網(wǎng)絡(luò)處理框架,用戶根據(jù)標(biāo)準(zhǔn)eBPF編程指南來自定義網(wǎng)絡(luò)處理行為。同時(shí)內(nèi)核新增AF_XDP協(xié)議族,在內(nèi)核XDP框架中被匹配的數(shù)據(jù)包通過其送抵用戶態(tài),這又將XDP的支持從內(nèi)核拓展到用戶態(tài)應(yīng)用場(chǎng)景。
2、XDP的整體框架
如下圖1,我們通過XDP整體框架圖來展示其在內(nèi)核系統(tǒng)中的相對(duì)位置以及其如何滿足數(shù)據(jù)平面開發(fā)框架的要求。
圖1 XDP整體框架圖
圖1包含了網(wǎng)卡設(shè)備、XDP框架、TCP/IP協(xié)議棧、Socket接口、應(yīng)用層等各個(gè)層面,覆蓋了網(wǎng)絡(luò)數(shù)據(jù)包從網(wǎng)卡到服務(wù)端的數(shù)據(jù)流全過程。圖1中間的灰色部分(XDP Packet Processor)是XDP框架,其數(shù)據(jù)面處理單元在內(nèi)核中的相對(duì)位置處于網(wǎng)卡驅(qū)動(dòng)和協(xié)議棧之間,實(shí)際運(yùn)行在驅(qū)動(dòng)層。從網(wǎng)卡到CPU處理器的網(wǎng)絡(luò)數(shù)據(jù)包經(jīng)由網(wǎng)卡驅(qū)動(dòng)首先到達(dá)XDP框架,被運(yùn)行在XDP框架中的用戶自定義eBPF程序處理,數(shù)據(jù)包的處理結(jié)果為丟棄(Drop)、轉(zhuǎn)發(fā)(Forward)、本地接受(Receive Local)等,結(jié)果為本地接受的網(wǎng)絡(luò)數(shù)據(jù)包延續(xù)原有內(nèi)核路徑繼續(xù)進(jìn)入TCP/IP協(xié)議棧處理,結(jié)果為轉(zhuǎn)發(fā)或者丟棄的網(wǎng)絡(luò)數(shù)據(jù)包則直接在XDP框架中被直接處理(這部分流量在現(xiàn)實(shí)網(wǎng)絡(luò)中占據(jù)大頭,其執(zhí)行路徑相對(duì)傳統(tǒng)的內(nèi)核路徑被大大縮短)。圖1中間灰色部分(XDP Packet Processor)中的黑色虛線展示了上層控制對(duì)XDP框架中的eBPF程序進(jìn)行加載/更新/配置等通道能力,內(nèi)核提供對(duì)應(yīng)的系統(tǒng)調(diào)用來實(shí)現(xiàn)控制面對(duì)數(shù)據(jù)面的管控。圖1XDP整體框架圖完整的展示了XDP作為一個(gè)高性能網(wǎng)絡(luò)數(shù)據(jù)面和控制面集合的整體框架。
3、XDP應(yīng)用開發(fā)介紹
XDP框架以eBPF技術(shù)為基礎(chǔ)。BPF是一個(gè)通用目的RISC指令集。1992年,BPF第一次在Berkeley實(shí)驗(yàn)室被提出。2013年,BPF被加強(qiáng)從而得到eBPF,并在2014年正式并入Linux內(nèi)核。eBPF提供了一種在各種內(nèi)核和應(yīng)用事件發(fā)生時(shí)運(yùn)行一小段程序的機(jī)制。如下圖2,我們講述eBPF的開發(fā)/運(yùn)行過程及在XDP上的具體應(yīng)用。
圖2 典型eBPF開發(fā)、運(yùn)行流程圖
圖2展示了一個(gè)典型的eBPF開發(fā)、運(yùn)行全過程。開發(fā)者用C語言的一個(gè)子集(內(nèi)核運(yùn)行,不可用標(biāo)準(zhǔn)C庫)開發(fā)程序,然后用LLVM/clang編譯器將其編譯成eBPF指令(Bytecode),在eBPF驗(yàn)證器(Verifier)檢驗(yàn)通過后被內(nèi)核中的即時(shí)編譯器(JIT Compiler)將eBPF指令映射成處理器的原生指令(opcode)再加載到內(nèi)核各個(gè)模塊預(yù)設(shè)的鉤子(Hooks)處。其中XDP框架是內(nèi)核在網(wǎng)卡驅(qū)動(dòng)開辟的一個(gè)網(wǎng)絡(luò)數(shù)據(jù)快速路徑的鉤子(Hooks)。內(nèi)核其他典型鉤子(Hooks)分別為內(nèi)核函數(shù) (kprobes)、用戶空間函數(shù) (uprobes)、系統(tǒng)調(diào)用、fentry/fexit、跟蹤點(diǎn)、網(wǎng)絡(luò)路由、TC、TCP擁塞算法、套接字等模塊。
XDP是內(nèi)核基于eBPF實(shí)現(xiàn)對(duì)網(wǎng)絡(luò)快速路徑的一個(gè)具體應(yīng)用。下圖3我們羅列了內(nèi)核中支持eBPF鉤子(Hooks)節(jié)點(diǎn)的典型應(yīng)用。
圖3 eBPF支持眾多內(nèi)核鉤子應(yīng)用
相比于傳統(tǒng)的用戶態(tài)/內(nèi)核態(tài)程序,eBPF/XDP有如下典型特征:
(1)如下圖4所示,內(nèi)核即時(shí)編譯器(in-kernel JIT Compiler)會(huì)將eBPF字節(jié)碼映射成性能更優(yōu)的處理器原生指令以實(shí)現(xiàn)高性能,同時(shí)其程序校驗(yàn)器(verifier)會(huì)校驗(yàn)程序安全性并提供沙箱運(yùn)行環(huán)境。其安全檢查包含判斷是否有循環(huán),程序長(zhǎng)度是否超過限制,程序內(nèi)存訪問是否越界,程序是否包含不可達(dá)的指令等。最強(qiáng)優(yōu)勢(shì)是可以在不中斷工作負(fù)載下實(shí)現(xiàn)實(shí)時(shí)更新。
圖4 eBPF加載、檢驗(yàn)、編譯示意圖
(2)eBPF程序的內(nèi)核態(tài)與用戶態(tài)數(shù)據(jù)交換通過BPF maps來實(shí)現(xiàn),其類似進(jìn)程間通信的共享內(nèi)存訪問。其支持的數(shù)據(jù)類型有Hash表、數(shù)組、LRU緩存(Least Recently Used)、 環(huán)形隊(duì)列、堆棧軌跡、LPM路由表(Longest Prefix match)。如下圖5所示,BPF Map承擔(dān)了用戶態(tài)和內(nèi)核態(tài)的數(shù)據(jù)交互角色。
圖5 BFP Map銜接用戶態(tài)和內(nèi)核態(tài)的數(shù)據(jù)交互
(3)eBPF通過提供輔助函數(shù)來彌補(bǔ)標(biāo)準(zhǔn)C庫的缺失。常見的如獲取隨機(jī)數(shù)、獲取當(dāng)前時(shí)間、map訪問、獲取進(jìn)程/cgroup上下文、處理網(wǎng)絡(luò)數(shù)據(jù)包和轉(zhuǎn)發(fā)、訪問套接字?jǐn)?shù)據(jù)、執(zhí)行尾調(diào)用、訪問進(jìn)程棧、訪問系統(tǒng)調(diào)用參數(shù)等,在實(shí)際開發(fā)中可通過man bpf-helpers命令獲取更多幫助信息。下圖6展示了一個(gè)bpf命名開頭的獲取隨機(jī)數(shù)輔助函數(shù)。
圖6 BPF輔助函數(shù)范例-獲取隨機(jī)數(shù)
(4)相比純內(nèi)核kmodule等開發(fā)模式,eBPF提供了一種獨(dú)特的尾調(diào)用和函數(shù)調(diào)用機(jī)制。因受內(nèi)核棧空間寶貴及eBPF不支持循環(huán),遞歸深度限制(最大32)等原因,eBPF引入尾調(diào)用和函數(shù)調(diào)用來實(shí)現(xiàn)eBPF程序間跳轉(zhuǎn)。尾調(diào)用和函數(shù)調(diào)用機(jī)制對(duì)性能優(yōu)化做了充分設(shè)計(jì),其中尾調(diào)用能復(fù)用當(dāng)前的棧幀并跳轉(zhuǎn)至另外一個(gè)eBPF程序,具體細(xì)節(jié)請(qǐng)參考bpf_tail_call輔助函數(shù)使用手冊(cè)。由于eBPF程序彼此獨(dú)立,尾調(diào)用機(jī)制在事實(shí)上給開發(fā)者提供了以函數(shù)為單元的編排能力。從Linux 4.16和LLVM 6.0開始,eBPF開始支持函數(shù)調(diào)用,并且在內(nèi)核5.9以后支持尾調(diào)用和函數(shù)調(diào)用的協(xié)同工作。尾調(diào)用的缺點(diǎn)是生成的程序鏡像大但是省內(nèi)存;函數(shù)調(diào)用的優(yōu)點(diǎn)是鏡像小但是內(nèi)存消耗大。開發(fā)者可根據(jù)實(shí)際需要靈活選擇不同的方式。下圖7展示了eBPF程序尾調(diào)用和函數(shù)調(diào)用的混合協(xié)作過程,其中tail call為尾調(diào)用,bpf2bpf call為函數(shù)調(diào)用。
圖7 eBPF程序尾調(diào)用和函數(shù)調(diào)用的混合協(xié)作
4、XDP的同類技術(shù)對(duì)比
以目前最廣泛使用的用戶態(tài)數(shù)據(jù)面開發(fā)框架DPDK為對(duì)標(biāo),我們通過如下數(shù)據(jù)流圖來說明XDP和DPDK的實(shí)現(xiàn)差異。如下圖8,DPDK完全旁路內(nèi)核且運(yùn)行在用戶態(tài),XDP在內(nèi)核中運(yùn)行在網(wǎng)卡和內(nèi)核協(xié)議棧之間。DPDK是脫離內(nèi)核的一個(gè)全新數(shù)據(jù)平面開發(fā)框架,而XDP則是依附于內(nèi)核的一個(gè)快速數(shù)據(jù)路徑(相比原先的內(nèi)核網(wǎng)絡(luò)慢路徑)。
圖8 數(shù)據(jù)流在XDP和DPDK數(shù)據(jù)平面上的走向差異
如下是XDP和DPDK具體的對(duì)比情況:
(1)DPDK會(huì)獨(dú)占CPU資源且需要大頁內(nèi)存。XDP對(duì)CPU不獨(dú)占也不需要大頁內(nèi)存。XDP對(duì)硬件的要求較DPDK更低。
(2)以DPDK為數(shù)據(jù)面框架的項(xiàng)目會(huì)是重開發(fā)人力資源投入,可參考典型項(xiàng)目FD.IO(VPP)和OVS-DPDK。XDP為內(nèi)核原生自帶的快速數(shù)據(jù)通道,是輕量級(jí)數(shù)據(jù)面框架。
(3)DPDK需要網(wǎng)卡驅(qū)動(dòng)和用戶態(tài)協(xié)議棧等各層面的代碼支持和許可證支持。XDP直接由Linux基金會(huì)維護(hù)和發(fā)布,具體技術(shù)生態(tài)由其子項(xiàng)目IO Visor來維護(hù)。
(4)DPDK在大容量高吞吐等場(chǎng)景有優(yōu)勢(shì)。XDP在云原生等場(chǎng)景有優(yōu)勢(shì)。
目前XDP有如下應(yīng)用場(chǎng)景的典型項(xiàng)目:
- DDoS防御
- 防火墻
- 基于XDP的負(fù)載均衡
- 協(xié)議棧前處置
- 云原生應(yīng)用服務(wù)優(yōu)化 (如對(duì)K8S,OpenStack,Docker等服務(wù)改進(jìn)項(xiàng)目)
- 流量控制
5、基于eBPF/XDP的著名開源項(xiàng)目
Cilium是使用eBPF和XDP為容器提供快速的內(nèi)核內(nèi)網(wǎng)絡(luò)和安全策略實(shí)施的開源項(xiàng)目。Cilium項(xiàng)目為Pod和外部服務(wù)之間的流量實(shí)現(xiàn)了分布式負(fù)載平衡,并且能夠完全取代kube-proxy,在eBPF中使用高效的哈希表,允許幾乎無限的擴(kuò)展。它還支持高級(jí)功能,如集成入口和出口網(wǎng)關(guān)、帶寬管理和服務(wù)網(wǎng)格,并提供深度網(wǎng)絡(luò)和安全可見性和監(jiān)控。
如下圖9所示,eBPF/XDP(小蜜蜂)處于容器、Pod等服務(wù)和網(wǎng)卡之間,通過XDP技術(shù)來改善上層服務(wù)的性能和安全,其非常巧妙和安全的在內(nèi)核數(shù)據(jù)流節(jié)點(diǎn)動(dòng)態(tài)完成之前內(nèi)核無法完成的工作。
圖9 Cilium項(xiàng)目組件分布圖
圖10展示了Cilium項(xiàng)目中分別通過XDP和eBPF在內(nèi)核網(wǎng)卡和Socket層實(shí)現(xiàn)功能改善的一個(gè)具體案例。圖10左邊是在網(wǎng)卡驅(qū)動(dòng)層XDP框架植入用戶態(tài)網(wǎng)絡(luò)處理代碼,右邊是在Socket層插入套接字處理代碼,這樣既可以在不修改內(nèi)核的前提下實(shí)現(xiàn)功能動(dòng)態(tài)拓展又實(shí)現(xiàn)了對(duì)上層容器、Pod等典型節(jié)點(diǎn)應(yīng)用的無感知功能升級(jí)。
圖10 Cilium項(xiàng)目中通過XDP和eBPF對(duì)內(nèi)核進(jìn)行功能擴(kuò)展示意圖
Cilium項(xiàng)目為云原生場(chǎng)景下的服務(wù)性能提升和安全改進(jìn)等方面提供了一個(gè)非常好的模范解決方案。如圖11,各類常見的云原生服務(wù)都得益于eBPF/XDP來實(shí)現(xiàn)性能提高和安全改進(jìn)。
圖11 eBPF/XDP在Cilium項(xiàng)目中的核心價(jià)值
6、DP的發(fā)展前景
為實(shí)現(xiàn)靈活的數(shù)據(jù)平面和加速NFV應(yīng)用,Linux基金會(huì)成立子項(xiàng)目IO Visor以實(shí)現(xiàn)基于Linux內(nèi)核延伸出一個(gè)開放可編程的網(wǎng)絡(luò)數(shù)據(jù)面開源項(xiàng)目,XDP屬于IO Visor項(xiàng)目的子項(xiàng)目。Linux內(nèi)核沒有虛擬化是IO Visor在NFV場(chǎng)景下最大的挑戰(zhàn),XDP通過eBPF虛擬機(jī)即時(shí)實(shí)現(xiàn)技術(shù)來彌補(bǔ)這個(gè)缺陷。但是幾乎所有的虛擬機(jī)都運(yùn)行在用戶空間,受制于eBPF虛擬機(jī)在內(nèi)核運(yùn)行的安全性要求,將虛擬化相關(guān)的任務(wù)移植到內(nèi)核空間會(huì)是比較大的挑戰(zhàn)。
在性能改進(jìn)方面,Sebastiano Miano等人于2019年使用XDP和TC鉤子掛載eBPF程序?qū)崿F(xiàn)了Linux的防火墻iptable,在規(guī)則數(shù)量提高的情況下提供相比原始iptable高數(shù)倍甚至數(shù)十倍的性能。Yoann Ghigoff等人于2021年更是基于eBPF和XDP、TC在內(nèi)核中實(shí)現(xiàn)了一層Memcached的緩存,達(dá)到了比DPDK內(nèi)核旁路方案還要高的性能。
XDP項(xiàng)目在傳統(tǒng)內(nèi)核模型和全新用戶態(tài)框架之間開盤了新的道路,用以填補(bǔ)新技術(shù)跨度過大帶來的資源投入陷阱。我們看到微軟在2022年宣布計(jì)劃在Windows平臺(tái)開始支持XDP技術(shù)。隨著整個(gè)生態(tài)環(huán)境的逐步完善,XDP帶來的輕量級(jí)、即時(shí)實(shí)現(xiàn)、高性能通道、安全可靠等能力會(huì)日益發(fā)揮更大的價(jià)值。
中國(guó)移動(dòng)智慧家庭中心會(huì)保持對(duì)XDP技術(shù)的密切跟蹤,從技術(shù)層面持續(xù)跟蹤產(chǎn)業(yè)的發(fā)展方向,對(duì)新興技術(shù)保持開放的心態(tài)并積極擁抱新技術(shù),推動(dòng)產(chǎn)業(yè)界通過新興技術(shù)為廣大人民群眾帶來實(shí)實(shí)在在的數(shù)智化服務(wù)。