Linux內核功能eBPF入門學習(一):BPF、eBPF、BCC等基本概念

2020-08-13 16:41:26

Linux內核觀測技術BP

https://www.lijiaocn.com/%E6%8A%80%E5%B7%A7/2019/02/25/ebpf-introduction-1.html

 

目錄

說明

eBPF是kernel 3.15中引入的全新設計,將原先的BPF發展成一個指令集更復雜、應用範圍更廣的「內核虛擬機器」。

eBPF支援在使用者態將C語言編寫的一小段「內核程式碼」注入到內核中執行,注入時要先用llvm編譯得到使用BPF指令集的elf檔案,然後從elf檔案中解析出可以注入內核的部分,最後用bpf_load_program方法完成注入。 使用者態程式和注入到內核中的程式通過共用一個位於內核中map實現通訊。爲了防止注入的程式碼導致內核崩潰,eBPF會對注入的程式碼進行嚴格檢查,拒絕不合格的程式碼的注入。

BCC是一個python庫,實現了map建立、程式碼編譯、解析、注入等操作,使開發人員只需聚焦於用C語言開發要注入的內核程式碼。 文章eBPF簡史從eBPF的前身BPF講起,將eBPF的來龍去脈介紹的很明白,是難得的好文章,建議直接過去閱讀,這裏就不摘抄了。 BPF: the universal in-kernel virtual machine介紹了BPF從網路子系統中的報文複製功能到內核通用虛擬機器eBPF的演變過程。

BPF

BPF是很早就有的內核特性,在內核中將報文「映象」了一份,並用BPF指令檢查映象出來的報文、決定報文的去留,即在1)拋棄報文和2)將其複製到使用者空間之間抉擇。

具體實現就不去瞭解了,BPF好歹設計了一套指令集,雖然比較簡單,但沒有紮實的編譯原理基礎,估計一時半會兒也看不懂,這裏只收集一下相關文件:

  1. The BSD Packet Filter: A New Architecture for User-level Packet Capture
  2. Kernel Documentation:BPF Documentation
  3. Linux Socket Filtering aka Berkeley Packet Filter (BPF)

另外學到了一個新知識,tcpdump使用的libpcap是基於BPF的,在使用tcpdump或者libpcap時傳入的「host 192.168.1.1」、「tcp and port 80」等是過濾表達式

過濾表達式會被編譯成BPF指令,在tcpdump命令後面加上-d參數可以看到:

$ tcpdump -d -i eth0 tcp and port 80
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2	jf 8
(002) ldb      [20]
(003) jeq      #0x6             jt 4	jf 19
(004) ldh      [54]
(005) jeq      #0x50            jt 18	jf 6
(006) ldh      [56]
(007) jeq      #0x50            jt 18	jf 19
(008) jeq      #0x800           jt 9	jf 19
(009) ldb      [23]
(010) jeq      #0x6             jt 11	jf 19
(011) ldh      [20]
(012) jset     #0x1fff          jt 19	jf 13
(013) ldxb     4*([14]&0xf)
(014) ldh      [x + 14]
(015) jeq      #0x50            jt 18	jf 16
(016) ldh      [x + 16]
(017) jeq      #0x50            jt 18	jf 19
(018) ret      #65535
(019) ret      #0

這些BPF指令是在內核中被BPF解釋執行的。

eBPF帶來的新變化

原先的BPF依然支援,用cBPF指代。eBPF全新設計了更豐富的指令集、增加了暫存器,效能大幅提高:

The original patch that added support for eBPF in the 3.15 kernel showed that eBPF was up to four times faster on x86-64 than the old classic BPF (cBPF) implementation for some network filter microbenchmarks, and most were 1.5 times faster.

增加了名爲bpf的系統呼叫,爲使用者態程式提供與內核中的eBPF進行互動的途徑:

int bpf(int cmd, union bpf_attr *attr, unsigned int size);

cmd是eBPF支援的cmd,分爲三類: 操作注入的程式碼、操作用於通訊的map、前兩個操作的混合。

通過eBPF可以做更多的事情,不再僅僅是進行報文複製和過濾,網路方面可以切入到更深的層次,在更「靠前」的階段進行幹預,例如XDP藉助eBPF在報文剛收到的時候就進行幹預,使用XDP(eXpress Data Path)防禦DDoS攻擊

還可以:

  1. 限制進程可以使用的系統呼叫,seccomp;

  2. 輸出內核中的數據,進行內核偵錯、效能分析、呼叫跟蹤;

  3. 偵錯使用者態程式,Userland Statically Defined Tracepoints 

eBPF使用

eBPF是kernel 3.15開始支援的,在kernel 3.17原始碼中獲得了一個單獨的bpf目錄,建議直接使用3.17以及以上版本的內核。下面 下麪這四篇文章可以幫你搭建對eBPF的認知框架:

  1. LWN.net: A thorough introduction to eBPF

  2. LWN.net: An introduction to the BPF Compiler Collection

  3. LWN.net: Some advanced BCC topics

  4. LWN.net: Using user-space tracepoints with BPF

升級內核

見:CentOS7/6內核升級的簡單方法:藉助ELRepo,用yum命令更新內核

eBPF程式碼範例

samples/bpf,暫時沒有找到相關資料,目前以學習bcc的使用爲主,2019-02-25 18:11:40

eBPF程式碼編譯裝載

同上一節。

使用BCC簡化eBPF應用開發過程

BCC首先提供了一個名爲bcc的python庫,簡化了eBPF應用的開發過程,然後它收集大量的eBPF應用,主要是效能分析相關的。 可以直接使用bcc已經收集的命令調查問題(bcc Tutorial),也可以用bcc提供的python庫自己開發eBPF應用(bcc Python Developer Tutorial)。

Kernel版本需要是4.1以上(2019-02-25 18:08:15),並且要安裝kernel-devel,如果沒有安裝kernel-devel,eBPF應用會彙編譯失敗(bcc收集的命令執行時也會出現下面 下麪錯誤):

# execsnoop
chdir(/lib/modules/4.20.12-1.el7.elrepo.x86_64/build): No such file or directory
Traceback (most recent call last):
  File "/usr/share/bcc/tools/execsnoop", line 166, in <module>
    b = BPF(text=bpf_text)
  File "/usr/lib/python2.7/site-packages/bcc/__init__.py", line 318, in __init__
    raise Exception("Failed to compile BPF text")
Exception: Failed to compile BPF text

BCC安裝

直接用yum安裝:

yum install bcc-tools

rpm -ql可以看到所有bcc檔案,tools/目錄中是bcc提供的命令,可以用man檢視對應的手冊,比如man bcc-argdist

$ rpm -ql bcc-tools
/usr/share/bcc
/usr/share/bcc/introspection
/usr/share/bcc/introspection/bps
/usr/share/bcc/tools
/usr/share/bcc/tools/argdist
/usr/share/bcc/tools/bashreadline
/usr/share/bcc/tools/biolatency
...
/usr/share/bcc/tools/doc
/usr/share/bcc/tools/doc/argdist_example.txt
/usr/share/bcc/tools/doc/bashreadline_example.txt
/usr/share/bcc/tools/doc/biolatency_example.txt
/usr/share/bcc/tools/doc/biosnoop_example.txt
...
/usr/share/man/man8/bcc-argdist.8.gz
/usr/share/man/man8/bcc-bashreadline.8.gz
/usr/share/man/man8/bcc-biolatency.8.gz
/usr/share/man/man8/bcc-biosnoop.8.gz
/usr/share/man/man8/bcc-biotop.8.gz

BCC收集的eBPF應用

BCC的命令較多,單開一篇筆記,這篇到此爲止。

參考

  1. 張亦鳴: eBPF 簡史
  2. BCC - Tools for BPF-based Linux IO analysis, networking, monitoring, and more
  3. Kernel Documentation:BPF Documentation
  4. Linux Socket Filtering aka Berkeley Packet Filter (BPF)
  5. The BSD Packet Filter: A New Architecture for User-level Packet Capture
  6. A thorough introduction to eBPF
  7. XDP:eXpress Data Path
  8. How to Upgrade Kernel on CentOS 7
  9. Welcome to the ELRepo Project
  10. CentOS7/6內核升級的簡單方法:藉助ELRepo,用yum命令更新內核
  11. LWN.net: An introduction to the BPF Compiler Collection
  12. samples/bpf
  13. LWN.net: Some advanced BCC topics
  14. LWN.net: Using user-space tracepoints with BPF
  15. Installing BCC
  16. bcc Tutorial
  17. bcc Python Developer Tutorial
  18. BPF: the universal in-kernel virtual machine
  19. 使用XDP(eXpress Data Path)防禦DDoS攻擊