作者 | Julia Evans
譯者 | qhwdw ? ? ? ? ? 共計翻譯:106 篇 貢獻時間:193 天
今天,我喜歡的 meetup 網站上有一篇我超愛的文章!Suchakra Sharma[1](@tuxology[2] 在 twitter/github)的一篇非常棒的關於傳統 BPF 和在 Linux 中最新加入的 eBPF 的討論文章,正是它促使我想去寫一個 eBPF 的程式!
這篇文章就是 —— BSD 包過濾器:一個新的使用者級包捕獲架構[3]
我想在討論的基礎上去寫一些筆記,因為,我覺得它超級棒!
開始前,這裡有個 幻燈片[4] 和一個 pdf[5]。這個 pdf 非常好,結束的位置有一些連結,在 PDF 中你可以直接點選這個連結。
什麼是 BPF?
在 BPF 出現之前,如果你想去做包過濾,你必須複製所有的包到使用者空間,然後才能去過濾它們(使用 “tap”)。
這樣做存在兩個問題:
問題 #1 的解決方法似乎很明顯,就是將過濾邏輯移到核心中。(雖然具體實現的細節並沒有明確,我們將在稍後討論)
但是,為什麼過濾演演算法會很低效?
如果你執行 tcpdump host foo
,它實際上運行了一個相當複雜的查詢,用下圖的這個樹來描述它:
評估這個樹有點複雜。因此,可以用一種更簡單的方式來表示這個樹,像這樣:
然後,如果你設定 ether.type = IP
和 ip.src = foo
,你必然明白匹配的包是 host foo
,你也不用去檢查任何其它的東西了。因此,這個資料結構(它們稱為“控制流圖” ,或者 “CFG”)是表示你真實希望去執行匹配檢查的程式的最佳方法,而不是用前面的樹。
為什麼 BPF 要工作在核心中
這裡的關鍵點是,包僅僅是個位元組的陣列。BPF 程式是執行在這些位元組的陣列之上。它們不允許有迴圈(loop),但是,它們 可以 有聰明的辦法知道 IP 包頭(IPv6 和 IPv4 長度是不同的)以及基於它們的長度來找到 TCP 埠:
x = ip_essay-header_length
port = *(packet_start + x + port_offset)
(看起來不一樣,其實它們基本上都相同)。在這個論文/幻燈片上有一個非常詳細的虛擬機器的描述,因此,我不打算解釋它。
當你執行 tcpdump host foo
後,這時發生了什麼?就我的理解,應該是如下的過程。
host foo
為一個高效的 DAG 規則現狀:eBPF
畢竟 BPF 出現已經有很長的時間了!現在,我們可以擁有一個更加令人激動的東西,它就是 eBPF。我以前聽說過 eBPF,但是,我覺得像這樣把這些片斷拼在一起更好(我在 4 月份的 netdev 上我寫了這篇 XDP & eBPF 的文章[8]回覆)
關於 eBPF 的一些事實是:
bpf
系統呼叫kprobes 和 eBPF
你可以在 Linux 核心中挑選一個函式(任意函式),然後執行一個你寫的每次該函式被呼叫時都執行的程式。這樣看起來是不是很神奇。
例如:這裡有一個 名為 disksnoop 的 BPF 程式[9],它的功能是當你開始/完成寫入一個塊到磁碟時,觸發它執行跟蹤。下圖是它的程式碼片斷:
BPF_HASH(start, struct request *);
void trace_start(struct pt_regs *ctx, struct request *req) {
// stash start timestamp by request ptr
u64 ts = bpf_ktime_get_ns();
start.update(&req, &ts);
}
...
b.attach_kprobe(event="blk_start_request", fn_name="trace_start")
b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_start")
本質上它宣告一個 BPF 雜湊(它的作用是當請求開始/完成時,這個程式去觸發跟蹤),一個名為 trace_start
的函式將被編譯進 BPF 位元組碼,然後附加 trace_start
到核心函式 blk_start_request
上。
這裡使用的是 bcc
框架,它可以讓你寫 Python 式的程式去生成 BPF 程式碼。你可以在 https://github.com/iovisor/bcc 找到它(那裡有非常多的示例程式)。
uprobes 和 eBPF
因為我知道可以附加 eBPF 程式到核心函式上,但是,我不知道能否將 eBPF 程式附加到使用者空間函式上!那會有更多令人激動的事情。這是 在 Python 中使用一個 eBPF 程式去計數 malloc 呼叫的示例[11]。
附加 eBPF 程式時應該考慮的事情
這個討論超級棒
在幻燈片裡有很多非常好的連結,並且在 iovisor 倉庫裡有個 LINKS.md[15]。雖然現在已經很晚了,但是我馬上要去寫我的第一個 eBPF 程式了!
via: https://jvns.ca/blog/2017/06/28/notes-on-bpf---ebpf/
作者:Julia Evans [17] 譯者:qhwdw 校對:wxy
本文由 LCTT 原創編譯,Linux中國 榮譽推出