BPF、eBPF、XDP 和 Bpfilter …… 這些東西是什么?
時間:2021-09-03 10:08:22
手機看文章
掃描二維碼
隨時隨地手機看文章
[導(dǎo)讀]↓推薦關(guān)注↓從Linux內(nèi)核3.15開始,您可能一直在關(guān)注內(nèi)核社區(qū)中擴展的BerkeleyPacketFilter(eBPF)的開發(fā),或者您可能仍然將BerkeleyPacketFilter與VanJacobson在1992年所做的工作聯(lián)系起來。您可能已經(jīng)使用BPF和tcpdum...
↓推薦關(guān)注↓
從 Linux 內(nèi)核3.15 開始,您可能一直在關(guān)注內(nèi)核社區(qū)中擴展的 Berkeley Packet Filter (eBPF) 的開發(fā),或者您可能仍然將 Berkeley Packet Filter 與 Van Jacobson 在 1992 年所做的工作聯(lián)系起來。您可能已經(jīng)使用 BPF 和 tcpdump 多年,或者您可能已經(jīng)開始在您的數(shù)據(jù)平面中探測它!本博客旨在從高性能網(wǎng)絡(luò)的角度在高層次上描述BPF的關(guān)鍵發(fā)展,以及為什么它對網(wǎng)絡(luò)運營商、系統(tǒng)管理員和企業(yè)解決方案提供商變得越來越重要。
圖 1. cBPF 與 eBPF 機器的比較
經(jīng)典 BPF (cBPF),舊版本,由一個 32 位寬累加器、一個 32 位寬“X”寄存器(也可以在指令中使用)和 16 個 32 位寄存器(用作暫存存儲器)組成. 這顯然導(dǎo)致了一些關(guān)鍵的限制。顧名思義,經(jīng)典的伯克利數(shù)據(jù)包過濾器主要限于(無狀態(tài))數(shù)據(jù)包過濾。任何更復(fù)雜的事情都將在其他子系統(tǒng)中完成。
eBPF 通過使用一組擴展的寄存器和指令、添加映射(沒有大小限制的鍵/值存儲)、512 字節(jié)堆棧、更復(fù)雜的查找、幫助程序,顯著拓寬了 BPF 的用例集可從程序內(nèi)部調(diào)用的函數(shù),以及鏈接多個程序的可能性?,F(xiàn)在可以進行狀態(tài)處理,也可以與用戶空間程序進行動態(tài)交互。由于這種靈活性的提高,eBPF 處理的數(shù)據(jù)包的分類級別和可能的交互范圍得到了極大的擴展。
但新功能不能以犧牲安全為代價。為確保正確行使 VM 增加的責(zé)任,內(nèi)核中實施的驗證程序已被修訂和整合。這個驗證器檢查代碼中的任何循環(huán)(這可能導(dǎo)致可能的無限循環(huán),從而掛起內(nèi)核)和任何不安全的內(nèi)存訪問。它拒絕任何不符合安全標準的程序。每次用戶嘗試注入程序時,都會在實時系統(tǒng)上執(zhí)行此步驟,然后將 BPF 字節(jié)碼 JIT 轉(zhuǎn)換為所選平臺的本機匯編指令。
圖 2. 主機上 eBPF 程序的編譯流程。一些CPU架構(gòu)沒有顯示。
為了允許在 eBPF 的限制內(nèi)難以執(zhí)行或優(yōu)化的任何關(guān)鍵功能,有許多幫助程序旨在協(xié)助執(zhí)行過程,例如地圖查找或隨機數(shù)的生成。我的同事 Quentin Monnet 目前正在完成記錄所有內(nèi)核助手的過程,并準備了一個補丁供審查。
圖 3. 高性能網(wǎng)絡(luò)相關(guān) eBPF 鉤子性能比較
圖 4. 包含 NFP JIT 的編譯流程(未顯示某些支持的 CPU 架構(gòu))
這是可能的關(guān)鍵原因是因為 BPF 機器映射到我們 NFP 上的流處理核心的程度,這意味著運行在 15-25W 之間的基于 NFP 的 Agilio CX SmartNIC 可以從主機卸載大量處理. 在下面的負載平衡示例中,NFP 處理的數(shù)據(jù)包數(shù)量與來自主機的近 12 個 x86 內(nèi)核的總和相同,由于 PCIe 帶寬限制(使用的內(nèi)核:Intel Xeon CPU E5-2630 v4 @ 2.20GHz)。
圖 5. NFP 和 x86 CPU (E5-2630 v4) 上的示例負載平衡器的比較性能
性能是使用 BPF 硬件卸載是對 SmartNIC 進行編程的正確技術(shù)的主要原因之一。但它不是唯一的:讓我們回顧一些其他的激勵措施。
在此不贅述,還可以注意到與 eBPF 工作流相關(guān)的工具正在開發(fā)中,并且相對于舊的 cBPF 版本已經(jīng)有了很大的改進。用戶現(xiàn)在通常會用 C 編寫程序,然后使用 clang-LLVM 提供的后端將它們編譯成 eBPF 字節(jié)碼。也可以使用其他語言,包括 Go、Rust 或 Lua。傳統(tǒng)工具中添加了對 eBPF 架構(gòu)的支持:llvm-objdump 可以以人類可讀的格式轉(zhuǎn)儲 eBPF 字節(jié)碼,llvm-mc 可以用作 eBPF 匯編器,strace 可以跟蹤對 bpf() 系統(tǒng)調(diào)用的調(diào)用。其他工具的一些工作仍在進行中:binutils 反匯編器應(yīng)該很快就會支持 NFP 微碼,而 valgrind 即將獲得對系統(tǒng)調(diào)用的支持。還創(chuàng)建了新工具:特別是 bpftool,
“這項技術(shù)是針對 Linux 中 iptables 防火墻的新的基于 eBPF 的后端的提議。在撰寫本文時,它還處于非常早期的階段:它在 2018 年 2 月中旬左右由 David Miller(網(wǎng)絡(luò)系統(tǒng)維護者)、Alexei Starovoitov 和 Daniel 在 Linux netdev 郵件列表上作為 RFC(征求意見)提交Borkmann(內(nèi)核中 BPF 部分的維護者)。因此,請記住,隨后的所有細節(jié)都可能發(fā)生變化,或者根本無法到達內(nèi)核!?
從技術(shù)上講,用于配置防火墻的 iptables 二進制文件將保持不變,而內(nèi)核中的 xtables 部分可以透明地替換為一組新命令,這些命令需要 BPF 子系統(tǒng)將防火墻規(guī)則轉(zhuǎn)換為 eBPF 程序。然后可以將此程序附加到與網(wǎng)絡(luò)相關(guān)的內(nèi)核掛鉤之一,例如在流量控制接口 (TC) 或驅(qū)動程序級別 (XDP) 上。規(guī)則轉(zhuǎn)換將發(fā)生在一種新的內(nèi)核模塊中,它介于傳統(tǒng)模塊和普通 ELF 用戶空間二進制文件之間。運行在具有完全權(quán)限但不能直接訪問內(nèi)核的特殊線程中,從而提供較少的攻擊面,這種特殊類型的模塊將能夠直接與 BPF 子系統(tǒng)通信(主要通過系統(tǒng)調(diào)用)。而與此同時,使用標準的用戶空間工具來開發(fā)、調(diào)試甚至模糊它仍然非常容易!除了這個新的模塊對象之外,bpfilter 方法的好處可能很多。由于 eBPF 驗證器,預(yù)計會提高安全性。重用 BPF 子系統(tǒng)可能會使這個組件的維護比遺留 xtables 更容易,并且可能提供與內(nèi)核的其他組件的后續(xù)集成,這些組件也依賴于 BPF。當(dāng)然,利用即時 (JIT) 編譯或可能的程序硬件卸載可以顯著提高性能!”?
bpfilter 正在被開發(fā)作為該問題的解決方案。它允許最終用戶無縫地遷移到這種新的高性能范例。將 CPU 的 8 個內(nèi)核和卸載與一系列簡單的 iptables 規(guī)則的 NFP 與 iptables (netfilter) 傳統(tǒng)后端、較新的 nftables、主機上的 bpfilter 和卸載到 SmartNIC 進行比較,清楚地顯示了性能所在.
圖 7. bpfilter 與舊 iptables 實現(xiàn)的性能比較
- EOF -
從 Linux 內(nèi)核3.15 開始,您可能一直在關(guān)注內(nèi)核社區(qū)中擴展的 Berkeley Packet Filter (eBPF) 的開發(fā),或者您可能仍然將 Berkeley Packet Filter 與 Van Jacobson 在 1992 年所做的工作聯(lián)系起來。您可能已經(jīng)使用 BPF 和 tcpdump 多年,或者您可能已經(jīng)開始在您的數(shù)據(jù)平面中探測它!本博客旨在從高性能網(wǎng)絡(luò)的角度在高層次上描述BPF的關(guān)鍵發(fā)展,以及為什么它對網(wǎng)絡(luò)運營商、系統(tǒng)管理員和企業(yè)解決方案提供商變得越來越重要。
BPF 或 eBPF——有什么區(qū)別?
虛擬機
從根本上說,eBPF 仍然是 BPF:它是一個小型虛擬機,它從用戶空間注入并附加到內(nèi)核中特定鉤子的程序。它可以對網(wǎng)絡(luò)數(shù)據(jù)包進行分類和操作。多年來,它一直在 Linux 上用于過濾數(shù)據(jù)包并避免將昂貴的副本復(fù)制到用戶空間,例如使用 tcpdump。但是,在過去幾年中,虛擬機的范圍已經(jīng)變得面目全非。eBPF 通過使用一組擴展的寄存器和指令、添加映射(沒有大小限制的鍵/值存儲)、512 字節(jié)堆棧、更復(fù)雜的查找、幫助程序,顯著拓寬了 BPF 的用例集可從程序內(nèi)部調(diào)用的函數(shù),以及鏈接多個程序的可能性?,F(xiàn)在可以進行狀態(tài)處理,也可以與用戶空間程序進行動態(tài)交互。由于這種靈活性的提高,eBPF 處理的數(shù)據(jù)包的分類級別和可能的交互范圍得到了極大的擴展。
但新功能不能以犧牲安全為代價。為確保正確行使 VM 增加的責(zé)任,內(nèi)核中實施的驗證程序已被修訂和整合。這個驗證器檢查代碼中的任何循環(huán)(這可能導(dǎo)致可能的無限循環(huán),從而掛起內(nèi)核)和任何不安全的內(nèi)存訪問。它拒絕任何不符合安全標準的程序。每次用戶嘗試注入程序時,都會在實時系統(tǒng)上執(zhí)行此步驟,然后將 BPF 字節(jié)碼 JIT 轉(zhuǎn)換為所選平臺的本機匯編指令。
鉤子 - 數(shù)據(jù)包在哪里分類?
由于其靈活性和實用性,eBPF 的鉤子數(shù)量正在激增。但是,我們將重點關(guān)注數(shù)據(jù)路徑低端的那些。這里的關(guān)鍵區(qū)別在于 eBPF 在驅(qū)動程序空間中添加了一個額外的鉤子。此掛鉤稱為 eXpress DataPath,或 XDP。這允許用戶在將 skb(套接字緩沖區(qū))元數(shù)據(jù)結(jié)構(gòu)添加到數(shù)據(jù)包之前丟棄、反射或重定向數(shù)據(jù)包。這導(dǎo)致性能提高約 4-5 倍。將 eBPF 卸載到 NFP
回到 4.9,我的同事和我們的內(nèi)核驅(qū)動程序維護者 Jakub Kicinski 將網(wǎng)絡(luò)流處理器 (NFP) BPF JIT 編譯器添加到內(nèi)核中,最初用于 cls_bpf ( https://www.spinics.net/lists/netdev/msg379464 .html)。從那時起,Netronome 一直致力于改進內(nèi)核和 LLVM 中的 BPF 基礎(chǔ)設(shè)施,它生成字節(jié)碼(感謝 Jiong Wang 的工作)。通過 NFP JIT,我們設(shè)法有效地修改了程序流程,如下圖所示:性能是使用 BPF 硬件卸載是對 SmartNIC 進行編程的正確技術(shù)的主要原因之一。但它不是唯一的:讓我們回顧一些其他的激勵措施。
- 靈活性:BPF 在主機上提供的主要優(yōu)勢之一是能夠即時重新加載程序。這使得在運行的數(shù)據(jù)中心中動態(tài)替換程序成為可能??赡苁菢渫鈨?nèi)核代碼或插入其他一些不太靈活的子系統(tǒng)的代碼現(xiàn)在可以輕松加載或卸載。由于不需要系統(tǒng)重新啟動的錯誤,這為數(shù)據(jù)中心提供了顯著的優(yōu)勢:相反,只需重新加載調(diào)整后的程序即可。
這個模型現(xiàn)在也可以擴展到卸載。用戶可以在流量運行時動態(tài)加載、卸載、重新加載 NFP 上的程序。這種在運行時動態(tài)重寫固件提供了一個強大的工具來被動地使用 NFP 的靈活性和性能。 - 延遲:通過卸載 eBPF,由于數(shù)據(jù)包不必跨越 PCIe 邊界,延遲顯著減少。這可以改善負載平衡或 NAT 用例的網(wǎng)絡(luò)衛(wèi)生。請注意,通過避免 PCIe 邊界,在 DDoS 預(yù)防案例中也有顯著的好處,因為數(shù)據(jù)包不再跨越邊界,否則可能會在構(gòu)造良好的 DDoS 攻擊下形成瓶頸。
?圖 6. 驅(qū)動程序中卸載的 XDP 與 XDP 的延遲,注意使用卸載時延遲的一致性 - 用于對 SmartNIC 數(shù)據(jù)路徑進行編程的接口:通過能夠使用 eBPF 對 SmartNIC 進行編程,這意味著可以非常輕松地實現(xiàn)諸如速率限制、數(shù)據(jù)包過濾、不良行為者緩解或其他傳統(tǒng) NIC 必須在硅片中實現(xiàn)的功能. 這可以針對最終用戶的特定用例進行定制。
我如何實際使用它?
首先要做的是將內(nèi)核更新到 4.16 或更高版本。我建議使用 4.17(撰寫本文時的開發(fā)版本)或更高版本以利用盡可能多的功能。請參閱用戶指南以獲取最新版本的功能以及如何使用它們的示例。在此不贅述,還可以注意到與 eBPF 工作流相關(guān)的工具正在開發(fā)中,并且相對于舊的 cBPF 版本已經(jīng)有了很大的改進。用戶現(xiàn)在通常會用 C 編寫程序,然后使用 clang-LLVM 提供的后端將它們編譯成 eBPF 字節(jié)碼。也可以使用其他語言,包括 Go、Rust 或 Lua。傳統(tǒng)工具中添加了對 eBPF 架構(gòu)的支持:llvm-objdump 可以以人類可讀的格式轉(zhuǎn)儲 eBPF 字節(jié)碼,llvm-mc 可以用作 eBPF 匯編器,strace 可以跟蹤對 bpf() 系統(tǒng)調(diào)用的調(diào)用。其他工具的一些工作仍在進行中:binutils 反匯編器應(yīng)該很快就會支持 NFP 微碼,而 valgrind 即將獲得對系統(tǒng)調(diào)用的支持。還創(chuàng)建了新工具:特別是 bpftool,
過濾器
對于企業(yè)系統(tǒng)管理員或 IT 架構(gòu)師而言,此時仍然懸而未決的一個關(guān)鍵問題是,這如何適用于擁有已完善和維護多年且基于 iptables 的設(shè)置的最終用戶。更改此設(shè)置的風(fēng)險在于,顯然,某些事情可能令人難以接受,必須修改編排層,應(yīng)該構(gòu)建新的 API,等等。要解決此問題,請輸入建議的 bpfilter 項目。正如昆汀今年早些時候所寫:“這項技術(shù)是針對 Linux 中 iptables 防火墻的新的基于 eBPF 的后端的提議。在撰寫本文時,它還處于非常早期的階段:它在 2018 年 2 月中旬左右由 David Miller(網(wǎng)絡(luò)系統(tǒng)維護者)、Alexei Starovoitov 和 Daniel 在 Linux netdev 郵件列表上作為 RFC(征求意見)提交Borkmann(內(nèi)核中 BPF 部分的維護者)。因此,請記住,隨后的所有細節(jié)都可能發(fā)生變化,或者根本無法到達內(nèi)核!?
從技術(shù)上講,用于配置防火墻的 iptables 二進制文件將保持不變,而內(nèi)核中的 xtables 部分可以透明地替換為一組新命令,這些命令需要 BPF 子系統(tǒng)將防火墻規(guī)則轉(zhuǎn)換為 eBPF 程序。然后可以將此程序附加到與網(wǎng)絡(luò)相關(guān)的內(nèi)核掛鉤之一,例如在流量控制接口 (TC) 或驅(qū)動程序級別 (XDP) 上。規(guī)則轉(zhuǎn)換將發(fā)生在一種新的內(nèi)核模塊中,它介于傳統(tǒng)模塊和普通 ELF 用戶空間二進制文件之間。運行在具有完全權(quán)限但不能直接訪問內(nèi)核的特殊線程中,從而提供較少的攻擊面,這種特殊類型的模塊將能夠直接與 BPF 子系統(tǒng)通信(主要通過系統(tǒng)調(diào)用)。而與此同時,使用標準的用戶空間工具來開發(fā)、調(diào)試甚至模糊它仍然非常容易!除了這個新的模塊對象之外,bpfilter 方法的好處可能很多。由于 eBPF 驗證器,預(yù)計會提高安全性。重用 BPF 子系統(tǒng)可能會使這個組件的維護比遺留 xtables 更容易,并且可能提供與內(nèi)核的其他組件的后續(xù)集成,這些組件也依賴于 BPF。當(dāng)然,利用即時 (JIT) 編譯或可能的程序硬件卸載可以顯著提高性能!”?
bpfilter 正在被開發(fā)作為該問題的解決方案。它允許最終用戶無縫地遷移到這種新的高性能范例。將 CPU 的 8 個內(nèi)核和卸載與一系列簡單的 iptables 規(guī)則的 NFP 與 iptables (netfilter) 傳統(tǒng)后端、較新的 nftables、主機上的 bpfilter 和卸載到 SmartNIC 進行比較,清楚地顯示了性能所在.
概括
因此有它后,內(nèi)核社區(qū)網(wǎng)絡(luò)方面產(chǎn)生了巨大轉(zhuǎn)變。eBPF 是一個強大的工具,它為內(nèi)核帶來了可編程性,它可以處理擁塞控制(TCP-BPF)、跟蹤(kprobes、tracepoints)和高性能網(wǎng)絡(luò)(XDP、cls_bpf)。由于其在社區(qū)中的成功,其他用例可能也會出現(xiàn)。除此之外,也會一直持續(xù)到最終用戶,他們能夠很快平滑地從舊的 iptables 后端,轉(zhuǎn)而使用更新的、更高效的基于 XDP 的后端——使用與今天相同的工具。特別是,這將允許直接的硬件卸載,并在用戶遷移到 10G 及以上網(wǎng)絡(luò)時提供必要的靈活性。轉(zhuǎn)自:極客重生https://www.netronome.com/blog/bpf-ebpf-xdp-and-bpfilter-what-are-these-things-and-what-do-they-mean-enterprise/
- EOF -