Packet Sniffer SDK VCL Edition

BPF instructions

 Previous Next

Below there are the semantics for each defined BPF instruction, where: A - the accumulator, X - the index register, P[...] - packet data, and M[...] - the scratch memory store.

P[i:n]

gives the data at byte offset i in the packet, interpreted as a word (n=4), unsigned halfword (n=2), or unsigned byte (n=1).

M[i]

gives the i'th word in the scratch memory store, which is only addressed in word units. The memory store is indexed from 0 to BPF_MEMWORDS-1.

k, jt, and jf

are the corresponding fields in the instruction definition.

#pktlen

pseudovariable containing the length of the packet.

In all instructions of the BPF Assembler, which are used in BPF programs compiled by HNUserFilter.CompileBPFAsmFromStr and HNUserFilter.CompileBPFAsmFromFile functions, the value of k is a number, predefined constant, or an arithmetic expression containing numbers, prefefined constants, and symbols '(', ')', '+', '-', '*', and '/'.

Registers names, packets addresses, and scratch memory addresses (A, X, P[...], and M[...]) must be uppercase.

BPF_LD

These instructions copy a value into the accumulator. The type of the source operand is specified by an "addressing mode" and can be a constant (BPF_IMM), packet data at a fixed offset (BPF_ABS), packet data at a variable offset (BPF_IND), the packet length (BPF_LEN), or a word in the scratch memory store (BPF_MEM).

For BPF_IND and BPF_ABS, the data size must be specified as a word (BPF_W), halfword (BPF_H), or byte (BPF_B). The semantics of all the recognized BPF_LD instructions follow.

Numeric value of a command to be used in HNUserFilter.AddCmd and HNUserFilter.AddJmp functionsCommand actionBPF Assembler instruction
BPF_LD+BPF_W+BPF_ABSA <- P[k:4]ld P[k:4]
BPF_LD+BPF_H+BPF_ABSA <- P[k:2]ld P[k:2]
BPF_LD+BPF_B+BPF_ABSA <- P[k:1]ld P[k:1] or ld P[k]
BPF_LD+BPF_W+BPF_INDA <- P[X+k:4]ld P[X+k:4]
BPF_LD+BPF_H+BPF_INDA <- P[X+k:2]ld P[X+k:2]
BPF_LD+BPF_B+BPF_INDA <- P[X+k:1]ld P[X+k:1] or ld P[X+k]
BPF_LD+BPF_W+BPF_LENA <- packet lengthld #pktlen
BPF_LD+BPF_IMMA <- kld k
BPF_LD+BPF_MEMA <- M[k]ld M[k]

BPF_LDX

These instructions load a value into the index register.

Numeric value of a command to be used in HNUserFilter.AddCmd and HNUserFilter.AddJmp functionsCommand actionBPF Assembler instruction
BPF_LDX+BPF_W+BPF_IMMX <- kldx k
BPF_LDX+BPF_W+BPF_MEMX <- M[k]ldx M[k]
BPF_LDX+BPF_W+BPF_LENX <- packet lengthldx #pktlen
BPF_LDX+BPF_B+BPF_MSHX <- 4*(P[k:1]&0xf)ldxm P[k:1] or ldxm P[k]

BPF_ST

This instruction stores the accumulator into the scratch memory.

Numeric value of a command to be used in HNUserFilter.AddCmd and HNUserFilter.AddJmp functionsCommand actionBPF Assembler instruction
BPF_STM[k] <- Ast M[k]

BPF_STX

This instruction stores the index register in the scratch memory store.

Numeric value of a command to be used in HNUserFilter.AddCmd and HNUserFilter.AddJmp functionsCommand actionBPF Assembler instruction
BPF_STXM[k] <- Xstx M[k]

BPF_ALU

The ALU instructions perform operations between the accumulator and index register or constant, and store the result back in the accumulator. For two-operand instructions source mode must be set (BPF_K or BPF_X).

Numeric value of a command to be used in HNUserFilter.AddCmd and HNUserFilter.AddJmp functionsCommand actionBPF Assembler instruction
PF_ALU+BPF_ADD+BPF_KA <- A + kadd k
PF_ALU+BPF_SUB+BPF_KA <- A – ksub k
PF_ALU+BPF_MUL+BPF_KA <- A * kmul k
PF_ALU+BPF_DIV+BPF_KA <- A / kdiv k
PF_ALU+BPF_AND+BPF_KA <- A & kand k
PF_ALU+BPF_OR+BPF_KA <- A | kor k
PF_ALU+BPF_LSH+BPF_KA <- A << klsh k
PF_ALU+BPF_RSH+BPF_KA <- A >> krsh k
PF_ALU+BPF_ADD+BPF_XA <- A + Xadd X
PF_ALU+BPF_SUB+BPF_XA <- A – Xsub X
PF_ALU+BPF_MUL+BPF_XA <- A * Xmul X
PF_ALU+BPF_DIV+BPF_XA <- A / Xdiv X
PF_ALU+BPF_AND+BPF_XA <- A & Xand X
PF_ALU+BPF_OR+BPF_XA <- A | Xor X
PF_ALU+BPF_LSH+BPF_XA <- A << Xlsh X
PF_ALU+BPF_RSH+BPF_XA <- A >> Xrsh X
PF_ALU+BPF_NEGA <- -Aneg

BPF_JMP

The jump instructions alter flow of control. Conditional jumps compare the accumulator against a constant (BPF_K) or the index register (BPF_X). If the result is true (or non-zero), the true branch is taken, otherwise the false branch is taken. Jump offsets are encoded in 8 bits, so the longest jump is 256 instructions. However, unconditional jump (BPF_JA) always uses the 32 bit k field as the offset, allowing far jumps. All conditionals use unsigned jump offsets.

jt (Jump If True) and jf (Jump If False) values are a number or expression with the result value from 0 to 255 jumps forward for all BPF_JMP commands. This value also may contain a label ID of a command we want to jump to. This rule is also effective for the jmp (BPF_JA) k command.

Backward jumps are not allowed.
Numeric value of a command to be used in HNUserFilter.AddCmd and HNUserFilter.AddJmp functionsCommand actionBPF Assembler instruction
BPF_JMP+BPF_JApc += kjmp k
BPF_JMP+BPF_JGT+BPF_Kpc += (A > k) ? jt : jfjg k, jt, jf
BPF_JMP+BPF_JGE+BPF_Kpc += (A >= k) ? jt : jfjge k, jt, jf
BPF_JMP+BPF_JEQ+BPF_Kpc += (A == k) ? jt : jfjeq k, jt, jf
BPF_JMP+BPF_JSET+BPF_Kpc += (A & k) ? jt : jfjset k, jt, jf
BPF_JMP+BPF_JGT+BPF_Xpc += (A > X) ? jt : jfjg X, jt, jf
BPF_JMP+BPF_JGE+BPF_Xpc += (A >= X) ? jt : jfjge X, jt, jf
BPF_JMP+BPF_JEQ+BPF_Xpc += (A == X) ? jt : jfjeq X, jt, jf
BPF_JMP+BPF_JSET+BPF_Xpc += (A & X) ? jt : jfjset X, jt, jf

BPF_RET

The return instructions terminate the filter program and specify the amount of packets to accept (i.e. they return the truncation amount). A return value of zero indicates that the packet should be ignored. The return value is either a constant (BPF_K) or the accumulator (BPF_A).

If a returned value of these commands is greater than 0, this means that this packet must be accepted (1), and specifies the number of the bytes that must be passed to the application (2).

This feature can be used in billing solutions to increase performance, in case the application doesn't need the whole packet and the packet header is enough.

If you want to pass to the application the whole packet, the return value must be equal to -1 (please see also HNPacket.IncPacketSize).

Numeric value of a command to be used in HNUserFilter.AddCmd and HNUserFilter.AddJmp functionsCommand actionBPF Assembler instruction
BPF_RET+BPF_Aaccept A bytesret A
BPF_RET+BPF_Kaccept k bytesret k

BPF_MISC

The miscellaneous category was created for anything that does not fit into the above classes and for any new instructions that might be added. Currently, these are the register transfer instructions that copy the index register to the accumulator or vice versa.

Numeric value of a command to be used in HNUserFilter.AddCmd and HNUserFilter.AddJmp functionsCommand actionBPF Assembler instruction
BPF_MISC+BPF_TAXX <- Atax
BPF_MISC+BPF_TXAA <- Xtxa
BPF_MISC+BPF_HTONLA <- htonl(A)ex_htonl A
BPF_MISC+BPF_HTONSA <- htons(A)ex_htons A
BPF_MISC+BPF_MARK+BPF_AMarks packet with the register A content.ex_mark A
BPF_MISC+BPF_MARK+BPF_XMarks packet with the register X content.ex_mark X
BPF_MISC+BPF_MARK+BPF_KMarks packet with the constant value k.ex_mark k