bpf 指令集

bpf 指令用于过滤逻辑 (filter program) 是有一个指令数组表示。

只有向前跳转

ret指令结束过滤

每一个指令操作 bpf虚拟机的内部状态

包括

累加器:accumulator,

指示器:index register,

bpf内存:memory store,

pc 程序指针: program counter.

指令格式

/*
 * The instruction data structure.
 */
struct bpf_insn {
    u_short    code;    /* 16bit  这条指令做什么 */
    u_char     jt; /* jump if true  如果为真 跳转的位置 */
    u_char     jf; /* jump if false  如果为假 跳转的位置 */
    bpf_int32 k; // int
};

所有的指令分为8类:

BPF_LD, BPF_LDX加载指令

BPF_ST, BPF_STX存储指令

BPF_ALU, 计算指令

BPF_JMP, 跳转指令

BPF_RET, 返回指令 (结束指令)

BPF_MISC, 其他指令

内存大小: BPF_MEMWORDS  ==> 16

1) load指令

BPF_LD 9条指令

BPF_LD+BPF_W+BPF_ABS
A <- P[k:4] (p是报文首地址, k是一个立即数, A 是累计器)

BPF_LD+BPF_H+BPF_ABS
A <- P[k:2]

BPF_LD+BPF_B+BPF_ABS

ldh      [12] ===> 标识加载报文的偏移12个字节的 hardword(也就是16bit) 以太网报文头 6bytes的源mac+6位目的mac 之后就是ethetype 上层协议

ethetype: ip #800

9c 21 6a 95 3f ac 84 34  97 94 03 ef 【08 00】 45 00 (ip 协议)

BPF_LD+BPF_W+BPF_IND
A <- P[X+k:4] (X 是指示器)

BPF_LD+BPF_H+BPF_IND
A <- P[X+k:2]

BPF_LD+BPF_B+BPF_IND
A <- P[X+k:1]

BPF_LD+BPF_W+BPF_LEN
A <- len (len是报文的长度)

BPF_LD+BPF_IMM
A <- k (器存器的值是 k)

BPF_LD+BPF_MEM
A <- M[k] (把内存的第k个字(word 4byte) 的值赋值到累加器中 )

LDX(X = index :指示器) 4 调指令

BPF_LDX+BPF_W+BPF_IMM
X <- k (把k值加载到指示器)

BPF_LDX+BPF_W+BPF_MEM
X <- M[k] (加载内存值到指示器)

BPF_LDX+BPF_W+BPF_LEN
X <- len (加载报文长度到 指示器中)

BPF_LDX+BPF_B+BPF_MSH
X <- 4*(P[k:1]&0xf) (加载ip头部长度到指示器中)

45 00 00 3c 47 c0 40 00 40 06  0a 95 c0 a8 01 0b 其中0x5 表示ip头长度字段 实际长度是 5*4=20byte的ip头

BPF_ST 保存指令

BPF_ST
M[k] <- A 所有保存值到内存都通过 累加器 所有很简单的指令

BPF_STX (保存指示器的值到内存中)
M[k] <- X

BPF_ALU

操作数 累加器, 指示器, 常量

BPF_ALU+BPF_ADD+BPF_K 操作立即数 k
A <- A + k

BPF_ALU+BPF_SUB+BPF_K
A <- A - k

BPF_ALU+BPF_MUL+BPF_K
A <- A * k

BPF_ALU+BPF_DIV+BPF_K
A <- A / k

BPF_ALU+BPF_AND+BPF_K
A <- A & k

BPF_ALU+BPF_OR+BPF_K
A <- A | k

BPF_ALU+BPF_LSH+BPF_K
A <- A << k

BPF_ALU+BPF_RSH+BPF_K
A <- A >> k

BPF_ALU+BPF_ADD+BPF_X 操作指示器X
A <- A + X

BPF_ALU+BPF_SUB+BPF_X
A <- A - X

BPF_ALU+BPF_MUL+BPF_X
A <- A * X

BPF_ALU+BPF_DIV+BPF_X
A <- A / X

BPF_ALU+BPF_AND+BPF_X
A <- A & X

BPF_ALU+BPF_OR+BPF_X
A <- A | X

BPF_ALU+BPF_LSH+BPF_X
A <- A << X

BPF_ALU+BPF_RSH+BPF_X
A <- A >> X

BPF_ALU+BPF_NEG 取负指令
A <- -A

BPF_JMP 跳转指令
操作数是无符号的
条件跳转 jt jf 只有8bit 最远是255的偏移
无条件跳转可跳32bit的数

BPF_JMP+BPF_JA
pc += k (跳转到下k调指令处)

BPF_JMP+BPF_JA
pc += k

BPF_JMP+BPF_JGT+BPF_K
pc += (A > k) ? jt : jf

BPF_JMP+BPF_JGE+BPF_K
pc += (A >= k) ? jt : jf

BPF_JMP+BPF_JEQ+BPF_K
pc += (A == k) ? jt : jf

BPF_JMP+BPF_JSET+BPF_K
pc += (A & k) ? jt : jf

BPF_JMP+BPF_JGT+BPF_X
pc += (A > X) ? jt : jf

BPF_JMP+BPF_JGE+BPF_X
pc += (A >= X) ? jt : jf

BPF_JMP+BPF_JEQ+BPF_X
pc += (A == X) ? jt : jf

BPF_JMP+BPF_JSET+BPF_X
pc += (A & X) ? jt : jf

返回指令

如果返回0 表示忽略此报文

BPF_RET+BPF_A
accept A bytes

BPF_RET+BPF_K
accept k bytes

BPF_MISC+BPF_TAX (t = transfer
X <- A (累加器的值 赋给 指示器)

BPF_MISC+BPF_TXA
A <- X

原文地址:https://www.cnblogs.com/kwingmei/p/3629668.html