久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

萬(wàn)字長(zhǎng)文|深入理解XDP全景指南

 姜換新 2022-01-31

圖片

譯者序

本文翻譯自 2018 年 ACM CoNEXT大會(huì)上的一篇文章:

The eXpress Data Path: Fast Programmable Packet Processing in the Operating System Kernel

作者陣容豪華,,包括來(lái)自 Cilium 的 Daniel Borkmann,、John Fastabend 等。

論文引用信息:

Toke H?iland-J?rgensen, Jesper Dangaard Brouer, Daniel Borkmann, John Fastabend, Tom Herbert, David Ahern, and David Miller. 2018. The eXpress Data Path: Fast Programmable Packet Processing in the Operating System Kernel. In CoNEXT ’18: International Conference on emerging Networking EXperiments and Technologies, December 4–7, 2018, Heraklion, Greece. ACM, New York, NY, USA, 13 pages. https:///10.1145/3281411.3281443

由于譯者水平有限,,本文不免存在遺漏或錯(cuò)誤之處。如有疑問(wèn),,請(qǐng)查閱原文,。

以下是譯文,。

  • 譯者序

  • 摘要

  • 1 引言

    • 1.1 現(xiàn)有方案(kernel bypass)存在的問(wèn)題

    • 1.2 新方案:給內(nèi)核網(wǎng)絡(luò)棧添加可編程能力

    • 1.3 新方案(XDP)的優(yōu)點(diǎn)

    • 1.4 本文組織結(jié)構(gòu)

  • 2 相關(guān)工作

    • 2.1 用戶態(tài)輪詢 vs. XDP

    • 2.2 內(nèi)核模塊 vs. XDP

    • 2.3 可編程硬件 vs. XDP

    • 2.4 小結(jié)

  • 3 XDP 設(shè)計(jì)

    • 唯一加載入口:bpf()系統(tǒng)調(diào)用

    • 校驗(yàn)器工作原理:two-pass DAG

    • 內(nèi)存越界和空指針檢查:職責(zé)上移到程序自身/開(kāi)發(fā)者

    • 跟蹤數(shù)據(jù)訪問(wèn)操作和值范圍

    • 不同類型數(shù)據(jù)的校驗(yàn)信息來(lái)源(source of truth)

    • 校驗(yàn)器的目的

    • 在設(shè)備驅(qū)動(dòng)中執(zhí)行,無(wú)需上下文切換

    • 在軟件最早能處理包的位置執(zhí)行,,性能最優(yōu)

    • XDP 程序典型執(zhí)行流

    • 3.0 XDP 系統(tǒng)架構(gòu)

    • 3.1 XDP driver hook

    • 3.2 eBPF 虛擬機(jī)

    • 3.3 BPF maps

    • 3.4 eBPF verifier

    • 3.5 XDP 程序示例

    • 3.6 小結(jié)

  • 4 性能評(píng)估

    • XDP 未做底層代碼優(yōu)化

    • 通用目的操作系統(tǒng),,首要目標(biāo):更好的擴(kuò)展和配置,,而非極致性能

    • 轉(zhuǎn)發(fā)吞吐(pps)

    • 轉(zhuǎn)發(fā)延遲

    • 4.1 直接棄包(packet drop)性能

    • 4.2 CPU Usage

    • 4.3 包轉(zhuǎn)發(fā)性能

    • 4.4 討論:XDP 性能與 DPDK 還有差距的原因

  • 5 真實(shí)場(chǎng)景使用案例

    • Facebook Katran

    • 性能

    • 模擬 Cloudflare 防御架構(gòu)

    • 程序邏輯

    • 性能

    • 內(nèi)核數(shù)據(jù)平面 & 控制平面(BIRD/FRR)

    • XDP:直接查詢內(nèi)核路由表并轉(zhuǎn)發(fā)

    • 測(cè)試:XDP routing 全球 BGP 路由表

    • 性能:2.5x

    • 5.1 案例一:軟件路由(software routing)

    • 5.2 案例二:Inline DoS Mitigation

    • 5.3 案例三:負(fù)載均衡(load balancing)

  • 6 XDP 的未來(lái)方向

    • 校驗(yàn)邏輯偏保守

    • 缺少標(biāo)準(zhǔn)庫(kù)

    • 一個(gè)網(wǎng)卡接口只能 attach 一個(gè) XDP 程序

    • 6.1 eBPF 程序的限制

    • 6.2 用戶體驗(yàn)和調(diào)試

    • 6.3 驅(qū)動(dòng)支持

    • 6.4 性能提升

    • 6.5 QoS 和 Rate Transitions

    • 6.6 加速傳輸層協(xié)議

    • 6.7 內(nèi)核-用戶空間零拷貝(zero-copy to userspace)

    • 6.8 XDP 作為基礎(chǔ)構(gòu)建模塊(XDP as a building block)

  • 7 總結(jié)

  • 致謝

  • 參考文獻(xiàn)

摘要

近些年業(yè)界流行通過(guò)內(nèi)核旁路(kernel bypass)的方式實(shí)現(xiàn) 可編程的包處理過(guò)程(programmable packet processing),。實(shí)現(xiàn)方式是 將網(wǎng)絡(luò)硬件完全交由某個(gè)專門(mén)的用戶空間應(yīng)用(userspace application) 接管,從而避免內(nèi)核和用戶態(tài)上下文切換的昂貴性能開(kāi)銷,。

但是,,操作系統(tǒng)被旁路(繞過(guò))之后,它的應(yīng)用隔離(application isolation) 和安全機(jī)制(security mechanisms)就都失效了,;一起失效的還有各種經(jīng)過(guò)已經(jīng) 充分測(cè)試的配置,、部署和管理工具

為解決這個(gè)問(wèn)題,我們提出一種新的可編程包處理方式:eXpress Data Path (XDP),。

  • XDP 提供了一個(gè)仍然基于操作系統(tǒng)內(nèi)核的安全執(zhí)行環(huán)境,,在設(shè)備驅(qū)動(dòng)上下文(device driver context)中執(zhí)行,可用于定制各種包處理應(yīng)用,。

  • XDP 是主線內(nèi)核(mainline Linux kernel)的一部分,,與現(xiàn)有的內(nèi)核 網(wǎng)絡(luò)棧(kernel’s networking stack)完全兼容,二者協(xié)同工作,。

  • XDP 應(yīng)用(application)通過(guò) C 等高層語(yǔ)言編寫(xiě),,然后編譯成特定字節(jié)碼;出于安 全考慮,,內(nèi)核會(huì)首先對(duì)這些字節(jié)碼執(zhí)行靜態(tài)分析,,然后再將它們翻譯成 處理器原生指令(native instructions)。

  • 測(cè)試結(jié)果顯示,,XDP 能達(dá)到 24Mpps/core的處理性能,。

為展示 XDP 靈活的編程模型,本文還將給出三個(gè)程序示例,,

  1. layer-3 routing三層路由轉(zhuǎn)發(fā)

  2. inline DDoS protectionDDoS 防護(hù)

  3. layer-4 load balancing四層負(fù)載均衡

1 引言

軟件實(shí)現(xiàn)高性能包處理的場(chǎng)景,,對(duì)每個(gè)包的處理耗時(shí)有著極高的要求。通用目的操作系統(tǒng)中 的網(wǎng)絡(luò)棧更多是針對(duì)靈活性的優(yōu)化,,這意味著它們花在每個(gè)包上 的指令太多了,,不適合網(wǎng)絡(luò)高吞吐的場(chǎng)景。

因此,,隨后出現(xiàn)了一些專門(mén)用于包處理的軟件開(kāi)發(fā)工具,例如 Data Plane Development Kit (DPDK) [16],。這些工具一般都會(huì)完全繞過(guò)內(nèi)核,,將網(wǎng)絡(luò)硬件直接交 給用戶態(tài)的網(wǎng)絡(luò)應(yīng)用,并需要獨(dú)占一個(gè)或多個(gè) CPU,。

1.1 現(xiàn)有方案(kernel bypass)存在的問(wèn)題

內(nèi)核旁路方式可以顯著提升性能,,但缺點(diǎn)也很明顯:

  • 很難與現(xiàn)有系統(tǒng)集成

  • 上層應(yīng)用必須要將內(nèi)核中已經(jīng)非常成熟的模塊在用戶態(tài)重新實(shí)現(xiàn)一遍,,例如路由表,、高層協(xié)議棧等;

  • 最壞的情況下,,這種包處理應(yīng)用只能工作在一個(gè)完全隔絕的環(huán)境,,因?yàn)閮?nèi)核提供的常見(jiàn)工具和部署方式在這種情況下都不可用了

  • 導(dǎo)致系統(tǒng)越來(lái)越復(fù)雜,,而且破壞了操作系統(tǒng)內(nèi)核在把控的安全邊界,。 在基礎(chǔ)設(shè)施逐漸遷移到 Kubernetes/Docker 等容器環(huán)境的背景下,這一點(diǎn)顯得尤其嚴(yán)重,, 因?yàn)樵谶@種場(chǎng)景下,,內(nèi)核擔(dān)負(fù)著資源抽象和隔離的重任,。

1.2 新方案:給內(nèi)核網(wǎng)絡(luò)棧添加可編程能力

對(duì)此,本文提供了另一種解決方案:給內(nèi)核網(wǎng)絡(luò)棧添加可編程能力,。這使得我們能在 兼容各種現(xiàn)有系統(tǒng),、復(fù)用已有網(wǎng)絡(luò)基礎(chǔ)設(shè)施的前提下,仍然實(shí)現(xiàn)高速包處理,。 這個(gè)框架稱為 XDP,,

  • XDP 定義了一個(gè)受限的執(zhí)行環(huán)境(a limited execution environment),運(yùn)行在一個(gè) eBPF 指令虛擬機(jī)中,。eBPF 是 BSD Packet Filter (BPF) [37] 的擴(kuò)展,。

  • XDP 程序運(yùn)行在內(nèi)核上下文中,此時(shí)內(nèi)核自身都還沒(méi)有接觸到包數(shù)據(jù)( before the kernel itself touches the packet data),,這使得我們能在網(wǎng)卡收到包后 最早能處理包的位置,,做一些自定義數(shù)據(jù)包處理(包括重定向)。

  • 內(nèi)核在加載(load)時(shí)執(zhí)行靜態(tài)校驗(yàn),,以確保用戶提供的 XDP 程序的安全,。

  • 之后,程序會(huì)被動(dòng)態(tài)編譯成原生機(jī)器指令(native machine instructions),,以獲得高性能,。

XDP 已經(jīng)在過(guò)去的幾個(gè)內(nèi)核 release 中逐漸合并到內(nèi)核,但在本文之前,,還沒(méi)有關(guān)于 XDP 系統(tǒng)的 完整架構(gòu)介紹,。本文將對(duì) XDP 做一個(gè)高層介紹。

1.3 新方案(XDP)的優(yōu)點(diǎn)

我們的測(cè)試結(jié)果顯示 XDP 能取得 24Mpps/core的處理性能,,這雖然與 DPDK 還有差距,, 但相比于后者這種 kernel bypass 的方式,XDP 有非常多的優(yōu)勢(shì),。

具體地,,XDP:

  1. 與內(nèi)核網(wǎng)絡(luò)棧協(xié)同工作,將硬件的控制權(quán)完全留在內(nèi)核范圍內(nèi),。帶來(lái)的好處:

    • 保持了內(nèi)核的安全邊界

    • 無(wú)需對(duì)網(wǎng)絡(luò)配置或管理工具做任何修改

  2. 無(wú)需任何特殊硬件特性,,任何有 Linux 驅(qū)動(dòng)的網(wǎng)卡都可以支持, 現(xiàn)有的驅(qū)動(dòng)只需做一些修改,,就能支持 XDP hooks,。

  3. 可以選擇性地復(fù)用內(nèi)核網(wǎng)絡(luò)棧中的現(xiàn)有功能,例如路由表或 TCP/IP 協(xié)議棧,,在保持配置接口不變的前提下,,加速關(guān)鍵性能路徑(critical performance paths)。

  4. 保證 eBPF 指令集和 XDP 相關(guān)的編程接口(API)的穩(wěn)定性。

  5. 與常規(guī) socket 層交互時(shí),,沒(méi)有從用戶態(tài)將包重新注入內(nèi)核的昂貴開(kāi)銷,。

  6. 對(duì)應(yīng)用透明。這創(chuàng)造了一些新的部署場(chǎng)景/方式,,例如直接在應(yīng)用所 在的服務(wù)器上部署 DoS 防御(而非中心式/網(wǎng)關(guān)式 DoS 防御),。

  7. 服務(wù)不中斷的前提下動(dòng)態(tài)重新編程(dynamically re-program), 這意味著可以按需加入或移除功能,,而不會(huì)引起任何流量中斷,,也能動(dòng)態(tài)響應(yīng)系統(tǒng)其他部分的的變化。

  8. 無(wú)需預(yù)留專門(mén)的 CPU 做包處理,,這意味著 CPU 功耗與流量高低直接相關(guān),,更節(jié)能。

1.4 本文組織結(jié)構(gòu)

接下來(lái)的內(nèi)容介紹 XDP 的設(shè)計(jì),,并做一些性能分析,。結(jié)構(gòu)組織如下:

  • Section 2 介紹相關(guān)工作;

  • Section 3介紹 XDP 系統(tǒng)的設(shè)計(jì),;

  • Section 4做一些性能分析,;

  • Section 5提供了幾個(gè)真實(shí) XDP 場(chǎng)景的程序例子;

  • Section 6討論 XDP 的未來(lái)發(fā)展方向,;

  • Section 7總結(jié),。

2 相關(guān)工作

XDP當(dāng)然不是第一個(gè)支持可編程包處理的系統(tǒng) —— 這一領(lǐng)域在過(guò)去幾年發(fā)展勢(shì)頭良好, 并且趨勢(shì)還在持續(xù),。業(yè)內(nèi)已經(jīng)有了幾種可編程包處理框架,,以及基于這些框架的新型應(yīng)用,包括:

  • 單一功能的應(yīng)用,,如 switching [47], routing [19], named-based forwarding [28], classification [48], caching [33] or traffic generation [14],。

  • 更加通用、且高度可定制的包處理解決方案,,能夠處理從多種源收來(lái)的數(shù)據(jù)包 [12, 20, 31, 34, 40, 44],。

要基于通用(Common Off The Shelf,,COTS)硬件實(shí)現(xiàn)高性能包處理,,就必須解決 網(wǎng)卡(NIC)和包處理程序之間的所有瓶頸。由于性能瓶頸主要來(lái)源于內(nèi)核和用戶態(tài)應(yīng)用之間的接口(系統(tǒng)調(diào)用開(kāi)銷非常大,,另外,,內(nèi)核功能豐富,但也非常復(fù)雜),, 低層(low-level)框架必須通過(guò)這樣或那樣的方式來(lái)降低這些開(kāi)銷,。

現(xiàn)有的一些框架通過(guò)幾種不同的方式實(shí)現(xiàn)了高性能,XDP構(gòu)建在其中一些技術(shù)之上。 接下來(lái)對(duì) XDP 和它們的異同做一些比較分析,。

2.1 用戶態(tài)輪詢 vs. XDP

  • DPDK[16] 可能是使用最廣泛的高性能包處理框架,。它最初只支持 Intel 網(wǎng)卡,后來(lái)逐 步擴(kuò)展到其他廠商的網(wǎng)卡,。DPDK 也稱作內(nèi)核旁路框架(kernel bypass framework),, 因?yàn)樗鼘⒕W(wǎng)絡(luò)硬件的控制權(quán)從內(nèi)核轉(zhuǎn)移到了用戶態(tài)的網(wǎng)絡(luò)應(yīng)用,完全避免了內(nèi)核-用戶態(tài) 之間的切換開(kāi)銷,。

  • 與DPDK 類似的還有 PF_RINGZC module [45] 和 hardware-specific Solarflare OpenOnload [24],。

在現(xiàn)有的所有框架中,內(nèi)核旁路方式性能是最高的[18],;但如引言中指 出,,這種方式在管理、維護(hù)和安全方面都存在不足,。

XDP 采用了一種與內(nèi)核旁路截然相反的方式:相比于將網(wǎng)絡(luò)硬件的控制權(quán)上移到用戶空間,, XDP 將性能攸關(guān)的包處理操作直接放在內(nèi)核中,在操作系統(tǒng)的網(wǎng)絡(luò)棧之前執(zhí)行,。

  • 這種方式同樣避免了內(nèi)核-用戶態(tài)切換開(kāi)銷(所有操作都在內(nèi)核),;

  • 但仍然由內(nèi)核來(lái)管理硬件,因此保留了操作系統(tǒng)提供的管理接口和安全防護(hù)能力,;

這里的主要?jiǎng)?chuàng)新是:使用了一個(gè)虛擬執(zhí)行環(huán)境,,它能對(duì)加載的 程序進(jìn)行校驗(yàn),確保它們不會(huì)對(duì)內(nèi)核造成破壞,。

2.2 內(nèi)核模塊 vs. XDP

在 XDP 之前,,以內(nèi)核模塊(kernel module)方式實(shí)現(xiàn)包處理功能代價(jià)非常高, 因?yàn)槌绦驁?zhí)行出錯(cuò)時(shí)可能會(huì)導(dǎo)致整個(gè)系統(tǒng)崩潰,,而且內(nèi)核的內(nèi)部 API 也會(huì)隨著時(shí)間發(fā)生變化,。 因此也就不難理解為什么只有很少的系統(tǒng)采用了這種方式。其中做的比較好包括

  • 虛擬交換機(jī)Open vSwitch [44]

  • Click [40]

  • 虛擬機(jī)路由器Contrail [41]

這幾個(gè)系統(tǒng)都支持靈活的配置,,適用于多種場(chǎng)景,,取得比較小的平攤代價(jià)。

XDP通過(guò):

  1. 提供一個(gè)安全的執(zhí)行環(huán)境,,以及內(nèi)核社區(qū)支持,,提供與那些暴露到用戶空間一樣穩(wěn)定的內(nèi)核 API

    極大地降低了那些將處理過(guò)程下沉到內(nèi)核的應(yīng)用(applications of moving processing into the kernel)的成本。

  2. 此外,,XDP 程序也能夠完全繞過(guò)內(nèi)核網(wǎng)絡(luò)棧(completely bypass),, 與在內(nèi)核網(wǎng)絡(luò)棧中做 hook 的傳統(tǒng)內(nèi)核模塊相比,性能也更高,。

  3. XDP 除了能將處理過(guò)程下沉到內(nèi)核以獲得最高性能之外,,還支持在程序中執(zhí)行重定向(redirection)操作,,完全繞過(guò)內(nèi)核網(wǎng)絡(luò)棧,將包送到特殊類型的用戶空間 socket,; 甚至能工作在 zero-copy 模式,,進(jìn)一步降低開(kāi)銷。

    • 這種模式與 Netmap [46] 和 PF_RING [11] 方式類似,,但后者是在沒(méi)有完全繞過(guò)內(nèi) 核的情況下,,通過(guò)降低從網(wǎng)絡(luò)設(shè)備到用戶態(tài)應(yīng)用(network device to userspace application)之間的傳輸開(kāi)銷,實(shí)現(xiàn)高性能包處理,。

內(nèi)核模塊方式的另一個(gè)例子是 Packet I/O engine,,這是 PacketShader [19] 的組成部分, 后者專用于 Arrakis [43] and ClickOS [36] 之類的特殊目的操作系統(tǒng),。

2.3 可編程硬件 vs. XDP

可編程硬件設(shè)備也是一種實(shí)現(xiàn)高性能包處理的方式,。

  • 一個(gè)例子是 NetFPGA [32],通過(guò)對(duì)它暴露的 API 進(jìn)行編程,,能夠在這種基于 FPGA 的專 用設(shè)備上運(yùn)行任何包處理任務(wù),。

  • P4 編程語(yǔ)言 [7] 致力于將這種可編程能力擴(kuò)展到更廣泛的包處理硬件上(巧合的是,它還包括了一個(gè) XDP backend [51]),。

某種意義上來(lái)說(shuō),,XDP 可以認(rèn)為是一種 offload方式

  1. 性能敏感的處理邏輯下放到網(wǎng)卡驅(qū)動(dòng)中,以提升性能,;

  2. 其他的處理邏輯仍然走內(nèi)核網(wǎng)絡(luò)棧,;

  3. 如果沒(méi)有用到內(nèi)核 helper 函數(shù),那整個(gè) XDP 程序都可以 offload 到網(wǎng)卡(目前 Netronome smart-NICs [27] 已經(jīng)支持),。

2.4 小結(jié)

XDP 提供了一種高性能包處理方式,,與已有方式相比,在性能,、與現(xiàn)有系統(tǒng)的集成,、靈活性 等方面取得了更好的平衡。接下來(lái)介紹 XDP 是如何取得這種平衡的,。

3 XDP 設(shè)計(jì)

XDP 的設(shè)計(jì)理念:

  • 高性能包處理

  • 集成到操作系統(tǒng)內(nèi)核(kernel)并與之協(xié)同工作,,同時(shí)

  • 確保系統(tǒng)其它部分的安全性(safety)完整性(integrity)

這種與內(nèi)核的深度集成顯然會(huì)給設(shè)計(jì)帶來(lái)一些限制,在 XDP 組件合并到 Linux 的過(guò)程中,,我們也收到了許多來(lái)自社區(qū)的反饋,,促使我們不斷調(diào)整 XDP 的設(shè)計(jì),但 這些設(shè)計(jì)反思不在本文討論范圍之內(nèi),。

3.0 XDP 系統(tǒng)架構(gòu)

圖 1 描繪了整個(gè) XDP 系統(tǒng),,四個(gè)主要組成部分:

  1. XDP driver hook:XDP 程序的主入口,,在網(wǎng)卡收到包執(zhí)行,。

  2. eBPF virtual machine:執(zhí)行 XDP 程序的字節(jié)碼,,以及對(duì)字節(jié)碼執(zhí)行 JIT 以提升性能。

  3. BPF maps:內(nèi)核中的 key/value 存儲(chǔ),,作為圖中各系統(tǒng)的主要通信通道,。

  4. eBPF verifier:加載程序時(shí)對(duì)其執(zhí)行靜態(tài)驗(yàn)證,以確保它們不會(huì)導(dǎo)致內(nèi)核崩潰,。

圖片

Fig 1. XDP 與 Linux 網(wǎng)絡(luò)棧的集成,。這里只畫(huà)了 ingress 路徑,以免圖過(guò)于復(fù)雜,。

上圖是 ingress 流程,。網(wǎng)卡收到包之后,在處理包數(shù)據(jù)(packet data)之前,,會(huì)先執(zhí)行 main XDP hook 中的 eBPF 程序,。 這段程序可以選擇:

  1. 丟棄(drop)這個(gè)包;或者

  2. 通過(guò)當(dāng)前網(wǎng)卡將包再發(fā)送(send)出去,;或者

  3. 將包重定向(redirect)到其他網(wǎng)絡(luò)接口(包括虛擬機(jī)的虛擬網(wǎng)卡),,或者通過(guò) AF_XDP socket 重定向到用戶空間;或者

  4. 放行(allow)這個(gè)包,,如果后面沒(méi)有其他原因?qū)е碌?drop,,這個(gè)包就會(huì)進(jìn)入常規(guī)的內(nèi)核網(wǎng)絡(luò)棧。如果是這種情況,,也就是放行包進(jìn)入內(nèi)核網(wǎng)絡(luò)棧,,那接下來(lái)在將包放到發(fā)送隊(duì)列之前(before packets are queued for transmission), 還有一個(gè)能執(zhí)行 BPF 程序的地方:TC BPF hook,。

此外,,圖 1 中還可以看出,不同的 eBPF 程序之間,、eBPF 程序和用戶空間應(yīng)用之間,,都能夠通過(guò) BPF maps 進(jìn)行通信

3.1 XDP driver hook

在設(shè)備驅(qū)動(dòng)中執(zhí)行,,無(wú)需上下文切換

XDP 程序在網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)中執(zhí)行,,網(wǎng)絡(luò)設(shè)備每收到一個(gè)包,程序就執(zhí)行一次,。

相關(guān)代碼實(shí)現(xiàn)為一個(gè)內(nèi)核庫(kù)函數(shù)(library function),,因此程序直接 在設(shè)備驅(qū)動(dòng)中執(zhí)行,無(wú)需切換到用戶空間上下文,。

在軟件最早能處理包的位置執(zhí)行,,性能最優(yōu)

回到上面圖 1 可以看到:程序在網(wǎng)卡收到包之后最早能處理包的位置執(zhí)行 —— 此時(shí)內(nèi)核還沒(méi)有為包分配 struct sk_buff 結(jié)構(gòu)體, 也沒(méi)有執(zhí)行任何解析包的操作,。

XDP 程序典型執(zhí)行流

下圖是一個(gè)典型的 XDP 程序執(zhí)行流:

圖片

Fig 2. 典型 XDP 程序的執(zhí)行流,。

網(wǎng)卡收到一個(gè)包時(shí),,XDP程序依次執(zhí)行:

  1. 提取包頭中的信息(例如 IP、MAC,、Port,、Proto 等),

    執(zhí)行到程序時(shí),,系統(tǒng)會(huì)傳遞給它一個(gè)上下文對(duì)象(context object)作為參賽(即 struct xdp_md *ctx,,后面有例子),其中包括了指向原 始包數(shù)據(jù)的指針,,以及描述這個(gè)包是從哪個(gè)網(wǎng)卡的哪個(gè)接口接收上來(lái)的等元數(shù)據(jù)字段,。

  2. 讀取或更新一些資源的元信息(例如更新統(tǒng)計(jì)信息);

    解析包數(shù)據(jù)之后,,XDP 程序可以讀取 ctx 中的包元數(shù)據(jù)(packet metadata) 字段,,例如從哪個(gè)網(wǎng)卡的哪個(gè)接口收上來(lái)的(ifindex)。除此之外,,ctx 對(duì)象還允許 程序訪問(wèn)與包數(shù)據(jù)毗鄰的一塊特殊內(nèi)存區(qū)域(cb, control buffer),, 在包穿越整個(gè)系統(tǒng)的過(guò)程中,可以將自定義的數(shù)據(jù)塞在這里,。

    除了 per-packet metadata,,XDP 程序還可以通過(guò) BPF map 定義和訪問(wèn)自己的持久數(shù)據(jù),以及通過(guò)各種 helper 函數(shù)訪問(wèn)內(nèi)核基礎(chǔ)設(shè)施,。

    • BPF map 使 BPF 程序能與系統(tǒng)的其他部分之間通信,;

    • Helpers 使 BPF 程序能利用到某些已有的內(nèi)核功能(例如路由表), 而無(wú)需穿越整個(gè)內(nèi)核網(wǎng)絡(luò)棧,。

  3. 如果有需要,對(duì)這個(gè)包進(jìn)行 rewrite header操作,,

    程序能修改包數(shù)據(jù)的任何部分,包括添加或刪除包頭,。這使得 XDP 程序能執(zhí)行封裝/接封裝操作,,以及重寫(xiě)(rewrite)地址字段然后轉(zhuǎn)發(fā)等操作,。

    內(nèi)核 helper 函數(shù)各有不同用途,,例如修改一個(gè)包之后,計(jì)算新的校驗(yàn)和(checksum),。

  4. 進(jìn)行最后的判決(verdict),確定接下來(lái)對(duì)這個(gè)包執(zhí)行什么操作;

    判決結(jié)果包括:

    重定向功能的用途

    這些不同的路徑,,在圖 1 對(duì)應(yīng)的是幾條實(shí)線。

    重定向判決(verdict)與重定向目標(biāo)(target)分開(kāi),,使得重定向目標(biāo)類型很容易擴(kuò)展,; 另外,,由于重定向參數(shù)(目標(biāo))是通過(guò) BPF map 查詢的,,因此無(wú)需修 改 XDP 程序,,就能動(dòng)態(tài)修改重定向目標(biāo),。

    • 三種簡(jiǎn)單返回碼:丟棄這個(gè)包、通過(guò)接收時(shí)的網(wǎng)卡將包重新發(fā)送出去、允許這個(gè)包進(jìn)入內(nèi)核網(wǎng)絡(luò)棧,;

    • 第四種返回碼 redirect:允許 XDP 程序指定網(wǎng)卡,、CPU、用戶態(tài) socket等,,將包重定向過(guò)去,。

    1. 將原始包通過(guò)另一個(gè)網(wǎng)卡(包括虛擬機(jī)的虛擬網(wǎng)卡)發(fā)送出去;

    2. 轉(zhuǎn)發(fā)給指定 CPU做進(jìn)一步處理,;

    3. 轉(zhuǎn)發(fā)給 AF_XDP 類型的 socket做進(jìn)一步處理,;

程序還能通過(guò)尾調(diào)用(tail call),將控制權(quán)交給另一個(gè) XDP 程序,; 通過(guò)這種方式,,可以將一個(gè)大程序拆分成幾個(gè)邏輯上的小程序(例如,根據(jù) IPv4/IPv6),。

由于 XDP 程序可包含任意指令,,因此前三步(讀取包數(shù)據(jù)、處理元數(shù)據(jù),、重寫(xiě)包數(shù)據(jù)) 順序可以是任意的,,而且支持多層嵌套,。 但實(shí)際中為了獲得高性能,,大部分情況下還是將執(zhí)行結(jié)構(gòu)組織成這順序的三步。

3.2 eBPF 虛擬機(jī)

XDP 程序在 Extended BPF (eBPF) 虛擬機(jī)中執(zhí)行,。eBPF 是早期 BSD packet filter (BPF) [37] 的擴(kuò)展,,后者在過(guò)去的幾十年中廣泛 應(yīng)用于各種包處理工具。

BPF 使用 基于寄存器的(register-based) virtual machine 來(lái)描述 過(guò)濾動(dòng)作(filtering actions),。

eBPF 虛擬機(jī)支持動(dòng)態(tài)加載(loading)和重加載(re-loading)程序,,內(nèi)核管理所有 BPF 程序的生命周期

3.3 BPF maps

eBPF 程序在觸發(fā)內(nèi)核事件時(shí)執(zhí)行(例如,,觸發(fā) XDP 程序執(zhí)行的,,是收包事件)。 程序每次執(zhí)行時(shí),,初始狀態(tài)都是相同的(即程序是無(wú)狀態(tài)的),,它們無(wú)法直接訪問(wèn)內(nèi)核中的持久存儲(chǔ)(BPF map)。為此,,內(nèi)核提供了訪問(wèn) BPF map 的 helper 函數(shù),。

BPF map 是 key/value 存儲(chǔ),在加載 eBPF 程序時(shí)定義(defined upon loading an eBPF program),。

用途:

  1. 持久存儲(chǔ),。例如一個(gè) eBPF 程序每次執(zhí)行時(shí),都會(huì)從里面獲取上一次的狀態(tài)。

  2. 用于協(xié)調(diào)兩個(gè)或多個(gè) eBPF 程序,。例如一個(gè)往里面寫(xiě)數(shù)據(jù),,一個(gè)從里面讀數(shù)據(jù)。

  3. 用于用戶態(tài)程序和內(nèi)核 eBPF 程序之間的通信,。

3.4 eBPF verifier

唯一加載入口:bpf()系統(tǒng)調(diào)用

由于 eBPF 代碼直接運(yùn)行在內(nèi)核地址空間,,因此它能直接訪問(wèn) —— 也可 能是破壞 —— 任何內(nèi)存。為防止這種情況發(fā)生,,內(nèi)核規(guī)定只能通過(guò)唯一入口( bpf() 系統(tǒng)調(diào)用)加載 BPF 程序,。

加載 BPF 程序時(shí),位于內(nèi)核中的校驗(yàn)器首先會(huì)對(duì)字節(jié)碼程序進(jìn)行靜態(tài)分析,,以確保

  • 程序中沒(méi)有任何不安全的操作(例如訪問(wèn)任意內(nèi)存),,

  • 程序會(huì)終止(terminate)。通過(guò)下面這兩點(diǎn)來(lái)實(shí)現(xiàn):

    • 禁止循環(huán)操作

    • 限制程序最大指令數(shù)

校驗(yàn)器工作原理:two-pass DAG

校驗(yàn)器的工作原理:首先根據(jù)程序的控制流構(gòu)建一個(gè)有向無(wú)環(huán)圖(DAG),, 然后對(duì) DAG 執(zhí)行如下校驗(yàn):

  • 首先,,對(duì) DAG 進(jìn)行一次深度優(yōu)先搜索(depth-first search),以 確保它是無(wú)環(huán)的(acyclic),,例如,,沒(méi)有循環(huán),也不包含不支持或無(wú)法執(zhí)行到的指令,。

  • 然后,,再掃描一遍,這次會(huì)遍歷 DAG 的所有可能路徑,。這次掃描的目的是:

    程序執(zhí)行 load或 call指令時(shí),,如果參數(shù)不合法,就會(huì)在這里被拒絕,。參數(shù)合法 性是通過(guò)在程序執(zhí)行期間跟蹤所有寄存器和棧變量的狀態(tài)(states of registers and stack variables)來(lái)實(shí)現(xiàn)的,。

    • 確保程序的內(nèi)存訪問(wèn)都是安全的,

    • 調(diào)用 helper 函數(shù)時(shí)傳的參數(shù)類型是對(duì)的,。

內(nèi)存越界和空指針檢查:職責(zé)上移到程序自身/開(kāi)發(fā)者

這種跟蹤寄存器狀態(tài)的機(jī)制是為了在無(wú)法預(yù)知內(nèi)存邊界的情況下,,仍然確保程序 的內(nèi)存訪問(wèn)不會(huì)越界。無(wú)法預(yù)知內(nèi)存邊界是因?yàn)椋?/p>

  • 包的大小是不固定的,;

  • map 的內(nèi)容也無(wú)法提前預(yù)知,,因此也無(wú)法判斷一次 map 查找操作是否會(huì)成功。

為解決這個(gè)問(wèn)題,,校驗(yàn)器會(huì)檢查已加載的程序自身是否會(huì)做如下檢查

  1. 解引用指針前做了內(nèi)存邊界檢查,,

  2. 查詢 map 之前是檢查了 map 指針是否為空。

這種方式將處理邏輯中的安全檢查和遇到錯(cuò)誤時(shí)如何處理的控制權(quán)都 交給了 BPF 程序的編寫(xiě)者,。

跟蹤數(shù)據(jù)訪問(wèn)操作和值范圍

為跟蹤數(shù)據(jù)訪問(wèn),,校驗(yàn)器會(huì)跟蹤

  1. 數(shù)據(jù)類型

  2. 指針偏置(pointer offsets)

  3. 所有寄存器的可能值范圍

程序開(kāi)始時(shí),,

  • R1寄存器中存儲(chǔ)的是指向 context metadata 的指針(struct xdp_md *ctx),

  • R10是棧指針(stack pointer),

  • 其他所有寄存器都是未初始化狀態(tài),。

接下來(lái)程序每執(zhí)行一步,,寄存器狀態(tài)就會(huì)更新一次。當(dāng)寄存器中存入一個(gè)新值時(shí),,這個(gè)寄存器 還會(huì)繼承與這個(gè)值相關(guān)的狀態(tài)變量(inherits the state variables from the source of the value),。

算術(shù)操作會(huì)影響標(biāo)量類型的值的范圍(value ranges of scalar types),以及指針類型的 offset,。 可能的最大范圍(max possible range)存儲(chǔ)在狀態(tài)變量中,,例如往寄存器中 load 一個(gè)字節(jié)時(shí), 這個(gè)寄存器的可能值范圍就設(shè)置為 0~255,。指令圖(instruction graph)中的 各邏輯分支就會(huì)根據(jù)操作結(jié)果更新寄存器狀態(tài),。例如,比較操作 R1 > 10,,

  • 校驗(yàn)器在一個(gè)分支 if R1 > 10中會(huì)將 R1 最小值設(shè)為 11,,

  • 在另一個(gè) else分支中將其最大值設(shè)為 10。

不同類型數(shù)據(jù)的校驗(yàn)信息來(lái)源(source of truth)

利用狀態(tài)變量中存儲(chǔ)的范圍信息,,校驗(yàn)器就能預(yù)測(cè)每個(gè) load 指令能訪問(wèn)的所有 內(nèi)存范圍,,確保它執(zhí)行的都是合法內(nèi)存訪問(wèn)。

  1. 對(duì)于包數(shù)據(jù)(packet data)的訪問(wèn),,會(huì)與 context 對(duì)象中的 data_end變量做比較,;

  2. 對(duì)于 BPF map 中獲取的值,或用到 map 定義中聲明的 data size 信息,;

  3. 對(duì)于棧上存儲(chǔ)的值,,會(huì)檢查狀態(tài)變量中記錄的值范圍,;

  4. 對(duì)于指針?biāo)阈g(shù)操作(pointer arithmetic)還會(huì)施加額外的限制,,指針通常不能被轉(zhuǎn)換成整形值。

只要校驗(yàn)器無(wú)法證明某個(gè)操作是安全,,該 BPF 程序在加載時(shí)(load time)就會(huì)被拒絕,。 除此之外,校驗(yàn)器還會(huì)利用范圍信息確保內(nèi)存的對(duì)齊訪問(wèn)(enforce aligned memory access),。

校驗(yàn)器的目的

需要說(shuō)明的是,,校驗(yàn)器的目的是避免將內(nèi)核內(nèi)部(the internals of the kernel )暴露給惡意或有缺陷的 eBPF 程序,而非確保程序中函數(shù)的實(shí)現(xiàn)已經(jīng)是最高效的,。

換句話說(shuō),,如果 XDP 程序中處理邏輯過(guò)多,也可能會(huì)導(dǎo)致機(jī)器變慢 ,;如果代碼寫(xiě)的有問(wèn)題,,也可能會(huì)破壞包數(shù)據(jù),。出于這些原因,加載 BPF 程序需要 管理員權(quán)限(root),。避免這些 bug 的責(zé)任在程序員,,但選擇將哪些程序加載 到系統(tǒng)的權(quán)限在管理員。

3.5 XDP 程序示例

下面是一個(gè)簡(jiǎn)單的 XDP 程序,,展示了前面介紹的一些特性,。 程序會(huì)解析包數(shù)據(jù),判斷如果是 UDP 包,,直接交換源和目的 MAC 地址,,然后將包從相同網(wǎng)卡再發(fā)送回去,

雖然這是一個(gè)非常簡(jiǎn)單的例子,,但真實(shí)世界中的 XDP 程序用到的組件和特性,,這里基本都具備了。

// 從內(nèi)核 BPF 代碼示例 xdp2_kern.c 修改而來(lái),。

1 // 用于統(tǒng)計(jì)包數(shù)
2 struct bpf_map_def SEC('maps') rxcnt = {
3 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
4 .key_size = sizeof(u32), // IP 協(xié)議類型,,即 IPv4/IPv6
5 .value_size = sizeof(long), // 包數(shù)
6 .max_entries = 256,
7 };
8
9 // 直接操作包數(shù)據(jù)(direct packet data access),交換 MAC 地址
10 static void swap_src_dst_mac(void *data)
11 {
12 unsigned short *p = data;
13 unsigned short dst[3];
14 dst[0] = p[0]; dst[1] = p[1]; dst[2] = p[2];
15 p[0] = p[3]; p[1] = p[4]; p[2] = p[5];
16 p[3] = dst[0]; p[4] = dst[1]; p[5] = dst[2];
17 }
18
19 static int parse_ipv4(void *data, u64 nh_off, void *data_end)
20 {
21 struct iphdr *iph = data nh_off;
22 if (iph 1 > data_end)
23 return 0;
24 return iph->protocol;
25 }
26
27 SEC('xdp1') // marks main eBPF program entry point
28 int xdp_prog1(struct xdp_md *ctx)
29 {
30 void *data_end = (void *)(long)ctx->data_end;
31 void *data = (void *)(long)ctx->data;
32 struct ethhdr *eth = data; int rc = XDP_DROP;
33 long *value; u16 h_proto; u64 nh_off; u32 ipproto;
34
35 nh_off = sizeof(*eth);
36 if (data nh_off > data_end)
37 return rc;
38
39 h_proto = eth->h_proto;
40
41 /* check VLAN tag; could be repeated to support double-tagged VLAN */
42 if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
43 struct vlan_hdr *vhdr;
44
45 vhdr = data nh_off;
46 nh_off = sizeof(struct vlan_hdr);
47 if (data nh_off > data_end)
48 return rc;
49 h_proto = vhdr->h_vlan_encapsulated_proto;
50 }
51
52 if (h_proto == htons(ETH_P_IP))
53 ipproto = parse_ipv4(data, nh_off, data_end);
54 else if (h_proto == htons(ETH_P_IPV6))
55 ipproto = parse_ipv6(data, nh_off, data_end);
56 else
57 ipproto = 0;
58
59 /* lookup map element for ip protocol, used for packet counter */
60 value = bpf_map_lookup_elem(&rxcnt, &ipproto);
61 if (value)
62 *value = 1;
63
64 /* swap MAC addrs for UDP packets, transmit out this interface */
65 if (ipproto == IPPROTO_UDP) {
66 swap_src_dst_mac(data);
67 rc = XDP_TX;
68 }
69 return rc;
70 }

具體地:

  • 定義了一個(gè) BPF map 存儲(chǔ)統(tǒng)計(jì)信息,。用戶態(tài)程序可以 poll 這個(gè) map 來(lái)獲取統(tǒng)計(jì)信息,。

  • context 對(duì)象 struct xdp_md *ctx中有包數(shù)據(jù)的 start/end 指針,可用于直接訪問(wèn)包數(shù)據(jù),。

  • 將數(shù)據(jù)指針和 data_end比較,,確保內(nèi)存訪問(wèn)不會(huì)越界。

  • 程序必須自己解析包,,包括 VLAN headers 等東西,。

  • 直接通過(guò)指針(direct packet data access)修改包頭

  • 內(nèi)核提供的 map lookup helper,。這是程序中唯一的真實(shí)函數(shù)調(diào)用,;其他函數(shù)都是內(nèi)聯(lián),包括 htons(),。

  • 最終針對(duì)這個(gè)包的判決通過(guò)程序返回值傳遞給調(diào)用方,。

將這段程序安裝到網(wǎng)卡接口上時(shí),它首先會(huì)被編譯成 eBPF 字節(jié)碼,,然后經(jīng)受校驗(yàn)器檢查,。 這里的檢查項(xiàng)包括:

  1. 無(wú)循環(huán)操作;程序大?。ㄖ噶顢?shù)量),;

  2. 訪問(wèn)包數(shù)據(jù)之前,做了內(nèi)存邊界檢查,;

  3. 傳遞給 map lookup 函數(shù)的參數(shù),,類型與 map 定義相匹配,;

  4. map lookup 的返回值(value 的內(nèi)存地址)在使用之前,檢查了是否為 NULL,。

3.6 小結(jié)

XDP系統(tǒng)由四個(gè)主要部分組成:

  1. XDP device driver hook:網(wǎng)卡收到包之后直接運(yùn)行,;

  2. eBPF虛擬機(jī):執(zhí)行 XDP 程序(以及內(nèi)核其他模塊加載的 BPF 程序);

  3. BPF maps:使不同 BPF 程序之間,、BPF 程序與用戶空間應(yīng)用之間能夠通信,;

  4. eBPF verifier:確保程序不包含任何可能會(huì)破壞內(nèi)核的操作。

這四部分加在一起,,創(chuàng)造了一個(gè)編寫(xiě)自定義包處理應(yīng)用的強(qiáng)大環(huán)境,,它能加速包處理的關(guān)鍵 路徑,同時(shí)還與內(nèi)核及現(xiàn)有基礎(chǔ)設(shè)施密切集成,。

接下來(lái)看一下 XDP 應(yīng)用的性能,。

4 性能評(píng)估

DPDK 是目前性能最高的包處理框架 [18],因此本文將 XDP 與 DPDK 及 Linux 內(nèi)核網(wǎng)絡(luò) 棧的性能做一個(gè)對(duì)比,。測(cè)試機(jī)器環(huán)境:

  • CPU:一塊 hexa-core Intel Xeon E5-1650 v4 CPU running at 3.60GHz,, 支持 Intel Data Direct I/O (DDIO) 技術(shù),網(wǎng)絡(luò)硬件通過(guò) DMA 能直接將包放到 CPU 緩存,。

  • 關(guān)閉超線性(Hyperthreading),。

  • 網(wǎng)卡:兩塊 Mellanox ConnectX-5 Ex VPI dual-port 100Gbps,mlx5 驅(qū)動(dòng),。

  • 內(nèi)核:Linux 4.18

  • 使用基于 DPDK 的 TRex packet generator [9] 生成測(cè)試流量,。所有測(cè)試腳本位于 [22]。

在測(cè)試中,,我們主要關(guān)心三個(gè) metric:

  • 直接棄包(packet drop)性能,。

    為展示最高的包處理性能,我們將用最簡(jiǎn)單的操作 —— 丟棄接收到的包—— 來(lái)測(cè)試,。 這個(gè)測(cè)試能有效測(cè)量系統(tǒng)的整體開(kāi)銷,,也是真正的包處理應(yīng)用能達(dá)到的性能上限

  • CPU 使用量,。

    如引言中指出,,XDP 的優(yōu)點(diǎn)之一是 CPU 使用量與流量大小是正相關(guān)的,而無(wú)需預(yù)留專 門(mén)的 CPU 給它用,。我們通過(guò)測(cè)量 CPU 利用率隨網(wǎng)絡(luò)負(fù)載的變化來(lái)量化這個(gè)指標(biāo)。

  • 包轉(zhuǎn)發(fā)性能,。

    轉(zhuǎn)發(fā)的復(fù)雜性要更高一些,,例如,涉及到與多塊網(wǎng)卡的交互,、重寫(xiě)二層頭等等,。 這里會(huì)將轉(zhuǎn)發(fā)延遲也考慮進(jìn)去,。

我們已經(jīng)驗(yàn)證,使用 MTU(1500 字節(jié))包時(shí),,我們的系統(tǒng)單核就能達(dá)到線速(100 Gbps), 而且 CPU 有 50% 是空閑的,。顯然,真正的挑戰(zhàn)在于 PPS,,而非帶寬,,其他一些測(cè)試也已經(jīng)指出了這一點(diǎn) [46]。 出于這個(gè)原因,,我們用最小包(64 字節(jié))測(cè)試,,衡量指標(biāo)是 PPS。

對(duì)于 XDP 和 Linux 內(nèi)核網(wǎng)絡(luò)棧的測(cè)試,,由于它們沒(méi)有顯式指定某些 CPU 來(lái)處理網(wǎng)絡(luò)包的方式,,因此我們通過(guò)配置硬件 RSS(Receive Side Scaling)來(lái)講流量定向到指定 CPU。

對(duì)網(wǎng)卡,、內(nèi)核的一些配置調(diào)優(yōu),,見(jiàn)代碼倉(cāng)庫(kù) [22]。

4.1 直接棄包(packet drop)性能

圖片

Fig 3. 直接棄包(packet drop)性能,。DPDK 需要預(yù)留一個(gè) CPU 運(yùn)行控制任務(wù),,因此只剩下 5 個(gè) CPU 做包處理。

上圖是性能與 CPU 數(shù)量的關(guān)系,。

  • XDP 基準(zhǔn)性能是 24Mpps/core,,DPDK 是 43.5Mpps/core

  • 二者在分別達(dá)到各自的峰值之前,,PPS 都是隨 CPU 數(shù)量線性增長(zhǎng)的,。

  • 最終全局性能受限于 PCI 總線,啟用 PCI descriptor compression(在 CPU cycles 和 PCI 總線帶寬之間取舍)之后,,能達(dá)到 115Mpps,。

再看圖中 Linux 網(wǎng)絡(luò)棧在兩種配置下的性能:

  1. 通過(guò) iptables 的 raw table丟棄流量,這是 Linux 網(wǎng)絡(luò)棧中最早能丟棄包的地方,;

  2. 通過(guò) conntrack(連接跟蹤)模塊,,這個(gè)模塊的開(kāi)銷非常大,但在很多 Linux 發(fā)行版中都是默認(rèn)開(kāi)啟的,。

conntrack 模式達(dá)到了 1.8Mpps/core,,raw 模式是 4.8Mpps/core ;這兩種模式均未達(dá)到硬件瓶頸,。 最終的性能,,XDP 比常規(guī)網(wǎng)絡(luò)棧的最快方式快了 5 倍

Linux raw mode test 中,,我們還測(cè)量了 XDP 程序不丟棄包,,而是更新包數(shù)統(tǒng)計(jì)然后將包 送到內(nèi)核網(wǎng)絡(luò)棧的場(chǎng)景,。 這種情況下,XDP單核的處理性能會(huì)下降到 4.5Mpps/core,,有 13.3ns 處理延遲,。 圖中并未給出這個(gè)測(cè)試結(jié)果,因?yàn)檫@個(gè)開(kāi)銷太小了,。

4.2 CPU Usage

圖片

Fig 4. 直接棄包(packet drop)場(chǎng)景下的 CPU 利用率,。

用系統(tǒng)提供的 mpstat命令測(cè)量 CPU 利用率。結(jié)果如圖 4 ,。

  • DPDK 是 busy poll 模式,,因此 CPU 永遠(yuǎn)是 100%。

  • XDP 和 Linux 內(nèi)核網(wǎng)絡(luò)棧都是隨流量平滑增長(zhǎng):前面一小段是非線性的,,后面基本是線性的,。

    前面非線性主要是硬中斷帶來(lái)的固定開(kāi)銷,在流量很小時(shí)這一部分占比較大,。

4.3 包轉(zhuǎn)發(fā)性能

這個(gè)測(cè)試中,,轉(zhuǎn)發(fā)應(yīng)用執(zhí)行非常簡(jiǎn)單的 MAC 地址重寫(xiě):直接交換源和目的 MAC 地址,然后轉(zhuǎn)發(fā),。 這是轉(zhuǎn)發(fā)場(chǎng)景下最精簡(jiǎn)的步驟了,,因此結(jié)果代表了所有真實(shí)轉(zhuǎn)發(fā)應(yīng)用的性能上限。

  • 圖中包括了同網(wǎng)卡轉(zhuǎn)發(fā)和不同網(wǎng)卡轉(zhuǎn)發(fā)(XDP程序返回碼不同)的結(jié)果,。

  • DPDK 示例程序只支持通過(guò)另一個(gè)網(wǎng)卡轉(zhuǎn)發(fā),,因此這里只列出了這種情況下的性能。

  • Linux 網(wǎng)絡(luò)棧不支持這種極簡(jiǎn)轉(zhuǎn)發(fā)模式(minimal forwarding mode),,需要設(shè)置完整的 橋接或路由查找(bridging or routing lookup)才能轉(zhuǎn)發(fā)包,;路由查找是非常耗時(shí)的 ,由于其他幾種應(yīng)用并沒(méi)有這一步,,因此結(jié)果直接對(duì)比是沒(méi)意義的,。因此這里略去了 Linux 網(wǎng)絡(luò)棧的結(jié)果。

轉(zhuǎn)發(fā)吞吐(pps)

圖片

Fig 5. 轉(zhuǎn)發(fā)性能,。在同一網(wǎng)卡接口上收發(fā)會(huì)占用同一 PCI port 的帶寬,, 這意味著在 70Mpps XDP same-nic 組就已經(jīng)達(dá)到了 PCI 總線的瓶頸

如圖 5 所示,性能隨 CPU 數(shù)量線性擴(kuò)展,,直到達(dá)到全局性能瓶頸,。XDP 在同網(wǎng)卡轉(zhuǎn)發(fā)的性能遠(yuǎn)高于 DPDK 異網(wǎng)卡性能,原因是內(nèi)存處理方式不同

  • packet buffer 是設(shè)備驅(qū)動(dòng)分配的,,與接收接口(receiving interface)相關(guān)聯(lián),。

  • 因此,異網(wǎng)卡場(chǎng)景下,,當(dāng)包轉(zhuǎn)發(fā)到另一個(gè)接口時(shí),,memory buffer 需要還給與之關(guān)聯(lián)的接口。

轉(zhuǎn)發(fā)延遲

圖片

表 1. 轉(zhuǎn)發(fā)延遲,。機(jī)器網(wǎng)卡的兩個(gè)接口直連,,在轉(zhuǎn)發(fā)速率分別為 100pps 和 1Mpps 的條件下,持續(xù) 50s 測(cè)量端到端延遲

高 pps 場(chǎng)景下,,XDP 的延遲已經(jīng)接近 DPDK,。但在低 pps 場(chǎng)景下,XDP 延遲比 DPDK 大的多,,原因是 XDP 是基于中斷的,,中斷處理時(shí)間( interrupt processing time)此時(shí)占大頭;而 DPDK 是輪詢模式,,延遲相對(duì)比較固定,。

4.4 討論:XDP 性能與 DPDK 還有差距的原因

XDP 未做底層代碼優(yōu)化

上一節(jié)已經(jīng)看到,XDP 相比于常規(guī) Linux 網(wǎng)絡(luò)棧性能有了顯著提升,。但對(duì)于大部分 XDP 場(chǎng)景來(lái)說(shuō),,性能還是與 DPDK 有差距。我們認(rèn)為,,這是主要是因?yàn)?DPDK 做了相當(dāng)多的底層 代碼優(yōu)化,。舉個(gè)例子來(lái)解釋,考慮 packet drop 例子:

  • XDP 24Mpps/core,,對(duì)應(yīng) 41.6ns/packet

  • DPDK 43.5Mpps,,對(duì)應(yīng) 22.9ns/packet

多出來(lái)的 18.7ns 在我們的 3.6GHz 機(jī)器上對(duì)應(yīng) 67 個(gè)時(shí)鐘周期。因此,,很顯然 每個(gè)很小的優(yōu)化在這里都會(huì)產(chǎn)生很大的影響,。例如,我們測(cè)量出在測(cè)試 機(jī)器上,,每次函數(shù)調(diào)用需要 1.3ns,。mlx5 驅(qū)動(dòng)處理每個(gè)包都有 10 次 函數(shù)調(diào)用,總計(jì)就是 13ns,。

通用目的操作系統(tǒng),,首要目標(biāo):更好的擴(kuò)展和配置,而非極致性能

另外,,在 Linux 這樣的通用目的操作系統(tǒng)中,,某些開(kāi)銷是不可避免的, 因?yàn)樵O(shè)備驅(qū)動(dòng)或子系統(tǒng)的組織方式是為了實(shí)現(xiàn)更好的擴(kuò)展和配置,,而非極致性能,。

但是,我們認(rèn)為有些優(yōu)化還是有必要的。例如,,我們嘗試將內(nèi)核中與測(cè)試網(wǎng)卡無(wú)關(guān)的 DMA 函數(shù)調(diào)用刪掉,, 這樣將前面提到的 10 個(gè)函數(shù)調(diào)用降低到了 6 個(gè),測(cè)試結(jié)果顯示這將單核性能提升到了 29Mpps/core,。 依此推測(cè)的話,,將另外 6 個(gè)函數(shù)調(diào)用也優(yōu)化掉,能將 XDP 的性能提升到 37.6Mpps,。 實(shí)際上我們不可能將 6 個(gè)全部去掉,,但去掉其中幾個(gè),再加上一些其他優(yōu)化,,我 們相信 XDP 和 DPDK 的性能差距將越來(lái)越小,。

其他驅(qū)動(dòng)的測(cè)試結(jié)果也是類似的,例如 i40e driver for 40 Gbps Intel cards,。

基于以上討論,,我們相信未來(lái) XDP 與 DPDK 的性能差距將越來(lái)越小。

另一方面,,考慮到 XDP 在靈活性和與內(nèi)核集成方面的優(yōu)勢(shì),, XDP 已經(jīng)是很多實(shí)際場(chǎng)景中的非常有競(jìng)爭(zhēng)力的方式。下文給出幾個(gè)例子,。

5 真實(shí)場(chǎng)景使用案例

本節(jié)給出三個(gè)例子來(lái)具體展示 XDP 在真實(shí)世界中的應(yīng)用,。 這幾個(gè)案例都是已經(jīng)真實(shí)在用的,但本文出于解釋目的,,將使用簡(jiǎn)化的版本,。 同時(shí)也建議讀者參考 [38],后者是獨(dú)立的文章,,介紹使用 XDP 解決實(shí)際工作中網(wǎng)絡(luò)服務(wù)所面臨的一些挑戰(zhàn),。

本節(jié)目的是展示真實(shí) XDP 方案的可行性,因此不會(huì)將重點(diǎn)放在與業(yè)界最新的實(shí)現(xiàn)做詳盡性能對(duì)比上,。 我們會(huì)拿常規(guī)的 Linux 內(nèi)核網(wǎng)絡(luò)棧的性能作為 baseline,,來(lái)對(duì)比 XDP 應(yīng)用的性能。

5.1 案例一:軟件路由(software routing)

內(nèi)核數(shù)據(jù)平面 & 控制平面(BIRD/FRR)

Linux 內(nèi)核實(shí)現(xiàn)了一個(gè)功能完整的路由表,,作為數(shù)據(jù)平面,,支持

  • policy routing

  • source-specific routing

  • multipath load balancing, and more.

對(duì)于控制平面,Bird [10] 或 FRR [17] 這樣的路由守護(hù)進(jìn)程( routing daemons)實(shí)現(xiàn)了多種路由控制平面協(xié)議,。Linux 提供的這套生態(tài)系統(tǒng)功能如此豐富 ,,因此再在另一個(gè)包處理框架中重新實(shí)現(xiàn)一套類似的路由棧代價(jià)將非常高, 更實(shí)際的方式是對(duì) Linux 內(nèi)核的數(shù)據(jù)平面進(jìn)行優(yōu)化,。

XDP:直接查詢內(nèi)核路由表并轉(zhuǎn)發(fā)

XDP 非常適合做這件事情,,尤其是它提供了一個(gè) helper 函數(shù),,能從 XDP 程序中直接查詢內(nèi)核路由表

  • 如果查詢成功,,會(huì)egress interface 和下一跳 MAC 地址,, XDP 程序利用這些信息足夠?qū)⒓崔D(zhuǎn)發(fā)出去

  • 如果下一跳 MAC 還是未知的(因?yàn)橹斑€沒(méi)進(jìn)行過(guò) neighbour lookup),,XDP 程序就 能將包傳給內(nèi)核網(wǎng)絡(luò)棧,,后者會(huì)解析 neighbor 地址,,這樣隨后的包 就能直接被 XDP 程序轉(zhuǎn)發(fā)了,。

測(cè)試:XDP routing 全球 BGP 路由表

為展示 XDP 路由的性能,我們用 Linux 內(nèi)核代碼中的 XDP routing 例子 [1],,與常規(guī) Linux 內(nèi)核網(wǎng)絡(luò)棧的性能做對(duì)比,。 兩組測(cè)試:

  1. 路由表中只有一條路由;

  2. 路由表中有從 routeviews.org 中 dump 而來(lái)的全球 BGP 路由表(global BGP routing table),。 包含 752,138 條路由,。隨機(jī)生成 4000 個(gè)目的 IP 地址,以確保能充分利用到這種路由表,。

    如果目的 IP 地址少于 4000 個(gè),,實(shí)際用到的路由表部分會(huì)較小,能夠保存在 CPU 緩存中,,使得結(jié)果不準(zhǔn)確,。 增大 IP 數(shù)量至 4000 個(gè)以上,不會(huì)對(duì)轉(zhuǎn)發(fā)性能造成影響,,但可以避免緩存導(dǎo)致的結(jié)果不準(zhǔn)問(wèn)題,。

對(duì)于兩組測(cè)試,下一跳 MAC 地址都是與我們的發(fā)送網(wǎng)卡直接相關(guān)的接口的地址,。

性能:2.5x

圖片

Fig 6. 軟件路由的性能,。由于性能隨核數(shù)線性增加,這里只給出單核的結(jié)果,。

測(cè)試結(jié)果如上圖所示,。

  • full table lookup 性能提升了 2.5 倍;

  • smaller routing table 組,,提升了 3 倍,。

這說(shuō)明,XDP 路由程序 單核 10Gbps 網(wǎng)卡的軟硬件配置,,就能 處理整張全球 BGP 路由表(保守估計(jì)每個(gè)包平均 300 字節(jié)),。

5.2 案例二:Inline DoS Mitigation

DoS 攻擊還是像瘟疫一樣糾纏著互聯(lián)網(wǎng),現(xiàn)在通常的方式是:通過(guò)已經(jīng)入侵的大量設(shè)備發(fā)起分布式(DDoS)攻擊,。

有了XDP 之后,,我們能直接在應(yīng)用服務(wù)器(application servers)上 部署包過(guò)濾程序來(lái)防御此類攻(inline DoS mitigation), 無(wú)需修改應(yīng)用代碼。如果應(yīng)用是部署在虛擬機(jī)里,,那 XDP 程序還可以 部署在宿主機(jī)(hypervisor)上,,這樣單個(gè)程序就能保護(hù)機(jī)器上所有的虛擬機(jī)。

模擬 Cloudflare 防御架構(gòu)

為展示工作原理,,我們用 XDP 作為過(guò)濾機(jī)制,,模擬 Cloudflare 的 DDoS 防御架構(gòu)[6]。 他們的 Gatebot architecture ,,首先在各 PoP 點(diǎn)機(jī)器上采樣,,然后統(tǒng)一收起來(lái)做分析, 根據(jù)分析結(jié)果生成防御規(guī)則,。

防御規(guī)則的形式是對(duì)包數(shù)據(jù)(payload)進(jìn)行一系列簡(jiǎn)單檢查,, 能直接編譯成 eBPF 代碼然后分發(fā)到 PoP 點(diǎn)的所有服務(wù)器上。這里說(shuō)的代碼是 XDP 程序 ,,它會(huì)將匹配到規(guī)則的所有流量丟棄,,同時(shí)將統(tǒng)計(jì)信息更新到 BPF map。

程序邏輯

為驗(yàn)證這種方案的性能,,我們編寫(xiě)一個(gè) XDP 程序,,它

  1. 解析包頭,執(zhí)行一些簡(jiǎn)單驗(yàn)證,。對(duì)每個(gè)包:執(zhí)行四次讀取操作,,以解析外層包頭。

  2. 將符合攻擊特性的流量丟棄,。具體:丟棄 UDP 特定端口的流量,。

  3. 將其他流量通過(guò) CPU redirect 方式重定向給另一個(gè) CPU做進(jìn)一步處理;

性能

我們用 netperf 做性能壓測(cè) [26],。

  • 用 netperf TCP round-trip benchmark,,單個(gè) TCP 連接來(lái)回小的 request/reply,統(tǒng)計(jì) transactions/second,。

    模擬的是互式應(yīng)用,,例如小的遠(yuǎn)程過(guò)程調(diào)用(RPC)。

  • 實(shí)驗(yàn)在單核上進(jìn)行,,模擬多個(gè)流量(正常流量 攻擊流量)競(jìng)爭(zhēng)同一物理資源的場(chǎng)景,。

  • 在 beseline 35K 業(yè)務(wù) TPS(transactions per second)基礎(chǔ)上,打少量 UDP 流量作為攻擊流量,。逐漸加大攻擊流量,,觀察 TPS 的變化。

圖片

Fig 7. DDoS 性能,。業(yè)務(wù)吞吐(TPS)隨攻擊流量的變化,。

結(jié)果如上圖所示,,

  • 沒(méi)有 XDP 的一組,性能急劇下降:攻擊流量在 3Mpps 時(shí)性能減半,,3.5Mpps 時(shí)基本跌零,;

  • 有 XDP 程序的一組,攻擊流量達(dá)到 19.5Mpps 之前,,業(yè)務(wù)吞吐保持在 28.5K TPS 以上,,過(guò)了這個(gè)臨界點(diǎn)性能才開(kāi)始急劇下降。

以上結(jié)果表明,,XDP 防御 DDoS 攻擊在實(shí)際中是完全可行的,,單核就能輕松處理 10Gbps 的、都是最小包(minimum-packet)的 DoS 流量,。 這種 DDoS 防御的部署更加靈活,,無(wú)需硬件或應(yīng)用做任何改動(dòng)。

5.3 案例三:負(fù)載均衡(load balancing)

Facebook Katran

負(fù)載均衡的場(chǎng)景,,我們用 Facebook 開(kāi)源的 Katran 作為例子 [15]。Katran 的工作原理是對(duì)外通告服務(wù)的 IP,,這樣目標(biāo)是這個(gè) IP 的流量就會(huì)被路由到 XDP 實(shí)現(xiàn)的負(fù)載均衡器,。

  • 負(fù)載均衡器對(duì)包頭(source packet header)進(jìn)行哈希,以此選擇目標(biāo)應(yīng)用服務(wù)器,。

  • 然后將對(duì)包進(jìn)行封裝(encap),,發(fā)送給應(yīng)用服務(wù)器;

  • 應(yīng)用服務(wù)器解封裝(decap),,處理請(qǐng)求,,然后直接將回包發(fā)給客戶端(DSR 模式)。

在這個(gè)過(guò)程中,,XDP 程序負(fù)責(zé)哈希,、封裝以及將包從接收網(wǎng)卡再發(fā)出去的任務(wù)。 配置信息存儲(chǔ)在 BPF map 中,,整個(gè)封裝邏輯是完全在 eBPF 中實(shí)現(xiàn)的,。

性能

為測(cè)試性能,我們給 Katran XDP 程序配置幾個(gè)固定的目標(biāo)機(jī)器,。 對(duì)照組是 IPVS,,它是 Linux 內(nèi)核的一部分。性能如表 2 所示,,隨 CPU 數(shù)量線性增長(zhǎng),, XDP 比 IPVS 性能高 4.3 倍。

表 2. 負(fù)載均衡器性能(Mpps)

圖片

配置:1 VIP/core, 100 DstIPs/VIP.

6 XDP 的未來(lái)方向

XDP已經(jīng)能用于解決真實(shí)問(wèn)題,,但作為L(zhǎng)inux內(nèi)核的一部分,,XDP 還在快速開(kāi)發(fā)過(guò)程中,。

6.1 eBPF 程序的限制

前面提到,加載到 eBPF 虛擬機(jī)的程序必須保證其安全性(不會(huì)破壞內(nèi)核),,因此對(duì) eBPF 程序作了一下限制,,歸結(jié)為兩方面:

  1. 確保程序會(huì)終止:在實(shí)現(xiàn)上是通過(guò)禁止循環(huán)和限制程序的最大指令數(shù)(max size of the program);

  2. 確保內(nèi)存訪問(wèn)的安全:通過(guò) 3.4 小結(jié)介紹的寄存器狀態(tài)跟蹤(register state tracking)來(lái)實(shí)現(xiàn),。

校驗(yàn)邏輯偏保守

由于校驗(yàn)器的首要職責(zé)是保證內(nèi)核的安全,,因此其校驗(yàn)邏輯比較保守, 凡是它不能證明為安全的,,一律都拒絕,。有時(shí)這會(huì)導(dǎo)致假陰性(false negatives), 即某些實(shí)際上是安全的程序被拒絕加載,;這方面在持續(xù)改進(jìn),。

  • 校驗(yàn)器的錯(cuò)誤提示也已經(jīng)更加友好,以幫助開(kāi)發(fā)者更快定位問(wèn)題,。

  • 近期已經(jīng)支持了 BPF 函數(shù)調(diào)用(function calls),。

  • 正在計(jì)劃支持有限循環(huán)(bounded loops)。

  • 正在提升校驗(yàn)器效率,,以便處理更大的 BPF 程序,。

缺少標(biāo)準(zhǔn)庫(kù)

相比于用戶空間 C 程序,eBPF 程序的另一個(gè)限制是缺少標(biāo)準(zhǔn)庫(kù),,包括 內(nèi)存分配,、線程、鎖等等庫(kù),。

  1. 內(nèi)核的生命周期和執(zhí)行上下文管理(life cycle and execution context management )部分地彌補(bǔ)了這一不足,,(例如,加載的 XDP 程序會(huì)為每個(gè)收到的包執(zhí)行),,

  2. 內(nèi)核提供的 helper 函數(shù)也部分地彌補(bǔ)了一不足,。

一個(gè)網(wǎng)卡接口只能 attach 一個(gè) XDP 程序

這個(gè)限制其實(shí)也是可以繞過(guò)的:將 XDP 程序組織成程序數(shù)組,通過(guò)尾 調(diào)用,,根據(jù)包上下文在程序之間跳轉(zhuǎn),,或者是將幾個(gè)程序做 chaining。

6.2 用戶體驗(yàn)和調(diào)試

XDP 程序運(yùn)行在內(nèi)核,,因此常規(guī)的用戶空間 debug 工具是用不了的,,但內(nèi)核自帶的 debug 和 introspection 功能是可以用在 XDP (及其他 eBPF 程序)上的。 包括:

  • tracepoints and kprobes [13]

  • performance counters that are part of the perf subsystem [42]

但不熟悉內(nèi)核生態(tài)系統(tǒng)的開(kāi)發(fā)者可能會(huì)對(duì)這些工具感到非常陌生,,難以使用,。因此,也出 現(xiàn)了一些更方便普通開(kāi)發(fā)者的工具,,包括 BCC [50],、bpftool [8],、libbpf 函數(shù)庫(kù) [30] 等等。

6.3 驅(qū)動(dòng)支持

設(shè)備要支持 XDP,,需要實(shí)現(xiàn)內(nèi)核核心網(wǎng)絡(luò)棧暴露出的一個(gè) API,。 寫(xiě)作本文時(shí) Linux 4.18 已經(jīng)有 12 種驅(qū)動(dòng)支持 XDP,包括了大部分高速網(wǎng)卡,。 最新列表見(jiàn) [2],。

隨著 XDP 系統(tǒng)的不斷成熟,核心代碼逐漸上移到內(nèi)核中,,驅(qū)動(dòng)需要維護(hù)的代碼越 來(lái)越少,。例如,redirection action 支持新的 target 時(shí),,無(wú)需驅(qū)動(dòng)做任何改動(dòng),。

最后,對(duì)于那些不支持 XDP 的驅(qū)動(dòng),,內(nèi)核提供了 Generic XDPfeature [39],,這是軟件實(shí)現(xiàn)的 XDP,性能會(huì)低一些,, 在實(shí)現(xiàn)上就是將 XDP 的執(zhí)行上移到了核心網(wǎng)絡(luò)棧(core networking stack),。

XDP 在內(nèi)核收包函數(shù) receive_skb() 之前

圖片

Generic XDP在 receive_skb() 之后,,

圖片

更多關(guān)于 Generic XDP,可參考參考:容器網(wǎng)絡(luò)|深入理解Cilium

6.4 性能提升

XDP 和 DPDK 之間還有一些性能差距,,一些改進(jìn)工作正在進(jìn)行中:

  • 驅(qū)動(dòng)代碼 micro-optimisations

  • 刪除核心 XDP 代碼中的非必要操作

  • 通過(guò)批處理平攤處理開(kāi)銷

6.5 QoS 和 Rate Transitions

當(dāng)前,,XDP 還沒(méi)有任何 QoS 機(jī)制。 尤其是,,如果對(duì)端已經(jīng)過(guò)載(例如兩端的網(wǎng)絡(luò)速度或特性不匹配),,XDP 程序是收不到任何背壓(back-pressure)的,

雖然 XDP 中缺少 QoS,,但 Linux 內(nèi)核網(wǎng)絡(luò)棧中卻有很多業(yè)界最佳的 Active Queue Management (AQM) 特性和 packet scheduling algorithms [23],。 這些特性中,部分并不適用于 XDP,,但我們相信能夠 以一種對(duì)包處理應(yīng)用完全透明的方式,,選擇其中部分集成到 XDP。 我們計(jì)劃對(duì)這一方向進(jìn)行更深入研究,。

6.6 加速傳輸層協(xié)議

我們已經(jīng)證明 XDP 能在保留操作系統(tǒng)原有功能的前提下,,集成到操作系統(tǒng)中,實(shí)現(xiàn)高速包數(shù)據(jù),。

目前的 XDP 還是用于無(wú)狀態(tài)包處理(stateless packet processing) ,,如果將這個(gè)模型擴(kuò)展到有狀態(tài)傳輸層協(xié)議(stateful transport protocols),,例如 TCP,它能給依賴可靠/有狀態(tài)傳輸?shù)膽?yīng)用提供類似的性能提升,。

實(shí)際上,,已經(jīng)有一些研究證明,相比于操作系統(tǒng)的協(xié)議棧,,accelerated transport protocols 能顯著提升性能[5, 25, 35, 52],。其中的一個(gè)解決方案 [52] 表明,在保留內(nèi) 核 TCP 協(xié)議棧的的前提下,,原始包處理性能(raw packet processing)存在巨大的提升 空間,。

XDP 非常適用于這種場(chǎng)景,目前也已經(jīng)有一些關(guān)于如何實(shí)現(xiàn)的初步討論 [21],, 雖然離實(shí)際使用還很遠(yuǎn),,但仍然是一個(gè)令人振奮的、擴(kuò)展 XDP 系統(tǒng) scope 的方向,。

6.7 內(nèi)核-用戶空間零拷貝(zero-copy to userspace)

3.1 小節(jié)提到,,XDP 程序能將數(shù)據(jù)包重定向到用戶空間應(yīng)用(userspace application)打 開(kāi)的特殊類型 socket。這可以用于加速客戶端和服務(wù)端在同一臺(tái)機(jī)器的網(wǎng)絡(luò)密集型應(yīng)用(network-heavy applications running on the local machine),。

更多信息可參考: (譯) 利用 ebpf sockmap/redirection 提升 socket 性能(2020),。 這里使用的是 BPF 而非 XDP,但核心原理是一樣的,,只是程序執(zhí)行的位置(hook)不同,。 譯注。

但在目前的實(shí)現(xiàn)中,,這種方式在底層仍然需要拷貝包數(shù)據(jù),,因此性能會(huì)打折扣。

目前已經(jīng)有工作在進(jìn)行,,通過(guò) AF_XDP 實(shí)現(xiàn)真正的數(shù)據(jù)零拷貝,。但這項(xiàng)工作需要 對(duì)網(wǎng)絡(luò)設(shè)備的內(nèi)存處理過(guò)程有一些限制,因此需要設(shè)備驅(qū)動(dòng)的顯式支持,。 第一個(gè)支持這個(gè)功能的 patch 已經(jīng)合并到 4.19內(nèi)核,,更多驅(qū)動(dòng)的支持 正在添加中。初步的性能測(cè)試結(jié)果還是很樂(lè)觀的,,顯示能達(dá)到 20Mpps/core 的內(nèi)核到用戶 空間傳遞(transfer)速度,。

6.8 XDP 作為基礎(chǔ)構(gòu)建模塊(XDP as a building block)

正如 DPDK 用于高層包處理框架的底層構(gòu)建模塊(例如 [31]),XDP 有望成為高層應(yīng)用的運(yùn)行時(shí)環(huán)境 (runtime environment for higher-level applications),。

實(shí)際上,,我們看到一些基于 XDP 的應(yīng)用和框架已經(jīng)出現(xiàn)了。包括

  • Cilium security middle-ware [3]

  • Suricata network monitor [4]

  • Open vSwitch [49]

  • P4-to-XDP compiler project [51]

甚至還有人嘗試將 XDP 作為 DPDK 的一種底層驅(qū)動(dòng) [53],。

7 總結(jié)

本文描述了 XDP,,一個(gè)安全,、快速、可編程,、集成到操作系統(tǒng)內(nèi)核的包處理框架,。 測(cè)試結(jié)果顯示,XDP 能提供 24Mpps/core 的高處理性能,,這一數(shù)字雖然與基于 kernel bypass 的 DPDK 仍有差距,,但提供了其他一些非常有競(jìng)爭(zhēng)力的優(yōu)勢(shì):

  1. 兼容內(nèi)核安全和管理框架(kernel bypass 方式在 bypass 內(nèi)核網(wǎng)絡(luò)棧的同時(shí),也將安全和設(shè)備管理等這些極其重要的基礎(chǔ)設(shè)施 bypass 了),;

  2. 兼容內(nèi)核網(wǎng)絡(luò)棧,,可選擇性利用內(nèi)核已有的基礎(chǔ)設(shè)施和功能;

  3. 提供與內(nèi)核 API 一樣穩(wěn)定的編程接口,;

  4. 對(duì)應(yīng)用完全透明,;

  5. 更新、替換程序的過(guò)程不會(huì)引起服務(wù)中斷,;

  6. 無(wú)需專門(mén)硬件,,無(wú)需獨(dú)占 CPU 等資源。

相比于 kernel bypass 這種非此即彼,、完全繞開(kāi)內(nèi)核的方式,,我們相信 XDP 有更廣闊的的應(yīng)用前景。Facebook,、Cloudflare 等公司實(shí)際落地的 XDP 應(yīng)用,,更加增強(qiáng)了我們的這種信心。

最后,,XDP系統(tǒng)還在快速發(fā)展,,前面也列出了一些正在未來(lái)可能會(huì)做的開(kāi)發(fā)/優(yōu)化工作。

致謝

XDP has been developed by the Linux networking community for a number of years, and the authors would like to thank everyone who has been involved. In particular,

  • Alexei Starovoitov has been instrumental in the development of the eBPF VM and verifier;

  • Jakub Kicinski has been a driving force behind XDP hardware offloading and the bpftool utility;

  • Bj?rn T?pel and Magnus Karlsson have been leading the AF_XDP and userspace zero-copy efforts.

We also wish to extend our thanks to the anonymous reviewers, and to our shepherd Srinivas Narayana, for their helpful comments.

參考文獻(xiàn)

https:///blog/xdp-paper-acm-2018-zh/

- END -


看完一鍵三連在看,,轉(zhuǎn)發(fā),,點(diǎn)贊

是對(duì)文章最大的贊賞,極客重生感謝你圖片


推薦閱讀


圖片

深入理解Linux內(nèi)核之內(nèi)存尋址


圖片

2022新年重磅技術(shù)分享|深入理解Linux操作系統(tǒng)


圖片

一些優(yōu)秀的后端開(kāi)源項(xiàng)目!


你好,,這里是極客重生,,我是阿榮,,大家都叫我榮哥,,從華為->外企->到互聯(lián)網(wǎng)大廠,,目前是大廠資深工程師,多次獲得五星員工,,多年職場(chǎng)經(jīng)驗(yàn),,技術(shù)扎實(shí),專業(yè)后端開(kāi)發(fā)和后臺(tái)架構(gòu)設(shè)計(jì),,熱愛(ài)底層技術(shù),,豐富的實(shí)戰(zhàn)經(jīng)驗(yàn),分享技術(shù)的本質(zhì)原理,,希望幫助更多人蛻變重生,,拿BAT大廠offer,培養(yǎng)高級(jí)工程師能力,,成為技術(shù)專家,,實(shí)現(xiàn)高薪夢(mèng)想,期待你的關(guān)注,!點(diǎn)擊藍(lán)字查看我的成長(zhǎng)之路,。

校招/社招/簡(jiǎn)歷/面試技巧/大廠技術(shù)棧分析/后端開(kāi)發(fā)進(jìn)階/優(yōu)秀開(kāi)源項(xiàng)目/直播分享/技術(shù)視野/實(shí)戰(zhàn)高手等, 極客星球希望成為最有技術(shù)價(jià)值星球,盡最大努力為星球的同學(xué)提供技術(shù)和成長(zhǎng)幫助,!詳情查看->極客星球

求點(diǎn)贊,,在看,分享三連圖片

的昂貴性能開(kāi)銷。

但是,,操作系統(tǒng)被旁路(繞過(guò))之后,,它的應(yīng)用隔離(application isolation) 和安全機(jī)制(security mechanisms)就都失效了;一起失效的還有各種經(jīng)過(guò)已經(jīng) 充分測(cè)試的配置,、部署和管理工具,。

為解決這個(gè)問(wèn)題,我們提出一種新的可編程包處理方式:eXpress Data Path (XDP),。

  • XDP 提供了一個(gè)仍然基于操作系統(tǒng)內(nèi)核的安全執(zhí)行環(huán)境,,在設(shè)備驅(qū)動(dòng)上下文(device driver context)中執(zhí)行,可用于定制各種包處理應(yīng)用,。

  • XDP 是主線內(nèi)核(mainline Linux kernel)的一部分,,與現(xiàn)有的內(nèi)核 網(wǎng)絡(luò)棧(kernel’s networking stack)完全兼容,二者協(xié)同工作,。

  • XDP 應(yīng)用(application)通過(guò) C 等高層語(yǔ)言編寫(xiě),,然后編譯成特定字節(jié)碼;出于安 全考慮,,內(nèi)核會(huì)首先對(duì)這些字節(jié)碼執(zhí)行靜態(tài)分析,,然后再將它們翻譯成 處理器原生指令(native instructions)。

  • 測(cè)試結(jié)果顯示,,XDP 能達(dá)到 24Mpps/core的處理性能,。

為展示 XDP 靈活的編程模型,本文還將給出三個(gè)程序示例,,

  1. layer-3 routing(三層路由轉(zhuǎn)發(fā)

  2. inline DDoS protection(DDoS 防護(hù)

  3. layer-4 load balancing(四層負(fù)載均衡

1 引言

軟件實(shí)現(xiàn)高性能包處理的場(chǎng)景,,對(duì)每個(gè)包的處理耗時(shí)有著極高的要求。通用目的操作系統(tǒng)中 的網(wǎng)絡(luò)棧更多是針對(duì)靈活性的優(yōu)化,,這意味著它們花在每個(gè)包上 的指令太多了,,不適合網(wǎng)絡(luò)高吞吐的場(chǎng)景。

因此,,隨后出現(xiàn)了一些專門(mén)用于包處理的軟件開(kāi)發(fā)工具,,例如 Data Plane Development Kit (DPDK) [16]。這些工具一般都會(huì)完全繞過(guò)內(nèi)核,,將網(wǎng)絡(luò)硬件直接交 給用戶態(tài)的網(wǎng)絡(luò)應(yīng)用,,并需要獨(dú)占一個(gè)或多個(gè) CPU

1.1 現(xiàn)有方案(kernel bypass)存在的問(wèn)題

內(nèi)核旁路方式可以顯著提升性能,,但缺點(diǎn)也很明顯:

  • 很難與現(xiàn)有系統(tǒng)集成

  • 上層應(yīng)用必須要將內(nèi)核中已經(jīng)非常成熟的模塊在用戶態(tài)重新實(shí)現(xiàn)一遍,,例如路由表,、高層協(xié)議棧等;

  • 最壞的情況下,這種包處理應(yīng)用只能工作在一個(gè)完全隔絕的環(huán)境,,因?yàn)閮?nèi)核提供的常見(jiàn)工具和部署方式在這種情況下都不可用了,。

  • 導(dǎo)致系統(tǒng)越來(lái)越復(fù)雜,而且破壞了操作系統(tǒng)內(nèi)核在把控的安全邊界,。 在基礎(chǔ)設(shè)施逐漸遷移到 Kubernetes/Docker 等容器環(huán)境的背景下,,這一點(diǎn)顯得尤其嚴(yán)重, 因?yàn)樵谶@種場(chǎng)景下,,內(nèi)核擔(dān)負(fù)著資源抽象和隔離的重任,。

1.2 新方案:給內(nèi)核網(wǎng)絡(luò)棧添加可編程能力

對(duì)此,本文提供了另一種解決方案:給內(nèi)核網(wǎng)絡(luò)棧添加可編程能力,。這使得我們能在 兼容各種現(xiàn)有系統(tǒng),、復(fù)用已有網(wǎng)絡(luò)基礎(chǔ)設(shè)施的前提下,仍然實(shí)現(xiàn)高速包處理,。 這個(gè)框架稱為XDP,,

  • XDP定義了一個(gè)受限的執(zhí)行環(huán)境(a limited execution environment),運(yùn)行在一個(gè) eBPF 指令虛擬機(jī)中,。eBPF 是 BSD Packet Filter (BPF) [37] 的擴(kuò)展,。

  • XDP 程序運(yùn)行在內(nèi)核上下文中,此時(shí)內(nèi)核自身都還沒(méi)有接觸到包數(shù)據(jù)( before the kernel itself touches the packet data),,這使得我們能在網(wǎng)卡收到包后 最早能處理包的位置,,做一些自定義數(shù)據(jù)包處理(包括重定向)。

  • 內(nèi)核在加載(load)時(shí)執(zhí)行靜態(tài)校驗(yàn),,以確保用戶提供的 XDP 程序的安全,。

  • 之后,程序會(huì)被動(dòng)態(tài)編譯成原生機(jī)器指令(native machine instructions),,以獲得高性能,。

XDP已經(jīng)在過(guò)去的幾個(gè)內(nèi)核 release 中逐漸合并到內(nèi)核,但在本文之前,,還沒(méi)有關(guān)于 XDP 系統(tǒng)的 完整架構(gòu)介紹,。本文將對(duì) XDP 做一個(gè)高層介紹。

1.3 新方案(XDP)的優(yōu)點(diǎn)

我們的測(cè)試結(jié)果顯示 XDP 能取得 24Mpps/core的處理性能,,這雖然與 DPDK 還有差距,, 但相比于后者這種 kernel bypass 的方式,XDP 有非常多的優(yōu)勢(shì),。

本文是 2018 年的測(cè)試結(jié)果,,更新的一些性能(及場(chǎng)景)對(duì)比可參考 (譯) 為容器時(shí)代設(shè)計(jì)的高級(jí) eBPF 內(nèi)核特性(FOSDEM, 2021)。 譯注,。

具體地,,XDP

  1. 與內(nèi)核網(wǎng)絡(luò)棧協(xié)同工作,,將硬件的控制權(quán)完全留在內(nèi)核范圍內(nèi)。帶來(lái)的好處:

    • 保持了內(nèi)核的安全邊界

    • 無(wú)需對(duì)網(wǎng)絡(luò)配置或管理工具做任何修改

  2. 無(wú)需任何特殊硬件特性,,任何有 Linux 驅(qū)動(dòng)的網(wǎng)卡都可以支持,, 現(xiàn)有的驅(qū)動(dòng)只需做一些修改,就能支持 XDP hooks,。

  3. 可以選擇性地復(fù)用內(nèi)核網(wǎng)絡(luò)棧中的現(xiàn)有功能,,例如路由表或 TCP/IP 協(xié)議棧,在保持配置接口不變的前提下,,加速關(guān)鍵性能路徑(critical performance paths),。

  4. 保證 eBPF 指令集和 XDP 相關(guān)的編程接口(API)的穩(wěn)定性。

  5. 與常規(guī) socket 層交互時(shí),,沒(méi)有從用戶態(tài)將包重新注入內(nèi)核的昂貴開(kāi)銷,。

  6. 對(duì)應(yīng)用透明。這創(chuàng)造了一些新的部署場(chǎng)景/方式,,例如直接在應(yīng)用所 在的服務(wù)器上部署 DoS 防御(而非中心式/網(wǎng)關(guān)式 DoS 防御),。

  7. 服務(wù)不中斷的前提下動(dòng)態(tài)重新編程(dynamically re-program), 這意味著可以按需加入或移除功能,,而不會(huì)引起任何流量中斷,,也能動(dòng)態(tài)響應(yīng)系統(tǒng)其他部分的的變化。

  8. 無(wú)需預(yù)留專門(mén)的 CPU 做包處理,,這意味著 CPU 功耗與流量高低直接相關(guān),,更節(jié)能。

1.4 本文組織結(jié)構(gòu)

接下來(lái)的內(nèi)容介紹 XDP 的設(shè)計(jì),,并做一些性能分析,。結(jié)構(gòu)組織如下:

  • Section 2介紹相關(guān)工作;

  • Section 3 介紹 XDP 系統(tǒng)的設(shè)計(jì),;

  • Section 4做一些性能分析,;

  • Section 5提供了幾個(gè)真實(shí) XDP 場(chǎng)景的程序例子;

  • Section 6討論 XDP 的未來(lái)發(fā)展方向,;

  • Section 7總結(jié),。

2 相關(guān)工作

XDP 當(dāng)然不是第一個(gè)支持可編程包處理的系統(tǒng) —— 這一領(lǐng)域在過(guò)去幾年發(fā)展勢(shì)頭良好, 并且趨勢(shì)還在持續(xù),。業(yè)內(nèi)已經(jīng)有了幾種可編程包處理框架,,以及基于這些框架的新型應(yīng)用,包括:

  • 單一功能的應(yīng)用,,如 switching [47], routing [19], named-based forwarding [28], classification [48], caching [33] or traffic generation [14],。

  • 更加通用、且高度可定制的包處理解決方案,,能夠處理從多種源收來(lái)的數(shù)據(jù)包 [12, 20, 31, 34, 40, 44],。

要基于通用(Common Off The Shelf,,COTS)硬件實(shí)現(xiàn)高性能包處理,就必須解決 網(wǎng)卡(NIC)和包處理程序之間的所有瓶頸,。由于性能瓶頸主要來(lái)源于內(nèi)核和用戶態(tài)應(yīng)用之 間的接口(系統(tǒng)調(diào)用開(kāi)銷非常大,另外,,內(nèi)核功能豐富,,但也非常復(fù)雜), 低層(low-level)框架必須通過(guò)這樣或那樣的方式來(lái)降低這些開(kāi)銷,。

現(xiàn)有的一些框架通過(guò)幾種不同的方式實(shí)現(xiàn)了高性能,,XDP 構(gòu)建在其中一些技術(shù)之上。 接下來(lái)對(duì) XDP 和它們的異同做一些比較分析,。

2.1 用戶態(tài)輪詢 vs. XDP

  • DPDK[16] 可能是使用最廣泛的高性能包處理框架,。它最初只支持 Intel 網(wǎng)卡,后來(lái)逐 步擴(kuò)展到其他廠商的網(wǎng)卡,。DPDK 也稱作內(nèi)核旁路框架(kernel bypass framework),, 因?yàn)樗鼘⒕W(wǎng)絡(luò)硬件的控制權(quán)從內(nèi)核轉(zhuǎn)移到了用戶態(tài)的網(wǎng)絡(luò)應(yīng)用,完全避免了內(nèi)核-用戶態(tài) 之間的切換開(kāi)銷,。

  • 與DPDK類似的還有PF_RING ZC module [45] 和 hardware-specific Solarflare OpenOnload [24],。

在現(xiàn)有的所有框架中,內(nèi)核旁路方式性能是最高的[18],;但如引言中指 出,,這種方式在管理、維護(hù)和安全方面都存在不足,。

XDP 采用了一種與內(nèi)核旁路截然相反的方式:相比于將網(wǎng)絡(luò)硬件的控制權(quán)上移到用戶空間,, XDP 將性能攸關(guān)的包處理操作直接放在內(nèi)核中,在操作系統(tǒng)的網(wǎng)絡(luò)棧之前執(zhí)行,。

  • 這種方式同樣避免了內(nèi)核-用戶態(tài)切換開(kāi)銷(所有操作都在內(nèi)核),,

  • 但仍然由內(nèi)核來(lái)管理硬件,因此保留了操作系統(tǒng)提供的管理接口和安全防護(hù)能力,。

    這里的主要?jiǎng)?chuàng)新是:使用了一個(gè)虛擬執(zhí)行環(huán)境,,它能對(duì)加載的 程序進(jìn)行校驗(yàn),確保它們不會(huì)對(duì)內(nèi)核造成破壞,。

2.2 內(nèi)核模塊 vs. XDP

在 XDP 之前,,以內(nèi)核模塊(kernel module)方式實(shí)現(xiàn)包處理功能代價(jià)非常高, 因?yàn)槌绦驁?zhí)行出錯(cuò)時(shí)可能會(huì)導(dǎo)致整個(gè)系統(tǒng)崩潰,,而且內(nèi)核的內(nèi)部 API 也會(huì)隨著時(shí)間發(fā)生變化,。 因此也就不難理解為什么只有很少的系統(tǒng)采用了這種方式。其中做的比較好包括

  • 虛擬交換機(jī)Open vSwitch [44]

  • Click [40]

  • 虛擬機(jī)路由器Contrail [41]

這幾個(gè)系統(tǒng)都支持靈活的配置,,適用于多種場(chǎng)景,,取得比較小的平攤代價(jià),。

XDP通過(guò):

  1. 提供一個(gè)安全的執(zhí)行環(huán)境,以及內(nèi)核社區(qū)支持,,提供與那些暴露到用戶空間一樣穩(wěn)定的內(nèi)核 API

    極大地降低了那些將處理過(guò)程下沉到內(nèi)核的應(yīng)用(applications of moving processing into the kernel)的成本,。

  2. 此外,XDP 程序也能夠完全繞過(guò)內(nèi)核網(wǎng)絡(luò)棧(completely bypass),, 與在內(nèi)核網(wǎng)絡(luò)棧中做 hook 的傳統(tǒng)內(nèi)核模塊相比,,性能也更高。

  3. XDP 除了能將處理過(guò)程下沉到內(nèi)核以獲得最高性能之外,,還支持在程序中執(zhí)行重定向(redirection)操作,,完全繞過(guò)內(nèi)核網(wǎng)絡(luò)棧,將包送到特殊類型的用戶空間 socket,; 甚至能工作在 zero-copy 模式,,進(jìn)一步降低開(kāi)銷。

  4. 這種模式與 Netmap [46] 和 PF_RING [11] 方式類似,,但后者是在沒(méi)有完全繞過(guò)內(nèi) 核的情況下,,通過(guò)降低從網(wǎng)絡(luò)設(shè)備到用戶態(tài)應(yīng)用(network device to userspace application)之間的傳輸開(kāi)銷,實(shí)現(xiàn)高性能包處理,。

內(nèi)核模塊方式的另一個(gè)例子是 Packet I/O engine,,這是 PacketShader [19] 的組成部分, 后者專用于 Arrakis [43] and ClickOS [36] 之類的特殊目的操作系統(tǒng),。

2.3 可編程硬件 vs. XDP

可編程硬件設(shè)備也是一種實(shí)現(xiàn)高性能包處理的方式,。

  • 一個(gè)例子是 NetFPGA[32],通過(guò)對(duì)它暴露的 API 進(jìn)行編程,,能夠在這種基于 FPGA 的專 用設(shè)備上運(yùn)行任何包處理任務(wù),。

  • P4 編程語(yǔ)言 [7] 致力于將這種可編程能力擴(kuò)展到更廣泛的包處理硬件上(巧合的是,它還包括了一個(gè) XDP backend [51]),。

某種意義上來(lái)說(shuō),,XDP 可以認(rèn)為是一種 offload方式

  1. 性能敏感的處理邏輯下放到網(wǎng)卡驅(qū)動(dòng)中,以提升性能,;

  2. 其他的處理邏輯仍然走內(nèi)核網(wǎng)絡(luò)棧,;

  3. 如果沒(méi)有用到內(nèi)核 helper 函數(shù),那整個(gè) XDP 程序都可以 offload 到網(wǎng)卡(目前 Netronome smart-NICs [27] 已經(jīng)支持),。

2.4 小結(jié)

XDP 提供了一種高性能包處理方式,,與已有方式相比,在性能,、與現(xiàn)有系統(tǒng)的集成,、靈活性 等方面取得了更好的平衡。接下來(lái)介紹 XDP 是如何取得這種平衡的,。

3 XDP 設(shè)計(jì)

XDP 的設(shè)計(jì)理念:

  • 高性能包處理

  • 集成到操作系統(tǒng)內(nèi)核(kernel)并與之協(xié)同工作,,同時(shí)

  • 確保系統(tǒng)其它部分的安全性(safety)完整性(integrity)

這種與內(nèi)核的深度集成顯然會(huì)給設(shè)計(jì)帶來(lái)一些限制,,在 XDP 組件合并到 Linux 的過(guò)程中,我們也收到了許多來(lái)自社區(qū)的反饋,,促使我們不斷調(diào)整 XDP 的設(shè)計(jì),,但 這些設(shè)計(jì)反思不在本文討論范圍之內(nèi)。

3.0 XDP 系統(tǒng)架構(gòu)

圖 1 描繪了整個(gè) XDP 系統(tǒng),,四個(gè)主要組成部分:

  1. XDP driver hook:XDP 程序的主入口,,在網(wǎng)卡收到包執(zhí)行。

  2. eBPF virtual machine:執(zhí)行 XDP 程序的字節(jié)碼,,以及對(duì)字節(jié)碼執(zhí)行 JIT 以提升性能。

  3. BPF maps:內(nèi)核中的 key/value 存儲(chǔ),,作為圖中各系統(tǒng)的主要通信通道,。

  4. eBPF verifier:加載程序時(shí)對(duì)其執(zhí)行靜態(tài)驗(yàn)證,以確保它們不會(huì)導(dǎo)致內(nèi)核崩潰,。

圖片

Fig 1. XDP 與 Linux 網(wǎng)絡(luò)棧的集成,。這里只畫(huà)了 ingress 路徑,以免圖過(guò)于復(fù)雜,。

上圖是 ingress 流程,。網(wǎng)卡收到包之后,在處理包數(shù)據(jù)(packet data)之前,,會(huì)先執(zhí)行 main XDP hook 中的 eBPF 程序,。 這段程序可以選擇:

  1. 丟棄(drop)這個(gè)包;或者

  2. 通過(guò)當(dāng)前網(wǎng)卡將包再發(fā)送(send)出去,;或者

  3. 將包重定向(redirect)到其他網(wǎng)絡(luò)接口(包括虛擬機(jī)的虛擬網(wǎng)卡),,或者通過(guò) AF_XDP socket 重定向到用戶空間;或者

  4. 放行(allow)這個(gè)包,,如果后面沒(méi)有其他原因?qū)е碌?drop,,這個(gè)包就會(huì)進(jìn)入常規(guī)的內(nèi)核網(wǎng)絡(luò)棧。

    如果是這種情況,,也就是放行包進(jìn)入內(nèi)核網(wǎng)絡(luò)棧,,那接下來(lái)在將包放到發(fā)送隊(duì)列之前(before packets are queued for transmission), 還有一個(gè)能執(zhí)行 BPF 程序的地方:TC BPF hook,。

    更多信息,,可參考 (譯) [論文] 邁向完全可編程 tc 分類器(cls_bpf)(NetdevConf,2016),。 譯注,。

此外,圖 1 中還可以看出,,不同的 eBPF 程序之間,、eBPF 程序和用戶空間應(yīng)用之間,,都能夠通過(guò) BPF maps 進(jìn)行通信

3.1 XDP driver hook

在設(shè)備驅(qū)動(dòng)中執(zhí)行,,無(wú)需上下文切換

XDP 程序在網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)中執(zhí)行,,網(wǎng)絡(luò)設(shè)備每收到一個(gè)包,程序就執(zhí)行一次,。

相關(guān)代碼實(shí)現(xiàn)為一個(gè)內(nèi)核庫(kù)函數(shù)(library function),,因此程序直接 在設(shè)備驅(qū)動(dòng)中執(zhí)行,無(wú)需切換到用戶空間上下文,。

在軟件最早能處理包的位置執(zhí)行,,性能最優(yōu)

回到上面圖 1 可以看到:程序在網(wǎng)卡收到包之后最早能處理包的位置執(zhí)行 —— 此時(shí)內(nèi)核還沒(méi)有為包分配 struct sk_buff 結(jié)構(gòu)體, 也沒(méi)有執(zhí)行任何解析包的操作,。

XDP 程序典型執(zhí)行流

下圖是一個(gè)典型的 XDP 程序執(zhí)行流:

圖片

Fig 2. 典型 XDP 程序的執(zhí)行流,。

網(wǎng)卡收到一個(gè)包時(shí),XDP 程序依次執(zhí)行:

  1. 提取包頭中的信息(例如 IP,、MAC,、Port、Proto 等),,

    執(zhí)行到程序時(shí),,系統(tǒng)會(huì)傳遞給它一個(gè)上下文對(duì)象(context object)作為參賽(即 struct xdp_md *ctx,后面有例子),,其中包括了指向原 始包數(shù)據(jù)的指針,,以及描述這個(gè)包是從哪個(gè)網(wǎng)卡的哪個(gè)接口接收上來(lái)的等元數(shù)據(jù)字段。

  2. 讀取或更新一些資源的元信息(例如更新統(tǒng)計(jì)信息),;

    解析包數(shù)據(jù)之后,,XDP 程序可以讀取 ctx 中的包元數(shù)據(jù)(packet metadata) 字段,例如從哪個(gè)網(wǎng)卡的哪個(gè)接口收上來(lái)的(ifindex),。除此之外,,ctx 對(duì)象還允許 程序訪問(wèn)與包數(shù)據(jù)毗鄰的一塊特殊內(nèi)存區(qū)域(cb, control buffer), 在包穿越整個(gè)系統(tǒng)的過(guò)程中,,可以將自定義的數(shù)據(jù)塞在這里,。

    除了 per-packet metadata,XDP 程序還可以通過(guò) BPF map 定義和訪問(wèn)自己的持久數(shù)據(jù),,以及通過(guò)各種 helper 函數(shù)訪問(wèn)內(nèi)核基礎(chǔ)設(shè)施,。

    • BPF map 使 BPF 程序能與系統(tǒng)的其他部分之間通信;

    • Helpers 使 BPF 程序能利用到某些已有的內(nèi)核功能(例如路由表),, 而無(wú)需穿越整個(gè)內(nèi)核網(wǎng)絡(luò)棧,。

  3. 如果有需要,對(duì)這個(gè)包進(jìn)行 rewrite header操作,

    程序能修改包數(shù)據(jù)的任何部分,,包括添加或刪除包頭,。這使得 XDP 程序能執(zhí)行封裝/接封裝操作,以及重寫(xiě)(rewrite)地址字段然后轉(zhuǎn)發(fā)等操作,。

    內(nèi)核 helper 函數(shù)各有不同用途,,例如修改一個(gè)包之后,計(jì)算新的校驗(yàn)和(checksum),。

  4. 進(jìn)行最后的判決(verdict),,確定接下來(lái)對(duì)這個(gè)包執(zhí)行什么操作;

    判決結(jié)果包括:

    重定向功能的用途

    這些不同的路徑,,在圖 1 對(duì)應(yīng)的是幾條實(shí)線,。

    重定向判決(verdict)與重定向目標(biāo)(target)分開(kāi),使得重定向目標(biāo)類型很容易擴(kuò)展,; 另外,,由于重定向參數(shù)(目標(biāo))是通過(guò) BPF map 查詢的,因此無(wú)需修 改 XDP 程序,,就能動(dòng)態(tài)修改重定向目標(biāo)。

    • 三種簡(jiǎn)單返回碼:丟棄這個(gè)包,、通過(guò)接收時(shí)的網(wǎng)卡將包重新發(fā)送出去,、允許這個(gè)包進(jìn)入內(nèi)核網(wǎng)絡(luò)棧;

    • 第四種返回碼 redirect:允許 XDP 程序指定網(wǎng)卡,、CPU,、用戶態(tài) socket等,將包重定向過(guò)去,。

    1. 將原始包通過(guò)另一個(gè)網(wǎng)卡(包括虛擬機(jī)的虛擬網(wǎng)卡)發(fā)送出去,;

    2. 轉(zhuǎn)發(fā)給指定 CPU做進(jìn)一步處理,;

    3. 轉(zhuǎn)發(fā)給 AF_XDP 類型的 socket做進(jìn)一步處理,;

程序還能通過(guò)尾調(diào)用(tail call),,將控制權(quán)交給另一個(gè) XDP 程序,; 通過(guò)這種方式,,可以將一個(gè)大程序拆分成幾個(gè)邏輯上的小程序(例如,,根據(jù) IPv4/IPv6),。

由于 XDP 程序可包含任意指令,,因此前三步(讀取包數(shù)據(jù),、處理元數(shù)據(jù),、重寫(xiě)包數(shù)據(jù)) 順序可以是任意的,而且支持多層嵌套,。 但實(shí)際中為了獲得高性能,,大部分情況下還是將執(zhí)行結(jié)構(gòu)組織成這順序的三步。

3.2 eBPF 虛擬機(jī)

XDP 程序在 Extended BPF (eBPF) 虛擬機(jī)中執(zhí)行,。eBPF 是早期 BSD packet filter (BPF) [37] 的擴(kuò)展,,后者在過(guò)去的幾十年中廣泛 應(yīng)用于各種包處理工具,。

BPF 使用 基于寄存器的(register-based) virtual machine 來(lái)描述 過(guò)濾動(dòng)作(filtering actions)。

eBPF 虛擬機(jī)支持動(dòng)態(tài)加載(loading)和重加載(re-loading)程序,,內(nèi)核管理所有 BPF 程序的生命周期,。

3.3 BPF maps

eBPF 程序在觸發(fā)內(nèi)核事件時(shí)執(zhí)行(例如,觸發(fā) XDP 程序執(zhí)行的,,是收包事件),。 程序每次執(zhí)行時(shí),初始狀態(tài)都是相同的(即程序是無(wú)狀態(tài)的),,它們無(wú)法直接訪問(wèn)內(nèi)核中的持久存儲(chǔ)(BPF map),。為此,內(nèi)核提供了訪問(wèn) BPF map 的 helper 函數(shù),。

BPF map 是 key/value 存儲(chǔ),,在加載 eBPF 程序時(shí)定義(defined upon loading an eBPF program)。

用途:

  1. 持久存儲(chǔ),。例如一個(gè) eBPF 程序每次執(zhí)行時(shí),,都會(huì)從里面獲取上一次的狀態(tài)。

  2. 用于協(xié)調(diào)兩個(gè)或多個(gè) eBPF 程序,。例如一個(gè)往里面寫(xiě)數(shù)據(jù),,一個(gè)從里面讀數(shù)據(jù)。

  3. 用于用戶態(tài)程序和內(nèi)核 eBPF 程序之間的通信,。

3.4 eBPF verifier

唯一加載入口:bpf()系統(tǒng)調(diào)用

由于 eBPF 代碼直接運(yùn)行在內(nèi)核地址空間,,因此它能直接訪問(wèn) —— 也可 能是破壞 —— 任何內(nèi)存。為防止這種情況發(fā)生,,內(nèi)核規(guī)定只能通過(guò)唯一入口( bpf() 系統(tǒng)調(diào)用)加載 BPF 程序,。

加載 BPF 程序時(shí),位于內(nèi)核中的校驗(yàn)器首先會(huì)對(duì)字節(jié)碼程序進(jìn)行靜態(tài)分析,,以確保

  • 程序中沒(méi)有任何不安全的操作(例如訪問(wèn)任意內(nèi)存),,

  • 程序會(huì)終止(terminate)。通過(guò)下面這兩點(diǎn)來(lái)實(shí)現(xiàn):

    • 禁止循環(huán)操作

    • 限制程序最大指令數(shù)

校驗(yàn)器工作原理:two-pass DAG

校驗(yàn)器的工作原理:首先根據(jù)程序的控制流構(gòu)建一個(gè)有向無(wú)環(huán)圖(DAG),, 然后對(duì) DAG 執(zhí)行如下校驗(yàn):

  • 首先,,對(duì) DAG 進(jìn)行一次深度優(yōu)先搜索(depth-first search),以 確保它是無(wú)環(huán)的(acyclic),,例如,,沒(méi)有循環(huán),也不包含不支持或無(wú)法執(zhí)行到的指令,。

  • 然后,,再掃描一遍,這次會(huì)遍歷 DAG 的所有可能路徑。這次掃描的目的是:

    程序執(zhí)行 load或 call指令時(shí),,如果參數(shù)不合法,,就會(huì)在這里被拒絕。參數(shù)合法 性是通過(guò)在程序執(zhí)行期間跟蹤所有寄存器和棧變量的狀態(tài)(states of registers and stack variables)來(lái)實(shí)現(xiàn)的,。

    • 確保程序的內(nèi)存訪問(wèn)都是安全的,,

    • 調(diào)用 helper 函數(shù)時(shí)傳的參數(shù)類型是對(duì)的。

內(nèi)存越界和空指針檢查:職責(zé)上移到程序自身/開(kāi)發(fā)者

這種跟蹤寄存器狀態(tài)的機(jī)制是為了在無(wú)法預(yù)知內(nèi)存邊界的情況下,,仍然確保程序 的內(nèi)存訪問(wèn)不會(huì)越界,。無(wú)法預(yù)知內(nèi)存邊界是因?yàn)椋?/p>

  • 包的大小是不固定的;

  • map 的內(nèi)容也無(wú)法提前預(yù)知,,因此也無(wú)法判斷一次 map 查找操作是否會(huì)成功,。

為解決這個(gè)問(wèn)題,校驗(yàn)器會(huì)檢查已加載的程序自身是否會(huì)做如下檢查

  1. 解引用指針前做了內(nèi)存邊界檢查,,

  2. 查詢 map 之前是檢查了 map 指針是否為空,。

這種方式將處理邏輯中的安全檢查和遇到錯(cuò)誤時(shí)如何處理的控制權(quán)都 交給了 BPF 程序的編寫(xiě)者

跟蹤數(shù)據(jù)訪問(wèn)操作和值范圍

為跟蹤數(shù)據(jù)訪問(wèn),,校驗(yàn)器會(huì)跟蹤

  1. 數(shù)據(jù)類型

  2. 指針偏置(pointer offsets)

  3. 所有寄存器的可能值范圍

程序開(kāi)始時(shí):

  • R1寄存器中存儲(chǔ)的是指向 context metadata 的指針(struct xdp_md *ctx),

  • R10是棧指針(stack pointer),,

  • 其他所有寄存器都是未初始化狀態(tài)。

接下來(lái)程序每執(zhí)行一步,,寄存器狀態(tài)就會(huì)更新一次,。當(dāng)寄存器中存入一個(gè)新值時(shí),這個(gè)寄存器 還會(huì)繼承與這個(gè)值相關(guān)的狀態(tài)變量(inherits the state variables from the source of the value),。

算術(shù)操作會(huì)影響標(biāo)量類型的值的范圍(value ranges of scalar types),以及指針類型的 offset,。 可能的最大范圍(max possible range)存儲(chǔ)在狀態(tài)變量中,,例如往寄存器中 load 一個(gè)字節(jié)時(shí), 這個(gè)寄存器的可能值范圍就設(shè)置為 0~255,。指令圖(instruction graph)中的 各邏輯分支就會(huì)根據(jù)操作結(jié)果更新寄存器狀態(tài),。例如,比較操作 R1 > 10,,

  • 校驗(yàn)器在一個(gè)分支 if R1 > 10中會(huì)將 R1 最小值設(shè)為 11,,

  • 在另一個(gè) else分支中將其最大值設(shè)為 10。

不同類型數(shù)據(jù)的校驗(yàn)信息來(lái)源(source of truth)

利用狀態(tài)變量中存儲(chǔ)的范圍信息,,校驗(yàn)器就能預(yù)測(cè)每個(gè) load 指令能訪問(wèn)的所有 內(nèi)存范圍,,確保它執(zhí)行的都是合法內(nèi)存訪問(wèn)。

  1. 對(duì)于包數(shù)據(jù)(packet data)的訪問(wèn),,會(huì)與 context 對(duì)象中的 data_end變量做比較,;

  2. 對(duì)于 BPFmap 中獲取的值,或用到 map 定義中聲明的 data size 信息;

  3. 對(duì)于棧上存儲(chǔ)的值,,會(huì)檢查狀態(tài)變量中記錄的值范圍,;

  4. 對(duì)于針?biāo)阈g(shù)操作(pointer arithmetic)還會(huì)施加額外的限制,指針通常不能被轉(zhuǎn)換成整形值,。

只要校驗(yàn)器無(wú)法證明某個(gè)操作是安全,,該 BPF 程序在加載時(shí)(load time)就會(huì)被拒絕。 除此之外,,校驗(yàn)器還會(huì)利用范圍信息確保內(nèi)存的對(duì)齊訪問(wèn)(enforce aligned memory access),。

校驗(yàn)器的目的

需要說(shuō)明的是,校驗(yàn)器的目的是避免將內(nèi)核內(nèi)部(the internals of the kernel )暴露給惡意或有缺陷的 eBPF 程序,,而非確保程序中函數(shù)的實(shí)現(xiàn)已經(jīng)是最高效的,。

換句話說(shuō),如果 XDP 程序中處理邏輯過(guò)多,,也可能會(huì)導(dǎo)致機(jī)器變慢 ,;如果代碼寫(xiě)的有問(wèn)題,也可能會(huì)破壞包數(shù)據(jù),。出于這些原因,,加載 BPF 程序需要 管理員權(quán)限(root)。避免這些 bug 的責(zé)任在程序員,,但選擇將哪些程序加載 到系統(tǒng)的權(quán)限在管理員,。

3.5 XDP 程序示例

下面是一個(gè)簡(jiǎn)單的 XDP 程序,展示了前面介紹的一些特性,。 程序會(huì)解析包數(shù)據(jù),,判斷如果是 UDP 包,直接交換源和目的 MAC 地址,,然后將包從相同網(wǎng)卡再發(fā)送回去,,

雖然這是一個(gè)非常簡(jiǎn)單的例子,但真實(shí)世界中的 XDP 程序用到的組件和特性,,這里基本都具備了,。

// 從內(nèi)核 BPF 代碼示例 xdp2_kern.c 修改而來(lái)。

1 // 用于統(tǒng)計(jì)包數(shù)
2 struct bpf_map_def SEC('maps') rxcnt = {
3 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
4 .key_size = sizeof(u32), // IP 協(xié)議類型,,即 IPv4/IPv6
5 .value_size = sizeof(long), // 包數(shù)
6 .max_entries = 256,
7 };
8
9 // 直接操作包數(shù)據(jù)(direct packet data access),,交換 MAC 地址
10 static void swap_src_dst_mac(void *data)
11 {
12 unsigned short *p = data;
13 unsigned short dst[3];
14 dst[0] = p[0]; dst[1] = p[1]; dst[2] = p[2];
15 p[0] = p[3]; p[1] = p[4]; p[2] = p[5];
16 p[3] = dst[0]; p[4] = dst[1]; p[5] = dst[2];
17 }
18
19 static int parse_ipv4(void *data, u64 nh_off, void *data_end)
20 {
21 struct iphdr *iph = data nh_off;
22 if (iph 1 > data_end)
23 return 0;
24 return iph->protocol;
25 }
26
27 SEC('xdp1') // marks main eBPF program entry point
28 int xdp_prog1(struct xdp_md *ctx)
29 {
30 void *data_end = (void *)(long)ctx->data_end;
31 void *data = (void *)(long)ctx->data;
32 struct ethhdr *eth = data; int rc = XDP_DROP;
33 long *value; u16 h_proto; u64 nh_off; u32 ipproto;
34
35 nh_off = sizeof(*eth);
36 if (data nh_off > data_end)
37 return rc;
38
39 h_proto = eth->h_proto;
40
41 /* check VLAN tag; could be repeated to support double-tagged VLAN */
42 if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
43 struct vlan_hdr *vhdr;
44
45 vhdr = data nh_off;
46 nh_off = sizeof(struct vlan_hdr);
47 if (data nh_off > data_end)
48 return rc;
49 h_proto = vhdr->h_vlan_encapsulated_proto;
50 }
51
52 if (h_proto == htons(ETH_P_IP))
53 ipproto = parse_ipv4(data, nh_off, data_end);
54 else if (h_proto == htons(ETH_P_IPV6))
55 ipproto = parse_ipv6(data, nh_off, data_end);
56 else
57 ipproto = 0;
58
59 /* lookup map element for ip protocol, used for packet counter */
60 value = bpf_map_lookup_elem(&rxcnt, &ipproto);
61 if (value)
62 *value = 1;
63
64 /* swap MAC addrs for UDP packets, transmit out this interface */
65 if (ipproto == IPPROTO_UDP) {
66 swap_src_dst_mac(data);
67 rc = XDP_TX;
68 }
69 return rc;
70 }

具體地:

  • 定義了一個(gè) BPF map 存儲(chǔ)統(tǒng)計(jì)信息。用戶態(tài)程序可以 poll 這個(gè) map 來(lái)獲取統(tǒng)計(jì)信息,。

  • context 對(duì)象 struct xdp_md *ctx中有包數(shù)據(jù)的 start/end 指針,,可用于直接訪問(wèn)包數(shù)據(jù)

  • 將數(shù)據(jù)指針和 data_end比較,,確保內(nèi)存訪問(wèn)不會(huì)越界,。

  • 程序必須自己解析包,,包括 VLAN headers 等東西。

  • 直接通過(guò)指針(direct packet data access)修改包頭,。

  • 內(nèi)核提供的 map lookup helper,。這是程序中唯一的真實(shí)函數(shù)調(diào)用;其他函數(shù)都是內(nèi)聯(lián),,包括 htons(),。

  • 最終針對(duì)這個(gè)包的判決通過(guò)程序返回值傳遞給調(diào)用方。

將這段程序安裝到網(wǎng)卡接口上時(shí),,它首先會(huì)被編譯成 eBPF 字節(jié)碼,,然后經(jīng)受校驗(yàn)器檢查。 這里的檢查項(xiàng)包括:

  1. 無(wú)循環(huán)操作,;程序大?。ㄖ噶顢?shù)量);

  2. 訪問(wèn)包數(shù)據(jù)之前,,做了內(nèi)存邊界檢查,;

  3. 傳遞給 map lookup 函數(shù)的參數(shù),類型與 map 定義相匹配,;

  4. map lookup 的返回值(value 的內(nèi)存地址)在使用之前,,檢查了是否為 NULL

3.6 小結(jié)

XDP 系統(tǒng)由四個(gè)主要部分組成:

  1. XDP device driver hook:網(wǎng)卡收到包之后直接運(yùn)行,;

  2. eBPF 虛擬機(jī):執(zhí)行 XDP 程序(以及內(nèi)核其他模塊加載的 BPF 程序),;

  3. BPF maps:使不同 BPF 程序之間、BPF 程序與用戶空間應(yīng)用之間能夠通信,;

  4. eBPF verifier:確保程序不包含任何可能會(huì)破壞內(nèi)核的操作,。

這四部分加在一起,創(chuàng)造了一個(gè)編寫(xiě)自定義包處理應(yīng)用的強(qiáng)大環(huán)境,,它能加速包處理的關(guān)鍵 路徑,,同時(shí)還與內(nèi)核及現(xiàn)有基礎(chǔ)設(shè)施密切集成。

接下來(lái)看一下 XDP 應(yīng)用的性能,。

4 性能評(píng)估

DPDK 是目前性能最高的包處理框架 [18],因此本文將 XDP 與 DPDK 及 Linux 內(nèi)核網(wǎng)絡(luò) 棧的性能做一個(gè)對(duì)比,。測(cè)試機(jī)器環(huán)境:

  • CPU:一塊 hexa-core Intel Xeon E5-1650 v4 CPU running at 3.60GHz,, 支持 Intel Data Direct I/O (DDIO) 技術(shù),網(wǎng)絡(luò)硬件通過(guò) DMA 能直接將包放到 CPU 緩存,。

  • 關(guān)閉超線性(Hyperthreading),。

  • 網(wǎng)卡:兩塊 Mellanox ConnectX-5 Ex VPI dual-port 100Gbps,mlx5 驅(qū)動(dòng),。

  • 內(nèi)核:Linux 4.18

  • 使用基于 DPDK 的 TRex packet generator [9] 生成測(cè)試流量,。所有測(cè)試腳本位于 [22],。

在測(cè)試中,我們主要關(guān)心三個(gè) metric:

  • 直接棄包(packet drop)性能,。

    為展示最高的包處理性能,,我們將用最簡(jiǎn)單的操作 —— 丟棄接收到的包—— 來(lái)測(cè)試。 這個(gè)測(cè)試能有效測(cè)量系統(tǒng)的整體開(kāi)銷,,也是真正的包處理應(yīng)用能達(dá)到的性能上限,。

  • CPU 使用量。

    如引言中指出,,XDP 的優(yōu)點(diǎn)之一是 CPU 使用量與流量大小是正相關(guān)的,,而無(wú)需預(yù)留專 門(mén)的 CPU 給它用。我們通過(guò)測(cè)量 CPU 利用率隨網(wǎng)絡(luò)負(fù)載的變化來(lái)量化這個(gè)指標(biāo),。

  • 包轉(zhuǎn)發(fā)性能,。

    轉(zhuǎn)發(fā)的復(fù)雜性要更高一些,例如,,涉及到與多塊網(wǎng)卡的交互,、重寫(xiě)二層頭等等。 這里會(huì)將轉(zhuǎn)發(fā)延遲也考慮進(jìn)去,。

我們已經(jīng)驗(yàn)證,,使用 MTU(1500 字節(jié))包時(shí),我們的系統(tǒng)單核就能達(dá)到線速(100 Gbps), 而且 CPU 有 50% 是空閑的,。顯然,,真正的挑戰(zhàn)在于 PPS,而非帶寬,,其他一些測(cè)試也已經(jīng)指出了這一點(diǎn) [46],。 出于這個(gè)原因,我們用最小包(64 字節(jié))測(cè)試,,衡量指標(biāo)是 PPS,。

對(duì)于 XDP 和 Linux 內(nèi)核網(wǎng)絡(luò)棧的測(cè)試,由于它們沒(méi)有顯式指定某些 CPU 來(lái)處理網(wǎng)絡(luò)包的方式,,因此我們通過(guò)配置硬件 RSS(Receive Side Scaling)來(lái)講流量定向到指定 CPU,。

對(duì)網(wǎng)卡、內(nèi)核的一些配置調(diào)優(yōu),,見(jiàn)代碼倉(cāng)庫(kù) [22],。

4.1 直接棄包(packet drop)性能

圖片

Fig 3. 直接棄包(packet drop)性能。DPDK 需要預(yù)留一個(gè) CPU 運(yùn)行控制任務(wù),,因此只剩下 5 個(gè) CPU 做包處理,。

上圖是性能與 CPU 數(shù)量的關(guān)系。

  • XDP 基準(zhǔn)性能是 24Mpps/core,,DPDK 是 43.5Mpps/core,。

  • 二者在分別達(dá)到各自的峰值之前,,PPS 都是隨 CPU 數(shù)量線性增長(zhǎng)的。

  • 最終全局性能受限于 PCI 總線,,啟用 PCI descriptor compression(在 CPU cycles 和 PCI 總線帶寬之間取舍)之后,,能達(dá)到 115Mpps。

再看圖中 Linux 網(wǎng)絡(luò)棧在兩種配置下的性能:

  1. 通過(guò) iptables 的 raw table丟棄流量,,這是 Linux 網(wǎng)絡(luò)棧中最早能丟棄包的地方,;

  2. 通過(guò) conntrack(連接跟蹤)模塊,這個(gè)模塊的開(kāi)銷非常大,,但在很多 Linux 發(fā)行版中都是默認(rèn)開(kāi)啟的,。

conntrack 模式達(dá)到了 1.8Mpps/core,raw 模式是 4.8Mpps/core ,;這兩種模式均未達(dá)到硬件瓶頸,。 最終的性能,XDP 比常規(guī)網(wǎng)絡(luò)棧的最快方式快了 5 倍,。

Linux raw mode test 中,,我們還測(cè)量了 XDP 程序不丟棄包,而是更新包數(shù)統(tǒng)計(jì)然后將包 送到內(nèi)核網(wǎng)絡(luò)棧的場(chǎng)景,。 這種情況下,,XDP單核的處理性能會(huì)下降到 4.5Mpps/core,有 13.3ns 處理延遲,。 圖中并未給出這個(gè)測(cè)試結(jié)果,,因?yàn)檫@個(gè)開(kāi)銷太小了。

4.2 CPU Usage

圖片

Fig 4. 直接棄包(packet drop)場(chǎng)景下的 CPU 利用率,。

用系統(tǒng)提供的 mpstat命令測(cè)量 CPU 利用率,。結(jié)果如圖 4 。

  • DPDK 是 busy poll 模式,,因此 CPU 永遠(yuǎn)是 100%,。

  • XDP 和 Linux 內(nèi)核網(wǎng)絡(luò)棧都是隨流量平滑增長(zhǎng):前面一小段是非線性的,后面基本是線性的,。

    前面非線性主要是硬中斷帶來(lái)的固定開(kāi)銷,,在流量很小時(shí)這一部分占比較大。

4.3 包轉(zhuǎn)發(fā)性能

這個(gè)測(cè)試中,,轉(zhuǎn)發(fā)應(yīng)用執(zhí)行非常簡(jiǎn)單的 MAC 地址重寫(xiě):直接交換源和目的 MAC 地址,,然后轉(zhuǎn)發(fā)。 這是轉(zhuǎn)發(fā)場(chǎng)景下最精簡(jiǎn)的步驟了,,因此結(jié)果代表了所有真實(shí)轉(zhuǎn)發(fā)應(yīng)用的性能上限,。

  • 圖中包括了同網(wǎng)卡轉(zhuǎn)發(fā)和不同網(wǎng)卡轉(zhuǎn)發(fā)(XDP程序返回碼不同)的結(jié)果,。

  • DPDK 示例程序只支持通過(guò)另一個(gè)網(wǎng)卡轉(zhuǎn)發(fā),,因此這里只列出了這種情況下的性能,。

  • Linux 網(wǎng)絡(luò)棧不支持這種極簡(jiǎn)轉(zhuǎn)發(fā)模式(minimal forwarding mode),需要設(shè)置完整的 橋接或路由查找(bridging or routing lookup)才能轉(zhuǎn)發(fā)包,;路由查找是非常耗時(shí)的 ,,由于其他幾種應(yīng)用并沒(méi)有這一步,因此結(jié)果直接對(duì)比是沒(méi)意義的,。因此這里略去了 Linux 網(wǎng)絡(luò)棧的結(jié)果,。

轉(zhuǎn)發(fā)吞吐(pps)

圖片

Fig 5. 轉(zhuǎn)發(fā)性能。在同一網(wǎng)卡接口上收發(fā)會(huì)占用同一 PCI port 的帶寬,, 這意味著在 70Mpps XDP same-nic 組就已經(jīng)達(dá)到了 PCI 總線的瓶頸

如圖 5 所示,,性能隨 CPU 數(shù)量線性擴(kuò)展,直到達(dá)到全局性能瓶頸,。XDP 在同網(wǎng)卡轉(zhuǎn)發(fā)的性能遠(yuǎn)高于 DPDK 異網(wǎng)卡性能,,原因是內(nèi)存處理方式不同

  • packet buffer 是設(shè)備驅(qū)動(dòng)分配的,與接收接口(receiving interface)相關(guān)聯(lián),。

  • 因此,,異網(wǎng)卡場(chǎng)景下,當(dāng)包轉(zhuǎn)發(fā)到另一個(gè)接口時(shí),,memory buffer 需要還給與之關(guān)聯(lián)的接口,。

轉(zhuǎn)發(fā)延遲

圖片

表 1. 轉(zhuǎn)發(fā)延遲。機(jī)器網(wǎng)卡的兩個(gè)接口直連,,在轉(zhuǎn)發(fā)速率分別為 100pps 和 1Mpps 的條件下,,持續(xù) 50s 測(cè)量端到端延遲

高 pps 場(chǎng)景下,XDP 的延遲已經(jīng)接近 DPDK,。但在低 pps 場(chǎng)景下,,XDP 延遲比 DPDK 大的多,原因是 XDP 是基于中斷的,,中斷處理時(shí)間( interrupt processing time)此時(shí)占大頭,;而 DPDK 是輪詢模式,延遲相對(duì)比較固定,。

4.4 討論:XDP 性能與 DPDK 還有差距的原因

XDP 未做底層代碼優(yōu)化

上一節(jié)已經(jīng)看到,,XDP 相比于常規(guī) Linux 網(wǎng)絡(luò)棧性能有了顯著提升。但對(duì)于大部分 XDP 場(chǎng)景來(lái)說(shuō),,性能還是與 DPDK 有差距,。我們認(rèn)為,這是主要是因?yàn)?DPDK 做了相當(dāng)多的底層 代碼優(yōu)化,。舉個(gè)例子來(lái)解釋,,考慮 packet drop 例子:

  • XDP 24Mpps/core,對(duì)應(yīng) 41.6ns/packet

  • DPDK 43.5Mpps,,對(duì)應(yīng) 22.9ns/packet

多出來(lái)的 18.7ns 在我們的 3.6GHz 機(jī)器上對(duì)應(yīng) 67 個(gè)時(shí)鐘周期,。因此,,很顯然 每個(gè)很小的優(yōu)化在這里都會(huì)產(chǎn)生很大的影響。例如,,我們測(cè)量出在測(cè)試 機(jī)器上,,每次函數(shù)調(diào)用需要 1.3ns。mlx5 驅(qū)動(dòng)處理每個(gè)包都有 10 次 函數(shù)調(diào)用,,總計(jì)就是 13ns,。

通用目的操作系統(tǒng),首要目標(biāo):更好的擴(kuò)展和配置,,而非極致性能

另外,,在 Linux 這樣的通用目的操作系統(tǒng)中,某些開(kāi)銷是不可避免的,, 因?yàn)樵O(shè)備驅(qū)動(dòng)或子系統(tǒng)的組織方式是為了實(shí)現(xiàn)更好的擴(kuò)展和配置,,而非極致性能

但是,,我們認(rèn)為有些優(yōu)化還是有必要的,。例如,我們嘗試將內(nèi)核中與測(cè)試網(wǎng)卡無(wú)關(guān)的 DMA 函數(shù)調(diào)用刪掉,, 這樣將前面提到的 10 個(gè)函數(shù)調(diào)用降低到了 6 個(gè),,測(cè)試結(jié)果顯示這將單核性能提升到了 29Mpps/core。 依此推測(cè)的話,,將另外 6 個(gè)函數(shù)調(diào)用也優(yōu)化掉,,能將 XDP 的性能提升到 37.6Mpps。 實(shí)際上我們不可能將 6 個(gè)全部去掉,,但去掉其中幾個(gè),,再加上一些其他優(yōu)化,我 們相信 XDP 和 DPDK 的性能差距將越來(lái)越小,。

其他驅(qū)動(dòng)的測(cè)試結(jié)果也是類似的,,例如 i40e driver for 40 Gbps Intel cards。

基于以上討論,,我們相信未來(lái) XDP 與 DPDK 的性能差距將越來(lái)越小,。

另一方面,考慮到 XDP 在靈活性和與內(nèi)核集成方面的優(yōu)勢(shì),, XDP 已經(jīng)是很多實(shí)際場(chǎng)景中的非常有競(jìng)爭(zhēng)力的方式,。下文給出幾個(gè)例子。

5 真實(shí)場(chǎng)景使用案例

本節(jié)給出三個(gè)例子來(lái)具體展示 XDP 在真實(shí)世界中的應(yīng)用,。 這幾個(gè)案例都是已經(jīng)真實(shí)在用的,,但本文出于解釋目的,將使用簡(jiǎn)化的版本。 同時(shí)也建議讀者參考 [38],,后者是獨(dú)立的文章,,介紹使用 XDP 解決實(shí)際工作中網(wǎng)絡(luò)服務(wù)所面臨的一些挑戰(zhàn)。

本節(jié)目的是展示真實(shí) XDP 方案的可行性,,因此不會(huì)將重點(diǎn)放在與業(yè)界最新的實(shí)現(xiàn)做詳盡性能對(duì)比上。 我們會(huì)拿常規(guī)的 Linux 內(nèi)核網(wǎng)絡(luò)棧的性能作為 baseline,,來(lái)對(duì)比 XDP 應(yīng)用的性能,。

5.1 案例一:軟件路由(software routing)

內(nèi)核數(shù)據(jù)平面 & 控制平面(BIRD/FRR)

Linux 內(nèi)核實(shí)現(xiàn)了一個(gè)功能完整的路由表,作為數(shù)據(jù)平面,,支持

  • policy routing

  • source-specific routing

  • multipath load balancing, and more.

對(duì)于控制平面,,Bird [10] 或 FRR [17] 這樣的路由守護(hù)進(jìn)程( routing daemons)實(shí)現(xiàn)了多種路由控制平面協(xié)議。Linux 提供的這套生態(tài)系統(tǒng)功能如此豐富 ,,因此再在另一個(gè)包處理框架中重新實(shí)現(xiàn)一套類似的路由棧代價(jià)將非常高,, 更實(shí)際的方式是對(duì) Linux 內(nèi)核的數(shù)據(jù)平面進(jìn)行優(yōu)化。

XDP:直接查詢內(nèi)核路由表并轉(zhuǎn)發(fā)

XDP 非常適合做這件事情,,尤其是它提供了一個(gè) helper 函數(shù),,能從 XDP 程序中直接查詢內(nèi)核路由表

  • 如果查詢成功,,會(huì)egress interface 和下一跳 MAC 地址,, XDP 程序利用這些信息足夠?qū)⒓崔D(zhuǎn)發(fā)出去

  • 如果下一跳 MAC 還是未知的(因?yàn)橹斑€沒(méi)進(jìn)行過(guò) neighbour lookup),,XDP 程序就 能將包傳給內(nèi)核網(wǎng)絡(luò)棧,,后者會(huì)解析 neighbor 地址,這樣隨后的包 就能直接被 XDP 程序轉(zhuǎn)發(fā)了,。

測(cè)試:XDP routing 全球 BGP 路由表

為展示 XDP 路由的性能,,我們用 Linux 內(nèi)核代碼中的 XDP routing 例子 [1],與常規(guī) Linux 內(nèi)核網(wǎng)絡(luò)棧的性能做對(duì)比,。 兩組測(cè)試:

  1. 路由表中只有一條路由,;

  2. 路由表中有從 routeviews.org 中 dump 而來(lái)的全球 BGP 路由表(global BGP routing table)。 包含 752,138 條路由,。隨機(jī)生成 4000 個(gè)目的 IP 地址,,以確保能充分利用到這種路由表。

    如果目的 IP 地址少于 4000 個(gè),,實(shí)際用到的路由表部分會(huì)較小,,能夠保存在 CPU 緩存中,使得結(jié)果不準(zhǔn)確,。 增大 IP 數(shù)量至 4000 個(gè)以上,,不會(huì)對(duì)轉(zhuǎn)發(fā)性能造成影響,但可以避免緩存導(dǎo)致的結(jié)果不準(zhǔn)問(wèn)題。

對(duì)于兩組測(cè)試,,下一跳 MAC 地址都是與我們的發(fā)送網(wǎng)卡直接相關(guān)的接口的地址,。

性能:2.5x

圖片

Fig 6. 軟件路由的性能。由于性能隨核數(shù)線性增加,,這里只給出單核的結(jié)果,。

測(cè)試結(jié)果如上圖所示。

  • full table lookup 性能提升了 2.5 倍,;

  • smaller routing table 組,,提升了 3 倍。

這說(shuō)明,,XDP 路由程序 單核 10Gbps 網(wǎng)卡的軟硬件配置,,就能 處理整張全球 BGP 路由表(保守估計(jì)每個(gè)包平均 300 字節(jié))。

5.2 案例二:Inline DoS Mitigation

DoS 攻擊還是像瘟疫一樣糾纏著互聯(lián)網(wǎng),,現(xiàn)在通常的方式是:通過(guò)已經(jīng)入侵的大量設(shè)備發(fā)起分布式(DDoS)攻擊,。

有了XDP 之后,我們能直接在應(yīng)用服務(wù)器(application servers)上 部署包過(guò)濾程序來(lái)防御此類攻(inline DoS mitigation),, 無(wú)需修改應(yīng)用代碼,。如果應(yīng)用是部署在虛擬機(jī)里,那 XDP 程序還可以 部署在宿主機(jī)(hypervisor)上,,這樣單個(gè)程序就能保護(hù)機(jī)器上所有的虛擬機(jī),。

模擬 Cloudflare 防御架構(gòu)

為展示工作原理,我們用 XDP 作為過(guò)濾機(jī)制,,模擬 Cloudflare 的 DDoS 防御架構(gòu)[6],。 他們的 Gatebot architecture ,首先在各 PoP 點(diǎn)機(jī)器上采樣,,然后統(tǒng)一收起來(lái)做分析,, 根據(jù)分析結(jié)果生成防御規(guī)則。

防御規(guī)則的形式是對(duì)包數(shù)據(jù)(payload)進(jìn)行一系列簡(jiǎn)單檢查,, 能直接編譯成 eBPF 代碼然后分發(fā)到 PoP 點(diǎn)的所有服務(wù)器上,。這里說(shuō)的代碼是 XDP 程序 ,它會(huì)將匹配到規(guī)則的所有流量丟棄,,同時(shí)將統(tǒng)計(jì)信息更新到 BPF map,。

程序邏輯

為驗(yàn)證這種方案的性能,我們編寫(xiě)一個(gè) XDP 程序,,它

  1. 解析包頭,,執(zhí)行一些簡(jiǎn)單驗(yàn)證。對(duì)每個(gè)包:執(zhí)行四次讀取操作,,以解析外層包頭,。

  2. 將符合攻擊特性的流量丟棄。具體:丟棄 UDP 特定端口的流量

  3. 將其他流量通過(guò) CPU redirect 方式重定向給另一個(gè) CPU做進(jìn)一步處理,;

性能

我們用 netperf 做性能壓測(cè) [26],。

  • 用 netperf TCP round-trip benchmark,單個(gè) TCP 連接來(lái)回小的 request/reply,,統(tǒng)計(jì) transactions/second,。

    模擬的是互式應(yīng)用,例如小的遠(yuǎn)程過(guò)程調(diào)用(RPC),。

  • 實(shí)驗(yàn)在單核上進(jìn)行,,模擬多個(gè)流量(正常流量 攻擊流量)競(jìng)爭(zhēng)同一物理資源的場(chǎng)景。

  • 在 beseline 35K 業(yè)務(wù) TPS(transactions per second)基礎(chǔ)上,,打少量 UDP 流量作為攻擊流量。逐漸加大攻擊流量,,觀察 TPS 的變化,。

圖片

Fig 7. DDoS 性能。業(yè)務(wù)吞吐(TPS)隨攻擊流量的變化,。

結(jié)果如上圖所示,,

  • 沒(méi)有 XDP 的一組,性能急劇下降:攻擊流量在 3Mpps 時(shí)性能減半,,3.5Mpps 時(shí)基本跌零,;

  • 有 XDP 程序的一組,攻擊流量達(dá)到 19.5Mpps 之前,,業(yè)務(wù)吞吐保持在 28.5K TPS 以上,,過(guò)了這個(gè)臨界點(diǎn)性能才開(kāi)始急劇下降。

以上結(jié)果表明,,XDP 防御 DDoS 攻擊在實(shí)際中是完全可行的,,單核就能輕松處理 10Gbps 的、都是最小包(minimum-packet)的 DoS 流量,。 這種 DDoS 防御的部署更加靈活,,無(wú)需硬件或應(yīng)用做任何改動(dòng)。

5.3 案例三:負(fù)載均衡(load balancing)

Facebook Katran

負(fù)載均衡的場(chǎng)景,,我們用 Facebook 開(kāi)源的 Katran 作為例子 [15],。Katran 的工作原理是對(duì)外通告服務(wù)的 IP,這樣目標(biāo)是這個(gè) IP 的流量就會(huì)被路由到 XDP 實(shí)現(xiàn)的負(fù)載均衡器,。

  • 負(fù)載均衡器對(duì)包頭(source packet header)進(jìn)行哈希,,以此選擇目標(biāo)應(yīng)用服務(wù)器。

  • 然后將對(duì)包進(jìn)行封裝(encap),,發(fā)送給應(yīng)用服務(wù)器,;

  • 應(yīng)用服務(wù)器解封裝(decap),處理請(qǐng)求,然后直接將回包發(fā)給客戶端(DSR 模式),。

在這個(gè)過(guò)程中,,XDP 程序負(fù)責(zé)哈希、封裝以及將包從接收網(wǎng)卡再發(fā)出去的任務(wù),。 配置信息存儲(chǔ)在 BPF map 中,,整個(gè)封裝邏輯是完全在 eBPF 中實(shí)現(xiàn)的。

性能

為測(cè)試性能,,我們給 Katran XDP 程序配置幾個(gè)固定的目標(biāo)機(jī)器,。 對(duì)照組是 IPVS,它是 Linux 內(nèi)核的一部分,。性能如表 2 所示,,隨 CPU 數(shù)量線性增長(zhǎng), XDP 比 IPVS 性能高 4.3 倍,。

表 2. 負(fù)載均衡器性能(Mpps)

圖片

配置:1 VIP/core, 100 DstIPs/VIP.

6 XDP 的未來(lái)方向

XDP 已經(jīng)能用于解決真實(shí)問(wèn)題,,但作為 Linux 內(nèi)核的一部分,XDP 還在快速開(kāi)發(fā)過(guò)程中,。

6.1 eBPF 程序的限制

前面提到,,加載到 eBPF 虛擬機(jī)的程序必須保證其安全性(不會(huì)破壞內(nèi)核),因此對(duì) eBPF 程序作了一下限制,,歸結(jié)為兩方面:

  1. 確保程序會(huì)終止:在實(shí)現(xiàn)上是通過(guò)禁止循環(huán)和限制程序的最大指令數(shù)(max size of the program),;

  2. 確保內(nèi)存訪問(wèn)的安全:通過(guò) 3.4 小結(jié)介紹的寄存器狀態(tài)跟蹤(register state tracking)來(lái)實(shí)現(xiàn)。

校驗(yàn)邏輯偏保守

由于校驗(yàn)器的首要職責(zé)是保證內(nèi)核的安全,,因此其校驗(yàn)邏輯比較保守,, 凡是它不能證明為安全的,一律都拒絕,。有時(shí)這會(huì)導(dǎo)致假陰性(false negatives),, 即某些實(shí)際上是安全的程序被拒絕加載;這方面在持續(xù)改進(jìn),。

  • 校驗(yàn)器的錯(cuò)誤提示也已經(jīng)更加友好,,以幫助開(kāi)發(fā)者更快定位問(wèn)題。

  • 近期已經(jīng)支持了 BPF 函數(shù)調(diào)用(function calls),。

  • 正在計(jì)劃支持有限循環(huán)(bounded loops),。

  • 正在提升校驗(yàn)器效率,以便處理更大的 BPF 程序,。

缺少標(biāo)準(zhǔn)庫(kù)

相比于用戶空間 C 程序,,eBPF 程序的另一個(gè)限制是缺少標(biāo)準(zhǔn)庫(kù),包括 內(nèi)存分配,、線程,、鎖等等庫(kù),。

  1. 內(nèi)核的生命周期和執(zhí)行上下文管理(life cycle and execution context management )部分地彌補(bǔ)了這一不足,(例如,,加載的 XDP 程序會(huì)為每個(gè)收到的包執(zhí)行),,

  2. 內(nèi)核提供的 helper 函數(shù)也部分地彌補(bǔ)了一不足。

一個(gè)網(wǎng)卡接口只能 attach 一個(gè) XDP 程序

這個(gè)限制其實(shí)也是可以繞過(guò)的:將 XDP 程序組織成程序數(shù)組,,通過(guò)尾 調(diào)用,,根據(jù)包上下文在程序之間跳轉(zhuǎn),或者是將幾個(gè)程序做 chaining,。

6.2 用戶體驗(yàn)和調(diào)試

XDP 程序運(yùn)行在內(nèi)核,,因此常規(guī)的用戶空間 debug 工具是用不了的,但內(nèi)核自帶的 debug 和 introspection 功能是可以用在 XDP (及其他 eBPF 程序)上的,。 包括:

  • tracepoints and kprobes [13]

  • performance counters that are part of the perf subsystem [42]

但不熟悉內(nèi)核生態(tài)系統(tǒng)的開(kāi)發(fā)者可能會(huì)對(duì)這些工具感到非常陌生,,難以使用。因此,,也出 現(xiàn)了一些更方便普通開(kāi)發(fā)者的工具,,包括 BCC [50]、bpftool [8],、libbpf 函數(shù)庫(kù) [30] 等等,。

6.3 驅(qū)動(dòng)支持

設(shè)備要支持 XDP,,需要實(shí)現(xiàn)內(nèi)核核心網(wǎng)絡(luò)棧暴露出的一個(gè) API,。 寫(xiě)作本文時(shí) Linux 4.18 已經(jīng)有 12 種驅(qū)動(dòng)支持 XDP,包括了大部分高速網(wǎng)卡,。 最新列表見(jiàn) [2],。

隨著 XDP 系統(tǒng)的不斷成熟,核心代碼逐漸上移到內(nèi)核中,,驅(qū)動(dòng)需要維護(hù)的代碼越 來(lái)越少,。例如,redirection action 支持新的 target 時(shí),,無(wú)需驅(qū)動(dòng)做任何改動(dòng),。

最后,對(duì)于那些不支持 XDP 的驅(qū)動(dòng),,內(nèi)核提供了 Generic XDPfeature [39],,這是軟件實(shí)現(xiàn)的 XDP,性能會(huì)低一些,, 在實(shí)現(xiàn)上就是將 XDP 的執(zhí)行上移到了核心網(wǎng)絡(luò)棧(core networking stack),。

XDP 在內(nèi)核收包函數(shù) receive_skb() 之前

圖片

Generic XDP在 receive_skb() 之后,,

圖片

更多關(guān)于 Generic XDP,,可參考參考:容器網(wǎng)絡(luò)|深入理解Cilium

6.4 性能提升

XDPDPDK之間還有一些性能差距,,一些改進(jìn)工作正在進(jìn)行中:

  • 驅(qū)動(dòng)代碼 micro-optimisations

  • 刪除核心 XDP 代碼中的非必要操作

  • 通過(guò)批處理平攤處理開(kāi)銷

6.5 QoS 和 Rate Transitions

當(dāng)前,XDP 還沒(méi)有任何 QoS 機(jī)制,。 尤其是,,如果對(duì)端已經(jīng)過(guò)載(例如兩端的網(wǎng)絡(luò)速度或特性不匹配),XDP 程序是收不到任何背壓(back-pressure)的,,

雖然 XDP 中缺少 QoS,,但 Linux 內(nèi)核網(wǎng)絡(luò)棧中卻有很多業(yè)界最佳的 Active Queue Management (AQM) 特性和 packet scheduling algorithms [23]。 這些特性中,,部分并不適用于 XDP,,但我們相信能夠 以一種對(duì)包處理應(yīng)用完全透明的方式,選擇其中部分集成到 XDP,。 我們計(jì)劃對(duì)這一方向進(jìn)行更深入研究,。

6.6 加速傳輸層協(xié)議

我們已經(jīng)證明 XDP 能在保留操作系統(tǒng)原有功能的前提下,集成到操作系統(tǒng)中,,實(shí)現(xiàn)高速包數(shù)據(jù),。

目前的 XDP 還是用于無(wú)狀態(tài)包處理(stateless packet processing) ,如果將這個(gè)模型擴(kuò)展到有狀態(tài)傳輸層協(xié)議(stateful transport protocols),,例如 TCP,,它能給依賴可靠/有狀態(tài)傳輸?shù)膽?yīng)用提供類似的性能提升。

實(shí)際上,,已經(jīng)有一些研究證明,,相比于操作系統(tǒng)的協(xié)議棧,accelerated transport protocols 能顯著提升性能[5, 25, 35, 52],。其中的一個(gè)解決方案 [52] 表明,,在保留內(nèi) 核 TCP 協(xié)議棧的的前提下,原始包處理性能(raw packet processing)存在巨大的提升 空間,。

XDP 非常適用于這種場(chǎng)景,,目前也已經(jīng)有一些關(guān)于如何實(shí)現(xiàn)的初步討論 [21], 雖然離實(shí)際使用還很遠(yuǎn),,但仍然是一個(gè)令人振奮的,、擴(kuò)展 XDP 系統(tǒng) scope 的方向。

6.7 內(nèi)核-用戶空間零拷貝(zero-copy to userspace)

3.1 小節(jié)提到,,XDP 程序能將數(shù)據(jù)包重定向到用戶空間應(yīng)用(userspace application)打 開(kāi)的特殊類型 socket,。這可以用于加速客戶端和服務(wù)端在同一臺(tái)機(jī)器的網(wǎng)絡(luò)密集型應(yīng)用(network-heavy applications running on the local machine)。

更多信息可參考: (譯) 利用 ebpf sockmap/redirection 提升 socket 性能(2020),。 這里使用的是 BPF 而非 XDP,,但核心原理是一樣的,只是程序執(zhí)行的位置(hook)不同,。 譯注,。

但在目前的實(shí)現(xiàn)中,,這種方式在底層仍然需要拷貝包數(shù)據(jù),因此性能會(huì)打折扣,。

目前已經(jīng)有工作在進(jìn)行,,通過(guò) AF_XDP 實(shí)現(xiàn)真正的數(shù)據(jù)零拷貝。但這項(xiàng)工作需要 對(duì)網(wǎng)絡(luò)設(shè)備的內(nèi)存處理過(guò)程有一些限制,,因此需要設(shè)備驅(qū)動(dòng)的顯式支持,。 第一個(gè)支持這個(gè)功能的 patch 已經(jīng)合并到 4.19內(nèi)核,更多驅(qū)動(dòng)的支持 正在添加中,。初步的性能測(cè)試結(jié)果還是很樂(lè)觀的,,顯示能達(dá)到 20Mpps/core 的內(nèi)核到用戶 空間傳遞(transfer)速度。

6.8 XDP 作為基礎(chǔ)構(gòu)建模塊(XDP as a building block)

正如 DPDK 用于高層包處理框架的底層構(gòu)建模塊(例如 [31]),,XDP 有望成為高層應(yīng)用的運(yùn)行時(shí)環(huán)境 (runtime environment for higher-level applications),。

實(shí)際上,我們看到一些基于 XDP 的應(yīng)用和框架已經(jīng)出現(xiàn)了,。包括

  • Cilium security middle-ware [3]

  • Suricata network monitor [4]

  • Open vSwitch [49]

  • P4-to-XDP compiler project [51]

甚至還有人嘗試將 XDP 作為 DPDK 的一種底層驅(qū)動(dòng) [53],。

7 總結(jié)

本文描述了XDP,一個(gè)安全,、快速,、可編程、集成到操作系統(tǒng)內(nèi)核的包處理框架,。 測(cè)試結(jié)果顯示,,XDP能提供 24Mpps/core 的高處理性能,這一數(shù)字雖然與基于 kernel bypass 的DPDK仍有差距,,但提供了其他一些非常有競(jìng)爭(zhēng)力的優(yōu)勢(shì):

  1. 兼容內(nèi)核安全管理框架(kernel bypass 方式在bypass 內(nèi)核網(wǎng)絡(luò)棧的同時(shí),,也將安全和設(shè)備管理等這些極其重要的基礎(chǔ)設(shè)施 bypass 了),;

  2. 兼容內(nèi)核網(wǎng)絡(luò)棧,,可選擇性利用內(nèi)核已有的基礎(chǔ)設(shè)施和功能;

  3. 提供與內(nèi)核 API 一樣穩(wěn)定的編程接口,;

  4. 對(duì)應(yīng)用完全透明,;

  5. 更新、替換程序的過(guò)程不會(huì)引起服務(wù)中斷,;

  6. 無(wú)需專門(mén)硬件,,無(wú)需獨(dú)占CPU等資源。

相比于kernel bypass 這種非此即彼,、完全繞開(kāi)內(nèi)核的方式,,我們相信 XDP 有更廣闊的的應(yīng)用前景。Facebook,、Cloudflare 等公司實(shí)際落地的 XDP 應(yīng)用,,更加增強(qiáng)了我們的這種信心,。

最后,XDP系統(tǒng)還在快速發(fā)展,,前面也列出了一些正在未來(lái)可能會(huì)做的開(kāi)發(fā)/優(yōu)化工作,。

致謝

XDP has been developed by the Linux networking community for a number of years, and the authors would like to thank everyone who has been involved. In particular,

  • Alexei Starovoitov has been instrumental in the development of the eBPF VM and verifier;

  • Jakub Kicinski has been a driving force behind XDP hardware offloading and the bpftool utility;

  • Bj?rn T?pel and Magnus Karlsson have been leading the AF_XDP and userspace zero-copy efforts.

We also wish to extend our thanks to the anonymous reviewers, and to our shepherd Srinivas Narayana, for their helpful comments.

參考文獻(xiàn)

https:///blog/xdp-paper-acm-2018-zh/

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多