]>
Commit | Line | Data |
---|---|---|
1d129d19 | 1 | /* |
e4225669 | 2 | * bpf_util.h BPF common code |
1d129d19 JP |
3 | * |
4 | * This program is free software; you can distribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * as published by the Free Software Foundation; either version | |
7 | * 2 of the License, or (at your option) any later version. | |
8 | * | |
e4225669 | 9 | * Authors: Daniel Borkmann <daniel@iogearbox.net> |
1d129d19 JP |
10 | * Jiri Pirko <jiri@resnulli.us> |
11 | */ | |
12 | ||
e4225669 DB |
13 | #ifndef __BPF_UTIL__ |
14 | #define __BPF_UTIL__ | |
1d129d19 | 15 | |
11c39b5e | 16 | #include <linux/bpf.h> |
f823f360 | 17 | #include <linux/btf.h> |
e4225669 | 18 | #include <linux/filter.h> |
32e93fb7 | 19 | #include <linux/magic.h> |
e4225669 DB |
20 | #include <linux/elf-em.h> |
21 | #include <linux/if_alg.h> | |
11c39b5e DB |
22 | |
23 | #include "utils.h" | |
4bd62446 | 24 | #include "bpf_scm.h" |
11c39b5e | 25 | |
88eea539 | 26 | #define BPF_ENV_UDS "TC_BPF_UDS" |
32e93fb7 | 27 | #define BPF_ENV_MNT "TC_BPF_MNT" |
88eea539 | 28 | |
afc1a200 DB |
29 | #ifndef BPF_MAX_LOG |
30 | # define BPF_MAX_LOG 4096 | |
31 | #endif | |
32 | ||
e4225669 DB |
33 | #define BPF_DIR_GLOBALS "globals" |
34 | ||
32e93fb7 DB |
35 | #ifndef BPF_FS_MAGIC |
36 | # define BPF_FS_MAGIC 0xcafe4a11 | |
37 | #endif | |
1d129d19 | 38 | |
32e93fb7 DB |
39 | #define BPF_DIR_MNT "/sys/fs/bpf" |
40 | ||
32e93fb7 DB |
41 | #ifndef TRACEFS_MAGIC |
42 | # define TRACEFS_MAGIC 0x74726163 | |
43 | #endif | |
44 | ||
45 | #define TRACE_DIR_MNT "/sys/kernel/tracing" | |
46 | ||
e4225669 DB |
47 | #ifndef AF_ALG |
48 | # define AF_ALG 38 | |
49 | #endif | |
50 | ||
51 | #ifndef EM_BPF | |
52 | # define EM_BPF 247 | |
53 | #endif | |
54 | ||
55 | struct bpf_cfg_ops { | |
56 | void (*cbpf_cb)(void *nl, const struct sock_filter *ops, int ops_len); | |
57 | void (*ebpf_cb)(void *nl, int fd, const char *annotation); | |
58 | }; | |
59 | ||
f20ff2f1 JK |
60 | enum bpf_mode { |
61 | CBPF_BYTECODE, | |
62 | CBPF_FILE, | |
63 | EBPF_OBJECT, | |
64 | EBPF_PINNED, | |
65 | BPF_MODE_MAX, | |
66 | }; | |
67 | ||
e4225669 DB |
68 | struct bpf_cfg_in { |
69 | const char *object; | |
70 | const char *section; | |
71 | const char *uds; | |
658cfebc | 72 | enum bpf_prog_type type; |
f20ff2f1 | 73 | enum bpf_mode mode; |
65fdae3d | 74 | __u32 ifindex; |
3f0b9e62 | 75 | bool verbose; |
e4225669 DB |
76 | int argc; |
77 | char **argv; | |
51be7546 | 78 | struct sock_filter opcodes[BPF_MAXINSNS]; |
3f0b9e62 JK |
79 | union { |
80 | int n_opcodes; | |
81 | int prog_fd; | |
82 | }; | |
e4225669 DB |
83 | }; |
84 | ||
10e51a76 DA |
85 | /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */ |
86 | ||
87 | #define BPF_ALU64_REG(OP, DST, SRC) \ | |
88 | ((struct bpf_insn) { \ | |
89 | .code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \ | |
90 | .dst_reg = DST, \ | |
91 | .src_reg = SRC, \ | |
92 | .off = 0, \ | |
93 | .imm = 0 }) | |
94 | ||
95 | #define BPF_ALU32_REG(OP, DST, SRC) \ | |
96 | ((struct bpf_insn) { \ | |
97 | .code = BPF_ALU | BPF_OP(OP) | BPF_X, \ | |
98 | .dst_reg = DST, \ | |
99 | .src_reg = SRC, \ | |
100 | .off = 0, \ | |
101 | .imm = 0 }) | |
102 | ||
103 | /* ALU ops on immediates, bpf_add|sub|...: dst_reg += imm32 */ | |
104 | ||
105 | #define BPF_ALU64_IMM(OP, DST, IMM) \ | |
106 | ((struct bpf_insn) { \ | |
107 | .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ | |
108 | .dst_reg = DST, \ | |
109 | .src_reg = 0, \ | |
110 | .off = 0, \ | |
111 | .imm = IMM }) | |
112 | ||
113 | #define BPF_ALU32_IMM(OP, DST, IMM) \ | |
114 | ((struct bpf_insn) { \ | |
115 | .code = BPF_ALU | BPF_OP(OP) | BPF_K, \ | |
116 | .dst_reg = DST, \ | |
117 | .src_reg = 0, \ | |
118 | .off = 0, \ | |
119 | .imm = IMM }) | |
120 | ||
121 | /* Short form of mov, dst_reg = src_reg */ | |
122 | ||
123 | #define BPF_MOV64_REG(DST, SRC) \ | |
124 | ((struct bpf_insn) { \ | |
125 | .code = BPF_ALU64 | BPF_MOV | BPF_X, \ | |
126 | .dst_reg = DST, \ | |
127 | .src_reg = SRC, \ | |
128 | .off = 0, \ | |
129 | .imm = 0 }) | |
130 | ||
131 | #define BPF_MOV32_REG(DST, SRC) \ | |
132 | ((struct bpf_insn) { \ | |
133 | .code = BPF_ALU | BPF_MOV | BPF_X, \ | |
134 | .dst_reg = DST, \ | |
135 | .src_reg = SRC, \ | |
136 | .off = 0, \ | |
137 | .imm = 0 }) | |
138 | ||
139 | /* Short form of mov, dst_reg = imm32 */ | |
140 | ||
141 | #define BPF_MOV64_IMM(DST, IMM) \ | |
142 | ((struct bpf_insn) { \ | |
143 | .code = BPF_ALU64 | BPF_MOV | BPF_K, \ | |
144 | .dst_reg = DST, \ | |
145 | .src_reg = 0, \ | |
146 | .off = 0, \ | |
147 | .imm = IMM }) | |
148 | ||
149 | #define BPF_MOV32_IMM(DST, IMM) \ | |
150 | ((struct bpf_insn) { \ | |
151 | .code = BPF_ALU | BPF_MOV | BPF_K, \ | |
152 | .dst_reg = DST, \ | |
153 | .src_reg = 0, \ | |
154 | .off = 0, \ | |
155 | .imm = IMM }) | |
156 | ||
157 | /* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ | |
158 | #define BPF_LD_IMM64(DST, IMM) \ | |
159 | BPF_LD_IMM64_RAW(DST, 0, IMM) | |
160 | ||
161 | #define BPF_LD_IMM64_RAW(DST, SRC, IMM) \ | |
162 | ((struct bpf_insn) { \ | |
163 | .code = BPF_LD | BPF_DW | BPF_IMM, \ | |
164 | .dst_reg = DST, \ | |
165 | .src_reg = SRC, \ | |
166 | .off = 0, \ | |
167 | .imm = (__u32) (IMM) }), \ | |
168 | ((struct bpf_insn) { \ | |
169 | .code = 0, /* zero is reserved opcode */ \ | |
170 | .dst_reg = 0, \ | |
171 | .src_reg = 0, \ | |
172 | .off = 0, \ | |
173 | .imm = ((__u64) (IMM)) >> 32 }) | |
174 | ||
175 | #ifndef BPF_PSEUDO_MAP_FD | |
176 | # define BPF_PSEUDO_MAP_FD 1 | |
177 | #endif | |
178 | ||
179 | /* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */ | |
180 | #define BPF_LD_MAP_FD(DST, MAP_FD) \ | |
181 | BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) | |
182 | ||
183 | ||
184 | /* Direct packet access, R0 = *(uint *) (skb->data + imm32) */ | |
185 | ||
186 | #define BPF_LD_ABS(SIZE, IMM) \ | |
187 | ((struct bpf_insn) { \ | |
188 | .code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \ | |
189 | .dst_reg = 0, \ | |
190 | .src_reg = 0, \ | |
191 | .off = 0, \ | |
192 | .imm = IMM }) | |
193 | ||
194 | /* Memory load, dst_reg = *(uint *) (src_reg + off16) */ | |
195 | ||
196 | #define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \ | |
197 | ((struct bpf_insn) { \ | |
198 | .code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \ | |
199 | .dst_reg = DST, \ | |
200 | .src_reg = SRC, \ | |
201 | .off = OFF, \ | |
202 | .imm = 0 }) | |
203 | ||
204 | /* Memory store, *(uint *) (dst_reg + off16) = src_reg */ | |
205 | ||
206 | #define BPF_STX_MEM(SIZE, DST, SRC, OFF) \ | |
207 | ((struct bpf_insn) { \ | |
208 | .code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \ | |
209 | .dst_reg = DST, \ | |
210 | .src_reg = SRC, \ | |
211 | .off = OFF, \ | |
212 | .imm = 0 }) | |
213 | ||
214 | /* Memory store, *(uint *) (dst_reg + off16) = imm32 */ | |
215 | ||
216 | #define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ | |
217 | ((struct bpf_insn) { \ | |
218 | .code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \ | |
219 | .dst_reg = DST, \ | |
220 | .src_reg = 0, \ | |
221 | .off = OFF, \ | |
222 | .imm = IMM }) | |
223 | ||
224 | /* Conditional jumps against registers, if (dst_reg 'op' src_reg) goto pc + off16 */ | |
225 | ||
226 | #define BPF_JMP_REG(OP, DST, SRC, OFF) \ | |
227 | ((struct bpf_insn) { \ | |
228 | .code = BPF_JMP | BPF_OP(OP) | BPF_X, \ | |
229 | .dst_reg = DST, \ | |
230 | .src_reg = SRC, \ | |
231 | .off = OFF, \ | |
232 | .imm = 0 }) | |
233 | ||
234 | /* Conditional jumps against immediates, if (dst_reg 'op' imm32) goto pc + off16 */ | |
235 | ||
236 | #define BPF_JMP_IMM(OP, DST, IMM, OFF) \ | |
237 | ((struct bpf_insn) { \ | |
238 | .code = BPF_JMP | BPF_OP(OP) | BPF_K, \ | |
239 | .dst_reg = DST, \ | |
240 | .src_reg = 0, \ | |
241 | .off = OFF, \ | |
242 | .imm = IMM }) | |
243 | ||
244 | /* Raw code statement block */ | |
245 | ||
246 | #define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \ | |
247 | ((struct bpf_insn) { \ | |
248 | .code = CODE, \ | |
249 | .dst_reg = DST, \ | |
250 | .src_reg = SRC, \ | |
251 | .off = OFF, \ | |
252 | .imm = IMM }) | |
253 | ||
254 | /* Program exit */ | |
255 | ||
256 | #define BPF_EXIT_INSN() \ | |
257 | ((struct bpf_insn) { \ | |
258 | .code = BPF_JMP | BPF_EXIT, \ | |
259 | .dst_reg = 0, \ | |
260 | .src_reg = 0, \ | |
261 | .off = 0, \ | |
262 | .imm = 0 }) | |
263 | ||
4a847fcb JK |
264 | int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops); |
265 | int bpf_load_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops, | |
266 | void *nl); | |
399db839 JK |
267 | int bpf_parse_and_load_common(struct bpf_cfg_in *cfg, |
268 | const struct bpf_cfg_ops *ops, void *nl); | |
e4225669 DB |
269 | |
270 | const char *bpf_prog_to_default_section(enum bpf_prog_type type); | |
6256f8c9 | 271 | |
91d88eeb | 272 | int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv); |
e4225669 | 273 | int bpf_trace_pipe(void); |
4bd62446 | 274 | |
52d57f6b | 275 | void bpf_print_ops(struct rtattr *bpf_ops, __u16 len); |
32e93fb7 | 276 | |
869d889e DA |
277 | int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, |
278 | size_t size_insns, const char *license, char *log, | |
279 | size_t size_log); | |
280 | ||
fc4ccce0 DA |
281 | int bpf_prog_attach_fd(int prog_fd, int target_fd, enum bpf_attach_type type); |
282 | int bpf_prog_detach_fd(int target_fd, enum bpf_attach_type type); | |
283 | ||
a0b5b7cf | 284 | int bpf_dump_prog_info(FILE *f, uint32_t id); |
779525cd | 285 | |
32e93fb7 | 286 | #ifdef HAVE_ELF |
4bd62446 DB |
287 | int bpf_send_map_fds(const char *path, const char *obj); |
288 | int bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux, | |
289 | unsigned int entries); | |
11c39b5e | 290 | #else |
4bd62446 | 291 | static inline int bpf_send_map_fds(const char *path, const char *obj) |
6256f8c9 DB |
292 | { |
293 | return 0; | |
294 | } | |
4bd62446 DB |
295 | |
296 | static inline int bpf_recv_map_fds(const char *path, int *fds, | |
297 | struct bpf_map_aux *aux, | |
298 | unsigned int entries) | |
299 | { | |
300 | return -1; | |
301 | } | |
11c39b5e | 302 | #endif /* HAVE_ELF */ |
e4225669 | 303 | #endif /* __BPF_UTIL__ */ |