1 Linux 實現注意事項¶
本文件提供了 eBPF 指令集在 Linux 核心中實現的更多具體細節。
1.1 位元組交換指令¶
BPF_FROM_LE 和 BPF_FROM_BE 分別作為 BPF_TO_LE 和 BPF_TO_BE 的別名存在。
1.2 跳轉指令¶
BPF_CALL | BPF_X | BPF_JMP (0x8d),其中輔助函式整數將從指定暫存器中讀取,目前不受驗證器支援。任何包含此指令的程式都將無法載入,直到新增此類支援為止。
1.3 對映¶
Linux 只支援對包含單個元素的陣列對映執行 'map_val(map)' 操作。
Linux 使用 fd_array 來儲存與 BPF 程式關聯的對映。因此,map_by_idx(imm) 使用該陣列中該索引處的 fd。
1.4 變數¶
以下 64 位即時指令指定應載入一個變數地址,該地址對應於 ‘imm’ 欄位中儲存的某個整數
操作碼結構 |
操作碼 |
源 |
虛擬碼 |
imm 型別 |
dst 型別 |
|---|---|---|---|---|---|
BPF_IMM | BPF_DW | BPF_LD |
0x18 |
0x3 |
dst = var_addr(imm) |
變數 ID |
資料指標 |
在 Linux 上,此整數是一個 BTF ID。
1.5 傳統 BPF 資料包訪問指令¶
如 ISA 標準文件中所述,Linux 具有特殊的 eBPF 指令,用於訪問資料包資料,這些指令是從經典 BPF 繼承而來的,旨在保留在 eBPF 直譯器中執行的傳統套接字過濾器的效能。
這些指令有兩種形式:BPF_ABS | <size> | BPF_LD 和 BPF_IND | <size> | BPF_LD。
這些指令用於訪問資料包資料,並且只能在程式上下文是指向網路資料包的指標時使用。BPF_ABS 訪問由立即資料指定的絕對偏移處的資料包資料,而 BPF_IND 訪問資料包資料時,其偏移量除了立即資料外還包括一個暫存器的值。
這些指令有七個隱式運算元
暫存器 R6 是一個隱式輸入,它必須包含指向
struct sk_buff的指標。暫存器 R0 是一個隱式輸出,其中包含從資料包中獲取的資料。
暫存器 R1-R5 是被指令覆蓋的暫存暫存器。
這些指令也帶有一個隱式的程式退出條件。如果 eBPF 程式試圖訪問超出資料包邊界的資料,程式執行將被中止。
BPF_ABS | BPF_W | BPF_LD (0x20) 意味著
R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + imm))
其中 ntohl() 將 32 位值從網路位元組序轉換為主機位元組序。
BPF_IND | BPF_W | BPF_LD (0x40) 意味著
R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + src + imm))