2 * bpfcmd.h -- Berkeley Packet Filter (ish) command set.
4 * This defines a virtual machine which is based on the BPF
5 * machine, as that is very suitable for taking apart packets,
6 * storing juicy parts on a scratchpad, and finally deciding
9 * The implementation, although inspired on the original
10 * BPF code, is a full reimplementation, mainly because the
11 * purpose is different: We want to generate code that is
12 * as efficient as possible, and that can be overridden
13 * locally by code that generates real assembler instructions
14 * optimised for a particular target platform.
16 * From: Rick van Rein <rick@openfortress.nl>
21 /* Enable overriding per target, if so desired. This supports
22 * direct translation of these instructions into real assembler,
23 * fit for very fast execution of these vital bits of network
24 * code. The utility of this code is that it is simple and is
25 * a delay in the actual handling of the network packet. The
26 * BPF setup is geared towards efficiency, although the added
27 * value of this implementation is even better -- compile-time
28 * translation into real machine instructions at the expense of
29 * the flexibility that BPF needs but that we can live without.
31 * All data is stored in network byte order. For some machines,
32 * that implies conversions. The commands below do as much of
33 * these conversions on constants, counting on a clever compiler
34 * to precalculate it before it turns into code.
37 #ifdef HAVE_BPF_ASM_INLINES
38 #include <asm/bpfcmd.h>
42 /* The following functions mark the structure of a program:
51 * uint32_t memspace [20];
53 * uint32_t pktlen = ...;
54 * uint32_t outcome = selhdr (pkt, pktlen, memspace);
59 #define BPF_BEGIN(fname) intptr_t fname (uint8_t *P, uint32_t L, uint32_t *M) { register uint32_t A, X=htonl ((uint32_t) P), S; register int k;
60 #define BPF_LABEL(l) l:
62 #define BPF_TAIL(fname) return (fname) (P, L, M);
65 /* Opcodes and their meaning:
67 * LDB_ load byte and expand into accu A, unsigned
68 * LDH_ load halfword and expand into accu A, unsigned
69 * LDW_ load word into accu A
70 * LDX_ load word into indexreg X
71 * STB_ store byte from accu A
72 * STH_ store halfword from accu A
74 * STX_ store indexreg X
77 * JNE_ jump on not equal
78 * JGT_ jump on greater
79 * JGE_ jump on greater or equal
81 * JLE_ jump on less or equal
82 * JMN_ jump on nonzero after masking
83 * JMZ_ jump on zero after masking
85 * SUB_ subtract from accu A
86 * MUL_ multiply into accu A
87 * DIV_ divide accu A by
88 * AND_ bitwise and with accu A
89 * IOR_ bitwise inclusive or with accu A
90 * LSH_ left shift accu A
91 * RSH_ right shift accu A
92 * RET_ return value (finish program)
94 * Note: TAX is renamed to LDX_ACC, TXA is renamed to LDW_REX
99 * _IDX k [X+k] (X not shown as an operand)
101 * _LEN #len (not shown as an operand)
102 * _MEM k M[k] (M not shown as an operand)
103 * _ACC A (not shown as an operand)
104 * _TOP A (not shown, top half is used)
105 * _REX X (not shown as an operand)
107 * _IP4 4*([k]&0x0f) (not used in this phone)
108 * _SUM S (not shown as an operand)
111 * Commands XOR_ STH_ STB_ SUM_ CLR_
113 * Combinations ST*_PKT ST*_IDX
118 /* A few utility macros */
120 #define BPF_GET32(a,o) htonl ( (((uint8_t *)a)[o+0] << 24) | (((uint8_t *)a)[o+1] << 16) | (((uint8_t *)a)[o+2] << 8) | ((uint8_t *)a)[o+3] )
121 #define BPF_GET16(a,o) htonl ( (((uint8_t *)a)[o+0] << 8) | ((uint8_t *)a)[o+1] )
122 #define BPF_GET08(a,o) htonl ( ((uint8_t *)a)[o+0] )
124 #define BPF_PUT32(a,o,v) ((uint8_t *)a)[o+0] = ((v) >> 24) & 0xff; \
125 ((uint8_t *)a)[o+1] = ((v) >> 16) & 0xff; \
126 ((uint8_t *)a)[o+2] = ((v) >> 8) & 0xff; \
127 ((uint8_t *)a)[o+3] = ((v) ) & 0xff;
128 #define BPF_PUT16(a,o,v) ((uint8_t *)a)[o+0] = ((v) >> 8) & 0xff; \
129 ((uint8_t *)a)[o+1] = ((v) ) & 0xff;
130 #define BPF_PUT08(a,o,v) ((uint8_t *)a)[o+0] = ((v) ) & 0xff;
133 /* Instruction macros. These can be overridden by
134 * real assembly instructions for a particular target
135 * platform if HAVE_BPF_ASM_INLINES is defined for it.
137 * TODO: Handle _PKT mode boundaries? How about _IDX?
142 # define DEBUG_REGS printf ("%d: A=%08X X=%08X\n", __LINE__, htonl (A), htonl (X))
143 # define DEBUG_REGS_PLUS printf ("%d: A=%08X X=%08X, S=%08X\n", __LINE__, htonl (A), htonl (X), S)
146 # define DEBUG_REGS_PLUS
149 #define RET_LIT(k) return (uint32_t) (k); DEBUG_REGS;
150 #define RET_ACC() return A; DEBUG_REGS;
151 #define LDW_PKT(k) A = BPF_GET32 (P, (k)); DEBUG_REGS;
152 #define LDH_PKT(k) A = BPF_GET16 (P, (k)); DEBUG_REGS;
153 #define LDB_PKT(k) A = BPF_GET08 (P, (k)); DEBUG_REGS;
154 #define LDW_LEN() A = htonl (L); DEBUG_REGS;
155 #define LDX_LIT(k) X = htonl (k); DEBUG_REGS;
156 #define LDX_LEN() X = htonl (L); DEBUG_REGS;
157 #define LDW_IDX(k) A = BPF_GET32 (ntohl(X), (k)); DEBUG_REGS;
158 #define STW_IDX(k) BPF_PUT32 (ntohl(X), (k), ntohl (A)); DEBUG_REGS;
159 #define LDH_IDX(k) A = BPF_GET16 (ntohl(X), (k)); DEBUG_REGS;
160 #define STH_IDX(k) BPF_PUT16 (ntohl(X), (k), ntohl (A)); DEBUG_REGS;
161 #define LDB_IDX(k) A = BPF_GET08 (ntohl(X), (k)); DEBUG_REGS;
162 #define STB_IDX(k) BPF_PUT08 (ntohl(X), (k), ntohl (A)); DEBUG_REGS;
163 #define LDX_IP4(k) A = (P [k] & 0x0f) << 2; DEBUG_REGS;
164 #define LDW_LIT(k) A = htonl ((k) & 0xffffffff); DEBUG_REGS;
165 #define LDH_LIT(k) A = htonl ((k) & 0x0000ffff); DEBUG_REGS;
166 #define LDB_LIT(k) A = htonl ((k) & 0x000000ff); DEBUG_REGS;
167 #define LDW_MEM(k) A = htonl (M[k]); DEBUG_REGS;
168 #define LDX_MEM(k) X = htonl (M[k]); DEBUG_REGS;
169 #define STW_MEM(k) M[k] = ntohl (A); DEBUG_REGS;
170 #define STX_MEM(k) M[k] = ntohl (X); DEBUG_REGS;
171 #define JMP_ALW(t) goto t; DEBUG_REGS;
172 #define JGT_LIT(k,t) if (ntohl(A) > (k)) goto t; DEBUG_REGS;
173 #define JGE_LIT(k,t) if (ntohl(A) >= (k)) goto t; DEBUG_REGS;
174 #define JLT_LIT(k,t) if (ntohl(A) < (k)) goto t; DEBUG_REGS;
175 #define JLE_LIT(k,t) if (ntohl(A) <= (k)) goto t; DEBUG_REGS;
176 #define JEQ_LIT(k,t) if (ntohl(A) == (k)) goto t; DEBUG_REGS;
177 #define JNE_LIT(k,t) if (ntohl(A) != (k)) goto t; DEBUG_REGS;
178 #define JMN_LIT(k,t) if ((ntohl(A) & (k)) != 0) goto t; DEBUG_REGS;
179 #define JMZ_LIT(k,t) if ((ntohl(A) & (k)) == 0) goto t; DEBUG_REGS;
180 #define ADD_REX() A = htonl (ntohl (A) + ntohl (X)); DEBUG_REGS;
181 #define SUB_REX() A = htonl (ntohl (A) - ntohl (X)); DEBUG_REGS;
182 #define MUL_REX() A = htonl (ntohl (A) * ntohl (X)); DEBUG_REGS;
183 #define DIV_REX() if (X == 0) return 0; A = htonl (ntohl (A) / ntohl (X)); \
185 #define AND_REX() A = A & X; DEBUG_REGS;
186 #define IOR_REX() A = A | X; DEBUG_REGS;
187 #define XOR_REX() A = A ^ X; DEBUG_REGS;
188 #define LSH_REX() A = htonl (ntohl (A) << ntohl (X)); DEBUG_REGS;
189 #define RSH_REX() A = htonl (ntohl (A) >> ntohl (X)); DEBUG_REGS;
190 #define ADD_LIT(k) A = htonl (ntohl (A) + (k)); DEBUG_REGS;
191 #define SUB_LIT(k) A = htonl (ntohl (A) - (k)); DEBUG_REGS;
192 #define MUL_LIT(k) A = htonl (ntohl (A) * (k)); DEBUG_REGS;
193 #define DIV_LIT(k) if ((k) == 0) return 0; A = htonl (ntohl (A) / (k)); \
195 #define AND_LIT(k) A = A & htonl ((k)); DEBUG_REGS;
196 #define IOR_LIT(k) A = A | htonl ((k)); DEBUG_REGS;
197 #define XOR_LIT(k) A = A ^ htonl ((k)); DEBUG_REGS;
198 #define LSH_LIT(k) A = htonl (ntohl (A) << (k)) DEBUG_REGS;
199 #define RSH_LIT(k) A = htonl (ntohl (A) >> (k)) DEBUG_REGS;
200 #define NEG_ACC() A = htonl (-ntohl (A)) DEBUG_REGS;
201 #define LDX_ACC() X = A; DEBUG_REGS;
202 #define LDW_REX() A = A; DEBUG_REGS;
203 #define SUM_PKT(k) S += ntohl (BPF_GET16 (P, (k))); DEBUG_REGS_PLUS;
204 #define SUM_IDX(k) S += ntohl (BPF_GET16 (ntohl(X), (k))); DEBUG_REGS_PLUS;
205 #define SUM_ACC() S += ntohl (A) & 0xffff; DEBUG_REGS_PLUS;
206 #define SUM_TOP() S += ntohl (A) >> 16; DEBUG_REGS_PLUS;
207 #define LDH_SUM() printf ("S_pre = %08x\n", S); S = ((S & 0xffff) + (S >> 16)) & 0xffff; A = htonl (S) ^ 0xffff; printf ("S_post= %08x\n", S); \
209 #define CLR_SUM() S = 0; DEBUG_REGS_PLUS;
212 #endif // HAVE_BPF_ASM_INLINES