| author | |
| committer | |
| log | 0fa3cfdb4aa04bf92c5d9344cd4d265ccb40e0dc |
| tree | 0fe31975cdd13b41adf998308258604225a86a13 |
| parent | 9605e5363b22874550687f5f96dc6cc8bf462115 |
| signature |
* moved bpf syscall, added some bpf instructions and tests
* had to move bpf out of bits so that a freestanding target could import it
* removed line
* fixed imports4 files changed, 974 insertions(+), 976 deletions(-)
lib/std/os/bits/linux.zig-1| ... | ... | @@ -24,7 +24,6 @@ pub usingnamespace switch (builtin.arch) { |
| 24 | 24 | }; |
| 25 | 25 | |
| 26 | 26 | pub usingnamespace @import("linux/netlink.zig"); |
| 27 | pub const BPF = @import("linux/bpf.zig"); | |
| 28 | 27 | |
| 29 | 28 | const is_mips = builtin.arch.isMIPS(); |
| 30 | 29 |
lib/std/os/bits/linux/bpf.zig deleted-975| ... | ... | @@ -1,975 +0,0 @@ |
| 1 | // SPDX-License-Identifier: MIT | |
| 2 | // Copyright (c) 2015-2020 Zig Contributors | |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | // and substantial portions of the software. | |
| 6 | usingnamespace std.os; | |
| 7 | const std = @import("../../../std.zig"); | |
| 8 | const expectEqual = std.testing.expectEqual; | |
| 9 | const fd_t = std.os.fd_t; | |
| 10 | const pid_t = std.os.pid_t; | |
| 11 | ||
| 12 | // instruction classes | |
| 13 | pub const LD = 0x00; | |
| 14 | pub const LDX = 0x01; | |
| 15 | pub const ST = 0x02; | |
| 16 | pub const STX = 0x03; | |
| 17 | pub const ALU = 0x04; | |
| 18 | pub const JMP = 0x05; | |
| 19 | pub const RET = 0x06; | |
| 20 | pub const MISC = 0x07; | |
| 21 | ||
| 22 | /// 32-bit | |
| 23 | pub const W = 0x00; | |
| 24 | /// 16-bit | |
| 25 | pub const H = 0x08; | |
| 26 | /// 8-bit | |
| 27 | pub const B = 0x10; | |
| 28 | /// 64-bit | |
| 29 | pub const DW = 0x18; | |
| 30 | ||
| 31 | pub const IMM = 0x00; | |
| 32 | pub const ABS = 0x20; | |
| 33 | pub const IND = 0x40; | |
| 34 | pub const MEM = 0x60; | |
| 35 | pub const LEN = 0x80; | |
| 36 | pub const MSH = 0xa0; | |
| 37 | ||
| 38 | // alu fields | |
| 39 | pub const ADD = 0x00; | |
| 40 | pub const SUB = 0x10; | |
| 41 | pub const MUL = 0x20; | |
| 42 | pub const DIV = 0x30; | |
| 43 | pub const OR = 0x40; | |
| 44 | pub const AND = 0x50; | |
| 45 | pub const LSH = 0x60; | |
| 46 | pub const RSH = 0x70; | |
| 47 | pub const NEG = 0x80; | |
| 48 | pub const MOD = 0x90; | |
| 49 | pub const XOR = 0xa0; | |
| 50 | ||
| 51 | // jmp fields | |
| 52 | pub const JA = 0x00; | |
| 53 | pub const JEQ = 0x10; | |
| 54 | pub const JGT = 0x20; | |
| 55 | pub const JGE = 0x30; | |
| 56 | pub const JSET = 0x40; | |
| 57 | ||
| 58 | //#define BPF_SRC(code) ((code) & 0x08) | |
| 59 | pub const K = 0x00; | |
| 60 | pub const X = 0x08; | |
| 61 | ||
| 62 | pub const MAXINSNS = 4096; | |
| 63 | ||
| 64 | // instruction classes | |
| 65 | /// jmp mode in word width | |
| 66 | pub const JMP32 = 0x06; | |
| 67 | /// alu mode in double word width | |
| 68 | pub const ALU64 = 0x07; | |
| 69 | ||
| 70 | // ld/ldx fields | |
| 71 | /// exclusive add | |
| 72 | pub const XADD = 0xc0; | |
| 73 | ||
| 74 | // alu/jmp fields | |
| 75 | /// mov reg to reg | |
| 76 | pub const MOV = 0xb0; | |
| 77 | /// sign extending arithmetic shift right */ | |
| 78 | pub const ARSH = 0xc0; | |
| 79 | ||
| 80 | // change endianness of a register | |
| 81 | /// flags for endianness conversion: | |
| 82 | pub const END = 0xd0; | |
| 83 | /// convert to little-endian */ | |
| 84 | pub const TO_LE = 0x00; | |
| 85 | /// convert to big-endian | |
| 86 | pub const TO_BE = 0x08; | |
| 87 | pub const FROM_LE = TO_LE; | |
| 88 | pub const FROM_BE = TO_BE; | |
| 89 | ||
| 90 | // jmp encodings | |
| 91 | /// jump != * | |
| 92 | pub const JNE = 0x50; | |
| 93 | /// LT is unsigned, '<' | |
| 94 | pub const JLT = 0xa0; | |
| 95 | /// LE is unsigned, '<=' * | |
| 96 | pub const JLE = 0xb0; | |
| 97 | /// SGT is signed '>', GT in x86 | |
| 98 | pub const JSGT = 0x60; | |
| 99 | /// SGE is signed '>=', GE in x86 | |
| 100 | pub const JSGE = 0x70; | |
| 101 | /// SLT is signed, '<' | |
| 102 | pub const JSLT = 0xc0; | |
| 103 | /// SLE is signed, '<=' | |
| 104 | pub const JSLE = 0xd0; | |
| 105 | /// function call | |
| 106 | pub const CALL = 0x80; | |
| 107 | /// function return | |
| 108 | pub const EXIT = 0x90; | |
| 109 | ||
| 110 | /// Flag for prog_attach command. If a sub-cgroup installs some bpf program, the | |
| 111 | /// program in this cgroup yields to sub-cgroup program. | |
| 112 | pub const F_ALLOW_OVERRIDE = 0x1; | |
| 113 | /// Flag for prog_attach command. If a sub-cgroup installs some bpf program, | |
| 114 | /// that cgroup program gets run in addition to the program in this cgroup. | |
| 115 | pub const F_ALLOW_MULTI = 0x2; | |
| 116 | /// Flag for prog_attach command. | |
| 117 | pub const F_REPLACE = 0x4; | |
| 118 | ||
| 119 | /// If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the verifier | |
| 120 | /// will perform strict alignment checking as if the kernel has been built with | |
| 121 | /// CONFIG_EFFICIENT_UNALIGNED_ACCESS not set, and NET_IP_ALIGN defined to 2. | |
| 122 | pub const F_STRICT_ALIGNMENT = 0x1; | |
| 123 | ||
| 124 | /// If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the verifier will | |
| 125 | /// allow any alignment whatsoever. On platforms with strict alignment | |
| 126 | /// requirements for loads ands stores (such as sparc and mips) the verifier | |
| 127 | /// validates that all loads and stores provably follow this requirement. This | |
| 128 | /// flag turns that checking and enforcement off. | |
| 129 | /// | |
| 130 | /// It is mostly used for testing when we want to validate the context and | |
| 131 | /// memory access aspects of the verifier, but because of an unaligned access | |
| 132 | /// the alignment check would trigger before the one we are interested in. | |
| 133 | pub const F_ANY_ALIGNMENT = 0x2; | |
| 134 | ||
| 135 | /// BPF_F_TEST_RND_HI32 is used in BPF_PROG_LOAD command for testing purpose. | |
| 136 | /// Verifier does sub-register def/use analysis and identifies instructions | |
| 137 | /// whose def only matters for low 32-bit, high 32-bit is never referenced later | |
| 138 | /// through implicit zero extension. Therefore verifier notifies JIT back-ends | |
| 139 | /// that it is safe to ignore clearing high 32-bit for these instructions. This | |
| 140 | /// saves some back-ends a lot of code-gen. However such optimization is not | |
| 141 | /// necessary on some arches, for example x86_64, arm64 etc, whose JIT back-ends | |
| 142 | /// hence hasn't used verifier's analysis result. But, we really want to have a | |
| 143 | /// way to be able to verify the correctness of the described optimization on | |
| 144 | /// x86_64 on which testsuites are frequently exercised. | |
| 145 | /// | |
| 146 | /// So, this flag is introduced. Once it is set, verifier will randomize high | |
| 147 | /// 32-bit for those instructions who has been identified as safe to ignore | |
| 148 | /// them. Then, if verifier is not doing correct analysis, such randomization | |
| 149 | /// will regress tests to expose bugs. | |
| 150 | pub const F_TEST_RND_HI32 = 0x4; | |
| 151 | ||
| 152 | /// When BPF ldimm64's insn[0].src_reg != 0 then this can have two extensions: | |
| 153 | /// insn[0].src_reg: BPF_PSEUDO_MAP_FD BPF_PSEUDO_MAP_VALUE | |
| 154 | /// insn[0].imm: map fd map fd | |
| 155 | /// insn[1].imm: 0 offset into value | |
| 156 | /// insn[0].off: 0 0 | |
| 157 | /// insn[1].off: 0 0 | |
| 158 | /// ldimm64 rewrite: address of map address of map[0]+offset | |
| 159 | /// verifier type: CONST_PTR_TO_MAP PTR_TO_MAP_VALUE | |
| 160 | pub const PSEUDO_MAP_FD = 1; | |
| 161 | pub const PSEUDO_MAP_VALUE = 2; | |
| 162 | ||
| 163 | /// when bpf_call->src_reg == BPF_PSEUDO_CALL, bpf_call->imm == pc-relative | |
| 164 | /// offset to another bpf function | |
| 165 | pub const PSEUDO_CALL = 1; | |
| 166 | ||
| 167 | /// flag for BPF_MAP_UPDATE_ELEM command. create new element or update existing | |
| 168 | pub const ANY = 0; | |
| 169 | /// flag for BPF_MAP_UPDATE_ELEM command. create new element if it didn't exist | |
| 170 | pub const NOEXIST = 1; | |
| 171 | /// flag for BPF_MAP_UPDATE_ELEM command. update existing element | |
| 172 | pub const EXIST = 2; | |
| 173 | /// flag for BPF_MAP_UPDATE_ELEM command. spin_lock-ed map_lookup/map_update | |
| 174 | pub const F_LOCK = 4; | |
| 175 | ||
| 176 | /// flag for BPF_MAP_CREATE command */ | |
| 177 | pub const BPF_F_NO_PREALLOC = 0x1; | |
| 178 | /// flag for BPF_MAP_CREATE command. Instead of having one common LRU list in | |
| 179 | /// the BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list which can | |
| 180 | /// scale and perform better. Note, the LRU nodes (including free nodes) cannot | |
| 181 | /// be moved across different LRU lists. | |
| 182 | pub const BPF_F_NO_COMMON_LRU = 0x2; | |
| 183 | /// flag for BPF_MAP_CREATE command. Specify numa node during map creation | |
| 184 | pub const BPF_F_NUMA_NODE = 0x4; | |
| 185 | /// flag for BPF_MAP_CREATE command. Flags for BPF object read access from | |
| 186 | /// syscall side | |
| 187 | pub const BPF_F_RDONLY = 0x8; | |
| 188 | /// flag for BPF_MAP_CREATE command. Flags for BPF object write access from | |
| 189 | /// syscall side | |
| 190 | pub const BPF_F_WRONLY = 0x10; | |
| 191 | /// flag for BPF_MAP_CREATE command. Flag for stack_map, store build_id+offset | |
| 192 | /// instead of pointer | |
| 193 | pub const BPF_F_STACK_BUILD_ID = 0x20; | |
| 194 | /// flag for BPF_MAP_CREATE command. Zero-initialize hash function seed. This | |
| 195 | /// should only be used for testing. | |
| 196 | pub const BPF_F_ZERO_SEED = 0x40; | |
| 197 | /// flag for BPF_MAP_CREATE command Flags for accessing BPF object from program | |
| 198 | /// side. | |
| 199 | pub const BPF_F_RDONLY_PROG = 0x80; | |
| 200 | /// flag for BPF_MAP_CREATE command. Flags for accessing BPF object from program | |
| 201 | /// side. | |
| 202 | pub const BPF_F_WRONLY_PROG = 0x100; | |
| 203 | /// flag for BPF_MAP_CREATE command. Clone map from listener for newly accepted | |
| 204 | /// socket | |
| 205 | pub const BPF_F_CLONE = 0x200; | |
| 206 | /// flag for BPF_MAP_CREATE command. Enable memory-mapping BPF map | |
| 207 | pub const BPF_F_MMAPABLE = 0x400; | |
| 208 | ||
| 209 | /// These values correspond to "syscalls" within the BPF program's environment | |
| 210 | pub const Helper = enum(i32) { | |
| 211 | unspec, | |
| 212 | map_lookup_elem, | |
| 213 | map_update_elem, | |
| 214 | map_delete_elem, | |
| 215 | probe_read, | |
| 216 | ktime_get_ns, | |
| 217 | trace_printk, | |
| 218 | get_prandom_u32, | |
| 219 | get_smp_processor_id, | |
| 220 | skb_store_bytes, | |
| 221 | l3_csum_replace, | |
| 222 | l4_csum_replace, | |
| 223 | tail_call, | |
| 224 | clone_redirect, | |
| 225 | get_current_pid_tgid, | |
| 226 | get_current_uid_gid, | |
| 227 | get_current_comm, | |
| 228 | get_cgroup_classid, | |
| 229 | skb_vlan_push, | |
| 230 | skb_vlan_pop, | |
| 231 | skb_get_tunnel_key, | |
| 232 | skb_set_tunnel_key, | |
| 233 | perf_event_read, | |
| 234 | redirect, | |
| 235 | get_route_realm, | |
| 236 | perf_event_output, | |
| 237 | skb_load_bytes, | |
| 238 | get_stackid, | |
| 239 | csum_diff, | |
| 240 | skb_get_tunnel_opt, | |
| 241 | skb_set_tunnel_opt, | |
| 242 | skb_change_proto, | |
| 243 | skb_change_type, | |
| 244 | skb_under_cgroup, | |
| 245 | get_hash_recalc, | |
| 246 | get_current_task, | |
| 247 | probe_write_user, | |
| 248 | current_task_under_cgroup, | |
| 249 | skb_change_tail, | |
| 250 | skb_pull_data, | |
| 251 | csum_update, | |
| 252 | set_hash_invalid, | |
| 253 | get_numa_node_id, | |
| 254 | skb_change_head, | |
| 255 | xdp_adjust_head, | |
| 256 | probe_read_str, | |
| 257 | get_socket_cookie, | |
| 258 | get_socket_uid, | |
| 259 | set_hash, | |
| 260 | setsockopt, | |
| 261 | skb_adjust_room, | |
| 262 | redirect_map, | |
| 263 | sk_redirect_map, | |
| 264 | sock_map_update, | |
| 265 | xdp_adjust_meta, | |
| 266 | perf_event_read_value, | |
| 267 | perf_prog_read_value, | |
| 268 | getsockopt, | |
| 269 | override_return, | |
| 270 | sock_ops_cb_flags_set, | |
| 271 | msg_redirect_map, | |
| 272 | msg_apply_bytes, | |
| 273 | msg_cork_bytes, | |
| 274 | msg_pull_data, | |
| 275 | bind, | |
| 276 | xdp_adjust_tail, | |
| 277 | skb_get_xfrm_state, | |
| 278 | get_stack, | |
| 279 | skb_load_bytes_relative, | |
| 280 | fib_lookup, | |
| 281 | sock_hash_update, | |
| 282 | msg_redirect_hash, | |
| 283 | sk_redirect_hash, | |
| 284 | lwt_push_encap, | |
| 285 | lwt_seg6_store_bytes, | |
| 286 | lwt_seg6_adjust_srh, | |
| 287 | lwt_seg6_action, | |
| 288 | rc_repeat, | |
| 289 | rc_keydown, | |
| 290 | skb_cgroup_id, | |
| 291 | get_current_cgroup_id, | |
| 292 | get_local_storage, | |
| 293 | sk_select_reuseport, | |
| 294 | skb_ancestor_cgroup_id, | |
| 295 | sk_lookup_tcp, | |
| 296 | sk_lookup_udp, | |
| 297 | sk_release, | |
| 298 | map_push_elem, | |
| 299 | map_pop_elem, | |
| 300 | map_peek_elem, | |
| 301 | msg_push_data, | |
| 302 | msg_pop_data, | |
| 303 | rc_pointer_rel, | |
| 304 | spin_lock, | |
| 305 | spin_unlock, | |
| 306 | sk_fullsock, | |
| 307 | tcp_sock, | |
| 308 | skb_ecn_set_ce, | |
| 309 | get_listener_sock, | |
| 310 | skc_lookup_tcp, | |
| 311 | tcp_check_syncookie, | |
| 312 | sysctl_get_name, | |
| 313 | sysctl_get_current_value, | |
| 314 | sysctl_get_new_value, | |
| 315 | sysctl_set_new_value, | |
| 316 | strtol, | |
| 317 | strtoul, | |
| 318 | sk_storage_get, | |
| 319 | sk_storage_delete, | |
| 320 | send_signal, | |
| 321 | tcp_gen_syncookie, | |
| 322 | skb_output, | |
| 323 | probe_read_user, | |
| 324 | probe_read_kernel, | |
| 325 | probe_read_user_str, | |
| 326 | probe_read_kernel_str, | |
| 327 | tcp_send_ack, | |
| 328 | send_signal_thread, | |
| 329 | jiffies64, | |
| 330 | _, | |
| 331 | }; | |
| 332 | ||
| 333 | /// a single BPF instruction | |
| 334 | pub const Insn = packed struct { | |
| 335 | code: u8, | |
| 336 | dst: u4, | |
| 337 | src: u4, | |
| 338 | off: i16, | |
| 339 | imm: i32, | |
| 340 | ||
| 341 | /// r0 - r9 are general purpose 64-bit registers, r10 points to the stack | |
| 342 | /// frame | |
| 343 | pub const Reg = packed enum(u4) { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 }; | |
| 344 | const Source = packed enum(u1) { reg, imm }; | |
| 345 | const AluOp = packed enum(u8) { | |
| 346 | add = ADD, | |
| 347 | sub = SUB, | |
| 348 | mul = MUL, | |
| 349 | div = DIV, | |
| 350 | op_or = OR, | |
| 351 | op_and = AND, | |
| 352 | lsh = LSH, | |
| 353 | rsh = RSH, | |
| 354 | neg = NEG, | |
| 355 | mod = MOD, | |
| 356 | xor = XOR, | |
| 357 | mov = MOV, | |
| 358 | }; | |
| 359 | ||
| 360 | pub const Size = packed enum(u8) { | |
| 361 | byte = B, | |
| 362 | half_word = H, | |
| 363 | word = W, | |
| 364 | double_word = DW, | |
| 365 | }; | |
| 366 | ||
| 367 | const JmpOp = packed enum(u8) { | |
| 368 | ja = JA, | |
| 369 | jeq = JEQ, | |
| 370 | jgt = JGT, | |
| 371 | jge = JGE, | |
| 372 | jset = JSET, | |
| 373 | }; | |
| 374 | ||
| 375 | const ImmOrReg = union(Source) { | |
| 376 | imm: i32, | |
| 377 | reg: Reg, | |
| 378 | }; | |
| 379 | ||
| 380 | fn imm_reg(code: u8, dst: Reg, src: anytype, off: i16) Insn { | |
| 381 | const imm_or_reg = if (@typeInfo(@TypeOf(src)) == .EnumLiteral) | |
| 382 | ImmOrReg{ .reg = @as(Reg, src) } | |
| 383 | else | |
| 384 | ImmOrReg{ .imm = src }; | |
| 385 | ||
| 386 | const src_type = switch (imm_or_reg) { | |
| 387 | .imm => K, | |
| 388 | .reg => X, | |
| 389 | }; | |
| 390 | ||
| 391 | return Insn{ | |
| 392 | .code = code | src_type, | |
| 393 | .dst = @enumToInt(dst), | |
| 394 | .src = switch (imm_or_reg) { | |
| 395 | .imm => 0, | |
| 396 | .reg => |r| @enumToInt(r), | |
| 397 | }, | |
| 398 | .off = off, | |
| 399 | .imm = switch (imm_or_reg) { | |
| 400 | .imm => |i| i, | |
| 401 | .reg => 0, | |
| 402 | }, | |
| 403 | }; | |
| 404 | } | |
| 405 | ||
| 406 | fn alu(comptime width: comptime_int, op: AluOp, dst: Reg, src: anytype) Insn { | |
| 407 | const width_bitfield = switch (width) { | |
| 408 | 32 => ALU, | |
| 409 | 64 => ALU64, | |
| 410 | else => @compileError("width must be 32 or 64"), | |
| 411 | }; | |
| 412 | ||
| 413 | return imm_reg(width_bitfield | @enumToInt(op), dst, src, 0); | |
| 414 | } | |
| 415 | ||
| 416 | pub fn mov(dst: Reg, src: anytype) Insn { | |
| 417 | return alu(64, .mov, dst, src); | |
| 418 | } | |
| 419 | ||
| 420 | pub fn add(dst: Reg, src: anytype) Insn { | |
| 421 | return alu(64, .add, dst, src); | |
| 422 | } | |
| 423 | ||
| 424 | fn jmp(op: JmpOp, dst: Reg, src: anytype, off: i16) Insn { | |
| 425 | return imm_reg(JMP | @enumToInt(op), dst, src, off); | |
| 426 | } | |
| 427 | ||
| 428 | pub fn jeq(dst: Reg, src: anytype, off: i16) Insn { | |
| 429 | return jmp(.jeq, dst, src, off); | |
| 430 | } | |
| 431 | ||
| 432 | pub fn stx_mem(size: Size, dst: Reg, src: Reg, off: i16) Insn { | |
| 433 | return Insn{ | |
| 434 | .code = STX | @enumToInt(size) | MEM, | |
| 435 | .dst = @enumToInt(dst), | |
| 436 | .src = @enumToInt(src), | |
| 437 | .off = off, | |
| 438 | .imm = 0, | |
| 439 | }; | |
| 440 | } | |
| 441 | ||
| 442 | pub fn xadd(dst: Reg, src: Reg) Insn { | |
| 443 | return Insn{ | |
| 444 | .code = STX | XADD | DW, | |
| 445 | .dst = @enumToInt(dst), | |
| 446 | .src = @enumToInt(src), | |
| 447 | .off = 0, | |
| 448 | .imm = 0, | |
| 449 | }; | |
| 450 | } | |
| 451 | ||
| 452 | /// direct packet access, R0 = *(uint *)(skb->data + imm32) | |
| 453 | pub fn ld_abs(size: Size, imm: i32) Insn { | |
| 454 | return Insn{ | |
| 455 | .code = LD | @enumToInt(size) | ABS, | |
| 456 | .dst = 0, | |
| 457 | .src = 0, | |
| 458 | .off = 0, | |
| 459 | .imm = imm, | |
| 460 | }; | |
| 461 | } | |
| 462 | ||
| 463 | fn ld_imm_impl1(dst: Reg, src: Reg, imm: u64) Insn { | |
| 464 | return Insn{ | |
| 465 | .code = LD | DW | IMM, | |
| 466 | .dst = @enumToInt(dst), | |
| 467 | .src = @enumToInt(src), | |
| 468 | .off = 0, | |
| 469 | .imm = @intCast(i32, @truncate(u32, imm)), | |
| 470 | }; | |
| 471 | } | |
| 472 | ||
| 473 | fn ld_imm_impl2(imm: u64) Insn { | |
| 474 | return Insn{ | |
| 475 | .code = 0, | |
| 476 | .dst = 0, | |
| 477 | .src = 0, | |
| 478 | .off = 0, | |
| 479 | .imm = @intCast(i32, @truncate(u32, imm >> 32)), | |
| 480 | }; | |
| 481 | } | |
| 482 | ||
| 483 | pub fn ld_map_fd1(dst: Reg, map_fd: fd_t) Insn { | |
| 484 | return ld_imm_impl1(dst, @intToEnum(Reg, PSEUDO_MAP_FD), @intCast(u64, map_fd)); | |
| 485 | } | |
| 486 | ||
| 487 | pub fn ld_map_fd2(map_fd: fd_t) Insn { | |
| 488 | return ld_imm_impl2(@intCast(u64, map_fd)); | |
| 489 | } | |
| 490 | ||
| 491 | pub fn call(helper: Helper) Insn { | |
| 492 | return Insn{ | |
| 493 | .code = JMP | CALL, | |
| 494 | .dst = 0, | |
| 495 | .src = 0, | |
| 496 | .off = 0, | |
| 497 | .imm = @enumToInt(helper), | |
| 498 | }; | |
| 499 | } | |
| 500 | ||
| 501 | /// exit BPF program | |
| 502 | pub fn exit() Insn { | |
| 503 | return Insn{ | |
| 504 | .code = JMP | EXIT, | |
| 505 | .dst = 0, | |
| 506 | .src = 0, | |
| 507 | .off = 0, | |
| 508 | .imm = 0, | |
| 509 | }; | |
| 510 | } | |
| 511 | }; | |
| 512 | ||
| 513 | fn expect_insn(insn: Insn, val: u64) void { | |
| 514 | expectEqual(@bitCast(u64, insn), val); | |
| 515 | } | |
| 516 | ||
| 517 | test "insn bitsize" { | |
| 518 | expectEqual(@bitSizeOf(Insn), 64); | |
| 519 | } | |
| 520 | ||
| 521 | // mov instructions | |
| 522 | test "mov imm" { | |
| 523 | expect_insn(Insn.mov(.r1, 1), 0x00000001000001b7); | |
| 524 | } | |
| 525 | ||
| 526 | test "mov reg" { | |
| 527 | expect_insn(Insn.mov(.r6, .r1), 0x00000000000016bf); | |
| 528 | } | |
| 529 | ||
| 530 | // alu instructions | |
| 531 | test "add imm" { | |
| 532 | expect_insn(Insn.add(.r2, -4), 0xfffffffc00000207); | |
| 533 | } | |
| 534 | ||
| 535 | // ld instructions | |
| 536 | test "ld_abs" { | |
| 537 | expect_insn(Insn.ld_abs(.byte, 42), 0x0000002a00000030); | |
| 538 | } | |
| 539 | ||
| 540 | test "ld_map_fd" { | |
| 541 | expect_insn(Insn.ld_map_fd1(.r1, 42), 0x0000002a00001118); | |
| 542 | expect_insn(Insn.ld_map_fd2(42), 0x0000000000000000); | |
| 543 | } | |
| 544 | ||
| 545 | // st instructions | |
| 546 | test "stx_mem" { | |
| 547 | expect_insn(Insn.stx_mem(.word, .r10, .r0, -4), 0x00000000fffc0a63); | |
| 548 | } | |
| 549 | ||
| 550 | test "xadd" { | |
| 551 | expect_insn(Insn.xadd(.r0, .r1), 0x00000000000010db); | |
| 552 | } | |
| 553 | ||
| 554 | // jmp instructions | |
| 555 | test "jeq imm" { | |
| 556 | expect_insn(Insn.jeq(.r0, 0, 2), 0x0000000000020015); | |
| 557 | } | |
| 558 | ||
| 559 | // other instructions | |
| 560 | test "call" { | |
| 561 | expect_insn(Insn.call(.map_lookup_elem), 0x0000000100000085); | |
| 562 | } | |
| 563 | ||
| 564 | test "exit" { | |
| 565 | expect_insn(Insn.exit(), 0x0000000000000095); | |
| 566 | } | |
| 567 | ||
| 568 | pub const Cmd = extern enum(usize) { | |
| 569 | map_create, | |
| 570 | map_lookup_elem, | |
| 571 | map_update_elem, | |
| 572 | map_delete_elem, | |
| 573 | map_get_next_key, | |
| 574 | prog_load, | |
| 575 | obj_pin, | |
| 576 | obj_get, | |
| 577 | prog_attach, | |
| 578 | prog_detach, | |
| 579 | prog_test_run, | |
| 580 | prog_get_next_id, | |
| 581 | map_get_next_id, | |
| 582 | prog_get_fd_by_id, | |
| 583 | map_get_fd_by_id, | |
| 584 | obj_get_info_by_fd, | |
| 585 | prog_query, | |
| 586 | raw_tracepoint_open, | |
| 587 | btf_load, | |
| 588 | btf_get_fd_by_id, | |
| 589 | task_fd_query, | |
| 590 | map_lookup_and_delete_elem, | |
| 591 | map_freeze, | |
| 592 | btf_get_next_id, | |
| 593 | map_lookup_batch, | |
| 594 | map_lookup_and_delete_batch, | |
| 595 | map_update_batch, | |
| 596 | map_delete_batch, | |
| 597 | link_create, | |
| 598 | link_update, | |
| 599 | link_get_fd_by_id, | |
| 600 | link_get_next_id, | |
| 601 | enable_stats, | |
| 602 | iter_create, | |
| 603 | link_detach, | |
| 604 | _, | |
| 605 | }; | |
| 606 | ||
| 607 | pub const MapType = extern enum(u32) { | |
| 608 | unspec, | |
| 609 | hash, | |
| 610 | array, | |
| 611 | prog_array, | |
| 612 | perf_event_array, | |
| 613 | percpu_hash, | |
| 614 | percpu_array, | |
| 615 | stack_trace, | |
| 616 | cgroup_array, | |
| 617 | lru_hash, | |
| 618 | lru_percpu_hash, | |
| 619 | lpm_trie, | |
| 620 | array_of_maps, | |
| 621 | hash_of_maps, | |
| 622 | devmap, | |
| 623 | sockmap, | |
| 624 | cpumap, | |
| 625 | xskmap, | |
| 626 | sockhash, | |
| 627 | cgroup_storage, | |
| 628 | reuseport_sockarray, | |
| 629 | percpu_cgroup_storage, | |
| 630 | queue, | |
| 631 | stack, | |
| 632 | sk_storage, | |
| 633 | devmap_hash, | |
| 634 | struct_ops, | |
| 635 | ringbuf, | |
| 636 | _, | |
| 637 | }; | |
| 638 | ||
| 639 | pub const ProgType = extern enum(u32) { | |
| 640 | unspec, | |
| 641 | socket_filter, | |
| 642 | kprobe, | |
| 643 | sched_cls, | |
| 644 | sched_act, | |
| 645 | tracepoint, | |
| 646 | xdp, | |
| 647 | perf_event, | |
| 648 | cgroup_skb, | |
| 649 | cgroup_sock, | |
| 650 | lwt_in, | |
| 651 | lwt_out, | |
| 652 | lwt_xmit, | |
| 653 | sock_ops, | |
| 654 | sk_skb, | |
| 655 | cgroup_device, | |
| 656 | sk_msg, | |
| 657 | raw_tracepoint, | |
| 658 | cgroup_sock_addr, | |
| 659 | lwt_seg6local, | |
| 660 | lirc_mode2, | |
| 661 | sk_reuseport, | |
| 662 | flow_dissector, | |
| 663 | cgroup_sysctl, | |
| 664 | raw_tracepoint_writable, | |
| 665 | cgroup_sockopt, | |
| 666 | tracing, | |
| 667 | struct_ops, | |
| 668 | ext, | |
| 669 | lsm, | |
| 670 | sk_lookup, | |
| 671 | }; | |
| 672 | ||
| 673 | pub const AttachType = extern enum(u32) { | |
| 674 | cgroup_inet_ingress, | |
| 675 | cgroup_inet_egress, | |
| 676 | cgroup_inet_sock_create, | |
| 677 | cgroup_sock_ops, | |
| 678 | sk_skb_stream_parser, | |
| 679 | sk_skb_stream_verdict, | |
| 680 | cgroup_device, | |
| 681 | sk_msg_verdict, | |
| 682 | cgroup_inet4_bind, | |
| 683 | cgroup_inet6_bind, | |
| 684 | cgroup_inet4_connect, | |
| 685 | cgroup_inet6_connect, | |
| 686 | cgroup_inet4_post_bind, | |
| 687 | cgroup_inet6_post_bind, | |
| 688 | cgroup_udp4_sendmsg, | |
| 689 | cgroup_udp6_sendmsg, | |
| 690 | lirc_mode2, | |
| 691 | flow_dissector, | |
| 692 | cgroup_sysctl, | |
| 693 | cgroup_udp4_recvmsg, | |
| 694 | cgroup_udp6_recvmsg, | |
| 695 | cgroup_getsockopt, | |
| 696 | cgroup_setsockopt, | |
| 697 | trace_raw_tp, | |
| 698 | trace_fentry, | |
| 699 | trace_fexit, | |
| 700 | modify_return, | |
| 701 | lsm_mac, | |
| 702 | trace_iter, | |
| 703 | cgroup_inet4_getpeername, | |
| 704 | cgroup_inet6_getpeername, | |
| 705 | cgroup_inet4_getsockname, | |
| 706 | cgroup_inet6_getsockname, | |
| 707 | xdp_devmap, | |
| 708 | cgroup_inet_sock_release, | |
| 709 | xdp_cpumap, | |
| 710 | sk_lookup, | |
| 711 | xdp, | |
| 712 | _, | |
| 713 | }; | |
| 714 | ||
| 715 | const obj_name_len = 16; | |
| 716 | /// struct used by Cmd.map_create command | |
| 717 | pub const MapCreateAttr = extern struct { | |
| 718 | /// one of MapType | |
| 719 | map_type: u32, | |
| 720 | /// size of key in bytes | |
| 721 | key_size: u32, | |
| 722 | /// size of value in bytes | |
| 723 | value_size: u32, | |
| 724 | /// max number of entries in a map | |
| 725 | max_entries: u32, | |
| 726 | /// .map_create related flags | |
| 727 | map_flags: u32, | |
| 728 | /// fd pointing to the inner map | |
| 729 | inner_map_fd: fd_t, | |
| 730 | /// numa node (effective only if MapCreateFlags.numa_node is set) | |
| 731 | numa_node: u32, | |
| 732 | map_name: [obj_name_len]u8, | |
| 733 | /// ifindex of netdev to create on | |
| 734 | map_ifindex: u32, | |
| 735 | /// fd pointing to a BTF type data | |
| 736 | btf_fd: fd_t, | |
| 737 | /// BTF type_id of the key | |
| 738 | btf_key_type_id: u32, | |
| 739 | /// BTF type_id of the value | |
| 740 | bpf_value_type_id: u32, | |
| 741 | /// BTF type_id of a kernel struct stored as the map value | |
| 742 | btf_vmlinux_value_type_id: u32, | |
| 743 | }; | |
| 744 | ||
| 745 | /// struct used by Cmd.map_*_elem commands | |
| 746 | pub const MapElemAttr = extern struct { | |
| 747 | map_fd: fd_t, | |
| 748 | key: u64, | |
| 749 | result: extern union { | |
| 750 | value: u64, | |
| 751 | next_key: u64, | |
| 752 | }, | |
| 753 | flags: u64, | |
| 754 | }; | |
| 755 | ||
| 756 | /// struct used by Cmd.map_*_batch commands | |
| 757 | pub const MapBatchAttr = extern struct { | |
| 758 | /// start batch, NULL to start from beginning | |
| 759 | in_batch: u64, | |
| 760 | /// output: next start batch | |
| 761 | out_batch: u64, | |
| 762 | keys: u64, | |
| 763 | values: u64, | |
| 764 | /// input/output: | |
| 765 | /// input: # of key/value elements | |
| 766 | /// output: # of filled elements | |
| 767 | count: u32, | |
| 768 | map_fd: fd_t, | |
| 769 | elem_flags: u64, | |
| 770 | flags: u64, | |
| 771 | }; | |
| 772 | ||
| 773 | /// struct used by Cmd.prog_load command | |
| 774 | pub const ProgLoadAttr = extern struct { | |
| 775 | /// one of ProgType | |
| 776 | prog_type: u32, | |
| 777 | insn_cnt: u32, | |
| 778 | insns: u64, | |
| 779 | license: u64, | |
| 780 | /// verbosity level of verifier | |
| 781 | log_level: u32, | |
| 782 | /// size of user buffer | |
| 783 | log_size: u32, | |
| 784 | /// user supplied buffer | |
| 785 | log_buf: u64, | |
| 786 | /// not used | |
| 787 | kern_version: u32, | |
| 788 | prog_flags: u32, | |
| 789 | prog_name: [obj_name_len]u8, | |
| 790 | /// ifindex of netdev to prep for. For some prog types expected attach | |
| 791 | /// type must be known at load time to verify attach type specific parts | |
| 792 | /// of prog (context accesses, allowed helpers, etc). | |
| 793 | prog_ifindex: u32, | |
| 794 | expected_attach_type: u32, | |
| 795 | /// fd pointing to BTF type data | |
| 796 | prog_btf_fd: fd_t, | |
| 797 | /// userspace bpf_func_info size | |
| 798 | func_info_rec_size: u32, | |
| 799 | func_info: u64, | |
| 800 | /// number of bpf_func_info records | |
| 801 | func_info_cnt: u32, | |
| 802 | /// userspace bpf_line_info size | |
| 803 | line_info_rec_size: u32, | |
| 804 | line_info: u64, | |
| 805 | /// number of bpf_line_info records | |
| 806 | line_info_cnt: u32, | |
| 807 | /// in-kernel BTF type id to attach to | |
| 808 | attact_btf_id: u32, | |
| 809 | /// 0 to attach to vmlinux | |
| 810 | attach_prog_id: u32, | |
| 811 | }; | |
| 812 | ||
| 813 | /// struct used by Cmd.obj_* commands | |
| 814 | pub const ObjAttr = extern struct { | |
| 815 | pathname: u64, | |
| 816 | bpf_fd: fd_t, | |
| 817 | file_flags: u32, | |
| 818 | }; | |
| 819 | ||
| 820 | /// struct used by Cmd.prog_attach/detach commands | |
| 821 | pub const ProgAttachAttr = extern struct { | |
| 822 | /// container object to attach to | |
| 823 | target_fd: fd_t, | |
| 824 | /// eBPF program to attach | |
| 825 | attach_bpf_fd: fd_t, | |
| 826 | attach_type: u32, | |
| 827 | attach_flags: u32, | |
| 828 | // TODO: BPF_F_REPLACE flags | |
| 829 | /// previously attached eBPF program to replace if .replace is used | |
| 830 | replace_bpf_fd: fd_t, | |
| 831 | }; | |
| 832 | ||
| 833 | /// struct used by Cmd.prog_test_run command | |
| 834 | pub const TestAttr = extern struct { | |
| 835 | prog_fd: fd_t, | |
| 836 | retval: u32, | |
| 837 | /// input: len of data_in | |
| 838 | data_size_in: u32, | |
| 839 | /// input/output: len of data_out. returns ENOSPC if data_out is too small. | |
| 840 | data_size_out: u32, | |
| 841 | data_in: u64, | |
| 842 | data_out: u64, | |
| 843 | repeat: u32, | |
| 844 | duration: u32, | |
| 845 | /// input: len of ctx_in | |
| 846 | ctx_size_in: u32, | |
| 847 | /// input/output: len of ctx_out. returns ENOSPC if ctx_out is too small. | |
| 848 | ctx_size_out: u32, | |
| 849 | ctx_in: u64, | |
| 850 | ctx_out: u64, | |
| 851 | }; | |
| 852 | ||
| 853 | /// struct used by Cmd.*_get_*_id commands | |
| 854 | pub const GetIdAttr = extern struct { | |
| 855 | id: extern union { | |
| 856 | start_id: u32, | |
| 857 | prog_id: u32, | |
| 858 | map_id: u32, | |
| 859 | btf_id: u32, | |
| 860 | link_id: u32, | |
| 861 | }, | |
| 862 | next_id: u32, | |
| 863 | open_flags: u32, | |
| 864 | }; | |
| 865 | ||
| 866 | /// struct used by Cmd.obj_get_info_by_fd command | |
| 867 | pub const InfoAttr = extern struct { | |
| 868 | bpf_fd: fd_t, | |
| 869 | info_len: u32, | |
| 870 | info: u64, | |
| 871 | }; | |
| 872 | ||
| 873 | /// struct used by Cmd.prog_query command | |
| 874 | pub const QueryAttr = extern struct { | |
| 875 | /// container object to query | |
| 876 | target_fd: fd_t, | |
| 877 | attach_type: u32, | |
| 878 | query_flags: u32, | |
| 879 | attach_flags: u32, | |
| 880 | prog_ids: u64, | |
| 881 | prog_cnt: u32, | |
| 882 | }; | |
| 883 | ||
| 884 | /// struct used by Cmd.raw_tracepoint_open command | |
| 885 | pub const RawTracepointAttr = extern struct { | |
| 886 | name: u64, | |
| 887 | prog_fd: fd_t, | |
| 888 | }; | |
| 889 | ||
| 890 | /// struct used by Cmd.btf_load command | |
| 891 | pub const BtfLoadAttr = extern struct { | |
| 892 | btf: u64, | |
| 893 | btf_log_buf: u64, | |
| 894 | btf_size: u32, | |
| 895 | btf_log_size: u32, | |
| 896 | btf_log_level: u32, | |
| 897 | }; | |
| 898 | ||
| 899 | pub const TaskFdQueryAttr = extern struct { | |
| 900 | /// input: pid | |
| 901 | pid: pid_t, | |
| 902 | /// input: fd | |
| 903 | fd: fd_t, | |
| 904 | /// input: flags | |
| 905 | flags: u32, | |
| 906 | /// input/output: buf len | |
| 907 | buf_len: u32, | |
| 908 | /// input/output: | |
| 909 | /// tp_name for tracepoint | |
| 910 | /// symbol for kprobe | |
| 911 | /// filename for uprobe | |
| 912 | buf: u64, | |
| 913 | /// output: prod_id | |
| 914 | prog_id: u32, | |
| 915 | /// output: BPF_FD_TYPE | |
| 916 | fd_type: u32, | |
| 917 | /// output: probe_offset | |
| 918 | probe_offset: u64, | |
| 919 | /// output: probe_addr | |
| 920 | probe_addr: u64, | |
| 921 | }; | |
| 922 | ||
| 923 | /// struct used by Cmd.link_create command | |
| 924 | pub const LinkCreateAttr = extern struct { | |
| 925 | /// eBPF program to attach | |
| 926 | prog_fd: fd_t, | |
| 927 | /// object to attach to | |
| 928 | target_fd: fd_t, | |
| 929 | attach_type: u32, | |
| 930 | /// extra flags | |
| 931 | flags: u32, | |
| 932 | }; | |
| 933 | ||
| 934 | /// struct used by Cmd.link_update command | |
| 935 | pub const LinkUpdateAttr = extern struct { | |
| 936 | link_fd: fd_t, | |
| 937 | /// new program to update link with | |
| 938 | new_prog_fd: fd_t, | |
| 939 | /// extra flags | |
| 940 | flags: u32, | |
| 941 | /// expected link's program fd, it is specified only if BPF_F_REPLACE is | |
| 942 | /// set in flags | |
| 943 | old_prog_fd: fd_t, | |
| 944 | }; | |
| 945 | ||
| 946 | /// struct used by Cmd.enable_stats command | |
| 947 | pub const EnableStatsAttr = extern struct { | |
| 948 | type: u32, | |
| 949 | }; | |
| 950 | ||
| 951 | /// struct used by Cmd.iter_create command | |
| 952 | pub const IterCreateAttr = extern struct { | |
| 953 | link_fd: fd_t, | |
| 954 | flags: u32, | |
| 955 | }; | |
| 956 | ||
| 957 | pub const Attr = extern union { | |
| 958 | map_create: MapCreateAttr, | |
| 959 | map_elem: MapElemAttr, | |
| 960 | map_batch: MapBatchAttr, | |
| 961 | prog_load: ProgLoadAttr, | |
| 962 | obj: ObjAttr, | |
| 963 | prog_attach: ProgAttachAttr, | |
| 964 | test_run: TestRunAttr, | |
| 965 | get_id: GetIdAttr, | |
| 966 | info: InfoAttr, | |
| 967 | query: QueryAttr, | |
| 968 | raw_tracepoint: RawTracepointAttr, | |
| 969 | btf_load: BtfLoadAttr, | |
| 970 | task_fd_query: TaskFdQueryAttr, | |
| 971 | link_create: LinkCreateAttr, | |
| 972 | link_update: LinkUpdateAttr, | |
| 973 | enable_stats: EnableStatsAttr, | |
| 974 | iter_create: IterCreateAttr, | |
| 975 | }; |
lib/std/os/linux.zig+1| ... | ... | @@ -29,6 +29,7 @@ pub usingnamespace switch (builtin.arch) { |
| 29 | 29 | }; |
| 30 | 30 | pub usingnamespace @import("bits.zig"); |
| 31 | 31 | pub const tls = @import("linux/tls.zig"); |
| 32 | pub const BPF = @import("linux/bpf.zig"); | |
| 32 | 33 | |
| 33 | 34 | /// Set by startup code, used by `getauxval`. |
| 34 | 35 | pub var elf_aux_maybe: ?[*]std.elf.Auxv = null; |
lib/std/os/linux/bpf.zig created+973| ... | ... | @@ -0,0 +1,973 @@ |
| 1 | // SPDX-License-Identifier: MIT | |
| 2 | // Copyright (c) 2015-2020 Zig Contributors | |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | // and substantial portions of the software. | |
| 6 | usingnamespace std.os; | |
| 7 | const std = @import("../../std.zig"); | |
| 8 | const expectEqual = std.testing.expectEqual; | |
| 9 | ||
| 10 | // instruction classes | |
| 11 | pub const LD = 0x00; | |
| 12 | pub const LDX = 0x01; | |
| 13 | pub const ST = 0x02; | |
| 14 | pub const STX = 0x03; | |
| 15 | pub const ALU = 0x04; | |
| 16 | pub const JMP = 0x05; | |
| 17 | pub const RET = 0x06; | |
| 18 | pub const MISC = 0x07; | |
| 19 | ||
| 20 | /// 32-bit | |
| 21 | pub const W = 0x00; | |
| 22 | /// 16-bit | |
| 23 | pub const H = 0x08; | |
| 24 | /// 8-bit | |
| 25 | pub const B = 0x10; | |
| 26 | /// 64-bit | |
| 27 | pub const DW = 0x18; | |
| 28 | ||
| 29 | pub const IMM = 0x00; | |
| 30 | pub const ABS = 0x20; | |
| 31 | pub const IND = 0x40; | |
| 32 | pub const MEM = 0x60; | |
| 33 | pub const LEN = 0x80; | |
| 34 | pub const MSH = 0xa0; | |
| 35 | ||
| 36 | // alu fields | |
| 37 | pub const ADD = 0x00; | |
| 38 | pub const SUB = 0x10; | |
| 39 | pub const MUL = 0x20; | |
| 40 | pub const DIV = 0x30; | |
| 41 | pub const OR = 0x40; | |
| 42 | pub const AND = 0x50; | |
| 43 | pub const LSH = 0x60; | |
| 44 | pub const RSH = 0x70; | |
| 45 | pub const NEG = 0x80; | |
| 46 | pub const MOD = 0x90; | |
| 47 | pub const XOR = 0xa0; | |
| 48 | ||
| 49 | // jmp fields | |
| 50 | pub const JA = 0x00; | |
| 51 | pub const JEQ = 0x10; | |
| 52 | pub const JGT = 0x20; | |
| 53 | pub const JGE = 0x30; | |
| 54 | pub const JSET = 0x40; | |
| 55 | ||
| 56 | //#define BPF_SRC(code) ((code) & 0x08) | |
| 57 | pub const K = 0x00; | |
| 58 | pub const X = 0x08; | |
| 59 | ||
| 60 | pub const MAXINSNS = 4096; | |
| 61 | ||
| 62 | // instruction classes | |
| 63 | /// jmp mode in word width | |
| 64 | pub const JMP32 = 0x06; | |
| 65 | /// alu mode in double word width | |
| 66 | pub const ALU64 = 0x07; | |
| 67 | ||
| 68 | // ld/ldx fields | |
| 69 | /// exclusive add | |
| 70 | pub const XADD = 0xc0; | |
| 71 | ||
| 72 | // alu/jmp fields | |
| 73 | /// mov reg to reg | |
| 74 | pub const MOV = 0xb0; | |
| 75 | /// sign extending arithmetic shift right */ | |
| 76 | pub const ARSH = 0xc0; | |
| 77 | ||
| 78 | // change endianness of a register | |
| 79 | /// flags for endianness conversion: | |
| 80 | pub const END = 0xd0; | |
| 81 | /// convert to little-endian */ | |
| 82 | pub const TO_LE = 0x00; | |
| 83 | /// convert to big-endian | |
| 84 | pub const TO_BE = 0x08; | |
| 85 | pub const FROM_LE = TO_LE; | |
| 86 | pub const FROM_BE = TO_BE; | |
| 87 | ||
| 88 | // jmp encodings | |
| 89 | /// jump != * | |
| 90 | pub const JNE = 0x50; | |
| 91 | /// LT is unsigned, '<' | |
| 92 | pub const JLT = 0xa0; | |
| 93 | /// LE is unsigned, '<=' * | |
| 94 | pub const JLE = 0xb0; | |
| 95 | /// SGT is signed '>', GT in x86 | |
| 96 | pub const JSGT = 0x60; | |
| 97 | /// SGE is signed '>=', GE in x86 | |
| 98 | pub const JSGE = 0x70; | |
| 99 | /// SLT is signed, '<' | |
| 100 | pub const JSLT = 0xc0; | |
| 101 | /// SLE is signed, '<=' | |
| 102 | pub const JSLE = 0xd0; | |
| 103 | /// function call | |
| 104 | pub const CALL = 0x80; | |
| 105 | /// function return | |
| 106 | pub const EXIT = 0x90; | |
| 107 | ||
| 108 | /// Flag for prog_attach command. If a sub-cgroup installs some bpf program, the | |
| 109 | /// program in this cgroup yields to sub-cgroup program. | |
| 110 | pub const F_ALLOW_OVERRIDE = 0x1; | |
| 111 | /// Flag for prog_attach command. If a sub-cgroup installs some bpf program, | |
| 112 | /// that cgroup program gets run in addition to the program in this cgroup. | |
| 113 | pub const F_ALLOW_MULTI = 0x2; | |
| 114 | /// Flag for prog_attach command. | |
| 115 | pub const F_REPLACE = 0x4; | |
| 116 | ||
| 117 | /// If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the verifier | |
| 118 | /// will perform strict alignment checking as if the kernel has been built with | |
| 119 | /// CONFIG_EFFICIENT_UNALIGNED_ACCESS not set, and NET_IP_ALIGN defined to 2. | |
| 120 | pub const F_STRICT_ALIGNMENT = 0x1; | |
| 121 | ||
| 122 | /// If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the verifier will | |
| 123 | /// allow any alignment whatsoever. On platforms with strict alignment | |
| 124 | /// requirements for loads ands stores (such as sparc and mips) the verifier | |
| 125 | /// validates that all loads and stores provably follow this requirement. This | |
| 126 | /// flag turns that checking and enforcement off. | |
| 127 | /// | |
| 128 | /// It is mostly used for testing when we want to validate the context and | |
| 129 | /// memory access aspects of the verifier, but because of an unaligned access | |
| 130 | /// the alignment check would trigger before the one we are interested in. | |
| 131 | pub const F_ANY_ALIGNMENT = 0x2; | |
| 132 | ||
| 133 | /// BPF_F_TEST_RND_HI32 is used in BPF_PROG_LOAD command for testing purpose. | |
| 134 | /// Verifier does sub-register def/use analysis and identifies instructions | |
| 135 | /// whose def only matters for low 32-bit, high 32-bit is never referenced later | |
| 136 | /// through implicit zero extension. Therefore verifier notifies JIT back-ends | |
| 137 | /// that it is safe to ignore clearing high 32-bit for these instructions. This | |
| 138 | /// saves some back-ends a lot of code-gen. However such optimization is not | |
| 139 | /// necessary on some arches, for example x86_64, arm64 etc, whose JIT back-ends | |
| 140 | /// hence hasn't used verifier's analysis result. But, we really want to have a | |
| 141 | /// way to be able to verify the correctness of the described optimization on | |
| 142 | /// x86_64 on which testsuites are frequently exercised. | |
| 143 | /// | |
| 144 | /// So, this flag is introduced. Once it is set, verifier will randomize high | |
| 145 | /// 32-bit for those instructions who has been identified as safe to ignore | |
| 146 | /// them. Then, if verifier is not doing correct analysis, such randomization | |
| 147 | /// will regress tests to expose bugs. | |
| 148 | pub const F_TEST_RND_HI32 = 0x4; | |
| 149 | ||
| 150 | /// When BPF ldimm64's insn[0].src_reg != 0 then this can have two extensions: | |
| 151 | /// insn[0].src_reg: BPF_PSEUDO_MAP_FD BPF_PSEUDO_MAP_VALUE | |
| 152 | /// insn[0].imm: map fd map fd | |
| 153 | /// insn[1].imm: 0 offset into value | |
| 154 | /// insn[0].off: 0 0 | |
| 155 | /// insn[1].off: 0 0 | |
| 156 | /// ldimm64 rewrite: address of map address of map[0]+offset | |
| 157 | /// verifier type: CONST_PTR_TO_MAP PTR_TO_MAP_VALUE | |
| 158 | pub const PSEUDO_MAP_FD = 1; | |
| 159 | pub const PSEUDO_MAP_VALUE = 2; | |
| 160 | ||
| 161 | /// when bpf_call->src_reg == BPF_PSEUDO_CALL, bpf_call->imm == pc-relative | |
| 162 | /// offset to another bpf function | |
| 163 | pub const PSEUDO_CALL = 1; | |
| 164 | ||
| 165 | /// flag for BPF_MAP_UPDATE_ELEM command. create new element or update existing | |
| 166 | pub const ANY = 0; | |
| 167 | /// flag for BPF_MAP_UPDATE_ELEM command. create new element if it didn't exist | |
| 168 | pub const NOEXIST = 1; | |
| 169 | /// flag for BPF_MAP_UPDATE_ELEM command. update existing element | |
| 170 | pub const EXIST = 2; | |
| 171 | /// flag for BPF_MAP_UPDATE_ELEM command. spin_lock-ed map_lookup/map_update | |
| 172 | pub const F_LOCK = 4; | |
| 173 | ||
| 174 | /// flag for BPF_MAP_CREATE command */ | |
| 175 | pub const BPF_F_NO_PREALLOC = 0x1; | |
| 176 | /// flag for BPF_MAP_CREATE command. Instead of having one common LRU list in | |
| 177 | /// the BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list which can | |
| 178 | /// scale and perform better. Note, the LRU nodes (including free nodes) cannot | |
| 179 | /// be moved across different LRU lists. | |
| 180 | pub const BPF_F_NO_COMMON_LRU = 0x2; | |
| 181 | /// flag for BPF_MAP_CREATE command. Specify numa node during map creation | |
| 182 | pub const BPF_F_NUMA_NODE = 0x4; | |
| 183 | /// flag for BPF_MAP_CREATE command. Flags for BPF object read access from | |
| 184 | /// syscall side | |
| 185 | pub const BPF_F_RDONLY = 0x8; | |
| 186 | /// flag for BPF_MAP_CREATE command. Flags for BPF object write access from | |
| 187 | /// syscall side | |
| 188 | pub const BPF_F_WRONLY = 0x10; | |
| 189 | /// flag for BPF_MAP_CREATE command. Flag for stack_map, store build_id+offset | |
| 190 | /// instead of pointer | |
| 191 | pub const BPF_F_STACK_BUILD_ID = 0x20; | |
| 192 | /// flag for BPF_MAP_CREATE command. Zero-initialize hash function seed. This | |
| 193 | /// should only be used for testing. | |
| 194 | pub const BPF_F_ZERO_SEED = 0x40; | |
| 195 | /// flag for BPF_MAP_CREATE command Flags for accessing BPF object from program | |
| 196 | /// side. | |
| 197 | pub const BPF_F_RDONLY_PROG = 0x80; | |
| 198 | /// flag for BPF_MAP_CREATE command. Flags for accessing BPF object from program | |
| 199 | /// side. | |
| 200 | pub const BPF_F_WRONLY_PROG = 0x100; | |
| 201 | /// flag for BPF_MAP_CREATE command. Clone map from listener for newly accepted | |
| 202 | /// socket | |
| 203 | pub const BPF_F_CLONE = 0x200; | |
| 204 | /// flag for BPF_MAP_CREATE command. Enable memory-mapping BPF map | |
| 205 | pub const BPF_F_MMAPABLE = 0x400; | |
| 206 | ||
| 207 | /// These values correspond to "syscalls" within the BPF program's environment | |
| 208 | pub const Helper = enum(i32) { | |
| 209 | unspec, | |
| 210 | map_lookup_elem, | |
| 211 | map_update_elem, | |
| 212 | map_delete_elem, | |
| 213 | probe_read, | |
| 214 | ktime_get_ns, | |
| 215 | trace_printk, | |
| 216 | get_prandom_u32, | |
| 217 | get_smp_processor_id, | |
| 218 | skb_store_bytes, | |
| 219 | l3_csum_replace, | |
| 220 | l4_csum_replace, | |
| 221 | tail_call, | |
| 222 | clone_redirect, | |
| 223 | get_current_pid_tgid, | |
| 224 | get_current_uid_gid, | |
| 225 | get_current_comm, | |
| 226 | get_cgroup_classid, | |
| 227 | skb_vlan_push, | |
| 228 | skb_vlan_pop, | |
| 229 | skb_get_tunnel_key, | |
| 230 | skb_set_tunnel_key, | |
| 231 | perf_event_read, | |
| 232 | redirect, | |
| 233 | get_route_realm, | |
| 234 | perf_event_output, | |
| 235 | skb_load_bytes, | |
| 236 | get_stackid, | |
| 237 | csum_diff, | |
| 238 | skb_get_tunnel_opt, | |
| 239 | skb_set_tunnel_opt, | |
| 240 | skb_change_proto, | |
| 241 | skb_change_type, | |
| 242 | skb_under_cgroup, | |
| 243 | get_hash_recalc, | |
| 244 | get_current_task, | |
| 245 | probe_write_user, | |
| 246 | current_task_under_cgroup, | |
| 247 | skb_change_tail, | |
| 248 | skb_pull_data, | |
| 249 | csum_update, | |
| 250 | set_hash_invalid, | |
| 251 | get_numa_node_id, | |
| 252 | skb_change_head, | |
| 253 | xdp_adjust_head, | |
| 254 | probe_read_str, | |
| 255 | get_socket_cookie, | |
| 256 | get_socket_uid, | |
| 257 | set_hash, | |
| 258 | setsockopt, | |
| 259 | skb_adjust_room, | |
| 260 | redirect_map, | |
| 261 | sk_redirect_map, | |
| 262 | sock_map_update, | |
| 263 | xdp_adjust_meta, | |
| 264 | perf_event_read_value, | |
| 265 | perf_prog_read_value, | |
| 266 | getsockopt, | |
| 267 | override_return, | |
| 268 | sock_ops_cb_flags_set, | |
| 269 | msg_redirect_map, | |
| 270 | msg_apply_bytes, | |
| 271 | msg_cork_bytes, | |
| 272 | msg_pull_data, | |
| 273 | bind, | |
| 274 | xdp_adjust_tail, | |
| 275 | skb_get_xfrm_state, | |
| 276 | get_stack, | |
| 277 | skb_load_bytes_relative, | |
| 278 | fib_lookup, | |
| 279 | sock_hash_update, | |
| 280 | msg_redirect_hash, | |
| 281 | sk_redirect_hash, | |
| 282 | lwt_push_encap, | |
| 283 | lwt_seg6_store_bytes, | |
| 284 | lwt_seg6_adjust_srh, | |
| 285 | lwt_seg6_action, | |
| 286 | rc_repeat, | |
| 287 | rc_keydown, | |
| 288 | skb_cgroup_id, | |
| 289 | get_current_cgroup_id, | |
| 290 | get_local_storage, | |
| 291 | sk_select_reuseport, | |
| 292 | skb_ancestor_cgroup_id, | |
| 293 | sk_lookup_tcp, | |
| 294 | sk_lookup_udp, | |
| 295 | sk_release, | |
| 296 | map_push_elem, | |
| 297 | map_pop_elem, | |
| 298 | map_peek_elem, | |
| 299 | msg_push_data, | |
| 300 | msg_pop_data, | |
| 301 | rc_pointer_rel, | |
| 302 | spin_lock, | |
| 303 | spin_unlock, | |
| 304 | sk_fullsock, | |
| 305 | tcp_sock, | |
| 306 | skb_ecn_set_ce, | |
| 307 | get_listener_sock, | |
| 308 | skc_lookup_tcp, | |
| 309 | tcp_check_syncookie, | |
| 310 | sysctl_get_name, | |
| 311 | sysctl_get_current_value, | |
| 312 | sysctl_get_new_value, | |
| 313 | sysctl_set_new_value, | |
| 314 | strtol, | |
| 315 | strtoul, | |
| 316 | sk_storage_get, | |
| 317 | sk_storage_delete, | |
| 318 | send_signal, | |
| 319 | tcp_gen_syncookie, | |
| 320 | skb_output, | |
| 321 | probe_read_user, | |
| 322 | probe_read_kernel, | |
| 323 | probe_read_user_str, | |
| 324 | probe_read_kernel_str, | |
| 325 | tcp_send_ack, | |
| 326 | send_signal_thread, | |
| 327 | jiffies64, | |
| 328 | _, | |
| 329 | }; | |
| 330 | ||
| 331 | /// a single BPF instruction | |
| 332 | pub const Insn = packed struct { | |
| 333 | code: u8, | |
| 334 | dst: u4, | |
| 335 | src: u4, | |
| 336 | off: i16, | |
| 337 | imm: i32, | |
| 338 | ||
| 339 | /// r0 - r9 are general purpose 64-bit registers, r10 points to the stack | |
| 340 | /// frame | |
| 341 | pub const Reg = packed enum(u4) { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 }; | |
| 342 | const Source = packed enum(u1) { reg, imm }; | |
| 343 | const AluOp = packed enum(u8) { | |
| 344 | add = ADD, | |
| 345 | sub = SUB, | |
| 346 | mul = MUL, | |
| 347 | div = DIV, | |
| 348 | op_or = OR, | |
| 349 | op_and = AND, | |
| 350 | lsh = LSH, | |
| 351 | rsh = RSH, | |
| 352 | neg = NEG, | |
| 353 | mod = MOD, | |
| 354 | xor = XOR, | |
| 355 | mov = MOV, | |
| 356 | }; | |
| 357 | ||
| 358 | pub const Size = packed enum(u8) { | |
| 359 | byte = B, | |
| 360 | half_word = H, | |
| 361 | word = W, | |
| 362 | double_word = DW, | |
| 363 | }; | |
| 364 | ||
| 365 | const JmpOp = packed enum(u8) { | |
| 366 | ja = JA, | |
| 367 | jeq = JEQ, | |
| 368 | jgt = JGT, | |
| 369 | jge = JGE, | |
| 370 | jset = JSET, | |
| 371 | }; | |
| 372 | ||
| 373 | const ImmOrReg = union(Source) { | |
| 374 | imm: i32, | |
| 375 | reg: Reg, | |
| 376 | }; | |
| 377 | ||
| 378 | fn imm_reg(code: u8, dst: Reg, src: anytype, off: i16) Insn { | |
| 379 | const imm_or_reg = if (@typeInfo(@TypeOf(src)) == .EnumLiteral) | |
| 380 | ImmOrReg{ .reg = @as(Reg, src) } | |
| 381 | else | |
| 382 | ImmOrReg{ .imm = src }; | |
| 383 | ||
| 384 | const src_type = switch (imm_or_reg) { | |
| 385 | .imm => K, | |
| 386 | .reg => X, | |
| 387 | }; | |
| 388 | ||
| 389 | return Insn{ | |
| 390 | .code = code | src_type, | |
| 391 | .dst = @enumToInt(dst), | |
| 392 | .src = switch (imm_or_reg) { | |
| 393 | .imm => 0, | |
| 394 | .reg => |r| @enumToInt(r), | |
| 395 | }, | |
| 396 | .off = off, | |
| 397 | .imm = switch (imm_or_reg) { | |
| 398 | .imm => |i| i, | |
| 399 | .reg => 0, | |
| 400 | }, | |
| 401 | }; | |
| 402 | } | |
| 403 | ||
| 404 | fn alu(comptime width: comptime_int, op: AluOp, dst: Reg, src: anytype) Insn { | |
| 405 | const width_bitfield = switch (width) { | |
| 406 | 32 => ALU, | |
| 407 | 64 => ALU64, | |
| 408 | else => @compileError("width must be 32 or 64"), | |
| 409 | }; | |
| 410 | ||
| 411 | return imm_reg(width_bitfield | @enumToInt(op), dst, src, 0); | |
| 412 | } | |
| 413 | ||
| 414 | pub fn mov(dst: Reg, src: anytype) Insn { | |
| 415 | return alu(64, .mov, dst, src); | |
| 416 | } | |
| 417 | ||
| 418 | pub fn add(dst: Reg, src: anytype) Insn { | |
| 419 | return alu(64, .add, dst, src); | |
| 420 | } | |
| 421 | ||
| 422 | fn jmp(op: JmpOp, dst: Reg, src: anytype, off: i16) Insn { | |
| 423 | return imm_reg(JMP | @enumToInt(op), dst, src, off); | |
| 424 | } | |
| 425 | ||
| 426 | pub fn jeq(dst: Reg, src: anytype, off: i16) Insn { | |
| 427 | return jmp(.jeq, dst, src, off); | |
| 428 | } | |
| 429 | ||
| 430 | pub fn stx_mem(size: Size, dst: Reg, src: Reg, off: i16) Insn { | |
| 431 | return Insn{ | |
| 432 | .code = STX | @enumToInt(size) | MEM, | |
| 433 | .dst = @enumToInt(dst), | |
| 434 | .src = @enumToInt(src), | |
| 435 | .off = off, | |
| 436 | .imm = 0, | |
| 437 | }; | |
| 438 | } | |
| 439 | ||
| 440 | pub fn xadd(dst: Reg, src: Reg) Insn { | |
| 441 | return Insn{ | |
| 442 | .code = STX | XADD | DW, | |
| 443 | .dst = @enumToInt(dst), | |
| 444 | .src = @enumToInt(src), | |
| 445 | .off = 0, | |
| 446 | .imm = 0, | |
| 447 | }; | |
| 448 | } | |
| 449 | ||
| 450 | /// direct packet access, R0 = *(uint *)(skb->data + imm32) | |
| 451 | pub fn ld_abs(size: Size, imm: i32) Insn { | |
| 452 | return Insn{ | |
| 453 | .code = LD | @enumToInt(size) | ABS, | |
| 454 | .dst = 0, | |
| 455 | .src = 0, | |
| 456 | .off = 0, | |
| 457 | .imm = imm, | |
| 458 | }; | |
| 459 | } | |
| 460 | ||
| 461 | fn ld_imm_impl1(dst: Reg, src: Reg, imm: u64) Insn { | |
| 462 | return Insn{ | |
| 463 | .code = LD | DW | IMM, | |
| 464 | .dst = @enumToInt(dst), | |
| 465 | .src = @enumToInt(src), | |
| 466 | .off = 0, | |
| 467 | .imm = @intCast(i32, @truncate(u32, imm)), | |
| 468 | }; | |
| 469 | } | |
| 470 | ||
| 471 | fn ld_imm_impl2(imm: u64) Insn { | |
| 472 | return Insn{ | |
| 473 | .code = 0, | |
| 474 | .dst = 0, | |
| 475 | .src = 0, | |
| 476 | .off = 0, | |
| 477 | .imm = @intCast(i32, @truncate(u32, imm >> 32)), | |
| 478 | }; | |
| 479 | } | |
| 480 | ||
| 481 | pub fn ld_map_fd1(dst: Reg, map_fd: fd_t) Insn { | |
| 482 | return ld_imm_impl1(dst, @intToEnum(Reg, PSEUDO_MAP_FD), @intCast(u64, map_fd)); | |
| 483 | } | |
| 484 | ||
| 485 | pub fn ld_map_fd2(map_fd: fd_t) Insn { | |
| 486 | return ld_imm_impl2(@intCast(u64, map_fd)); | |
| 487 | } | |
| 488 | ||
| 489 | pub fn call(helper: Helper) Insn { | |
| 490 | return Insn{ | |
| 491 | .code = JMP | CALL, | |
| 492 | .dst = 0, | |
| 493 | .src = 0, | |
| 494 | .off = 0, | |
| 495 | .imm = @enumToInt(helper), | |
| 496 | }; | |
| 497 | } | |
| 498 | ||
| 499 | /// exit BPF program | |
| 500 | pub fn exit() Insn { | |
| 501 | return Insn{ | |
| 502 | .code = JMP | EXIT, | |
| 503 | .dst = 0, | |
| 504 | .src = 0, | |
| 505 | .off = 0, | |
| 506 | .imm = 0, | |
| 507 | }; | |
| 508 | } | |
| 509 | }; | |
| 510 | ||
| 511 | fn expect_insn(insn: Insn, val: u64) void { | |
| 512 | expectEqual(@bitCast(u64, insn), val); | |
| 513 | } | |
| 514 | ||
| 515 | test "insn bitsize" { | |
| 516 | expectEqual(@bitSizeOf(Insn), 64); | |
| 517 | } | |
| 518 | ||
| 519 | // mov instructions | |
| 520 | test "mov imm" { | |
| 521 | expect_insn(Insn.mov(.r1, 1), 0x00000001000001b7); | |
| 522 | } | |
| 523 | ||
| 524 | test "mov reg" { | |
| 525 | expect_insn(Insn.mov(.r6, .r1), 0x00000000000016bf); | |
| 526 | } | |
| 527 | ||
| 528 | // alu instructions | |
| 529 | test "add imm" { | |
| 530 | expect_insn(Insn.add(.r2, -4), 0xfffffffc00000207); | |
| 531 | } | |
| 532 | ||
| 533 | // ld instructions | |
| 534 | test "ld_abs" { | |
| 535 | expect_insn(Insn.ld_abs(.byte, 42), 0x0000002a00000030); | |
| 536 | } | |
| 537 | ||
| 538 | test "ld_map_fd" { | |
| 539 | expect_insn(Insn.ld_map_fd1(.r1, 42), 0x0000002a00001118); | |
| 540 | expect_insn(Insn.ld_map_fd2(42), 0x0000000000000000); | |
| 541 | } | |
| 542 | ||
| 543 | // st instructions | |
| 544 | test "stx_mem" { | |
| 545 | expect_insn(Insn.stx_mem(.word, .r10, .r0, -4), 0x00000000fffc0a63); | |
| 546 | } | |
| 547 | ||
| 548 | test "xadd" { | |
| 549 | expect_insn(Insn.xadd(.r0, .r1), 0x00000000000010db); | |
| 550 | } | |
| 551 | ||
| 552 | // jmp instructions | |
| 553 | test "jeq imm" { | |
| 554 | expect_insn(Insn.jeq(.r0, 0, 2), 0x0000000000020015); | |
| 555 | } | |
| 556 | ||
| 557 | // other instructions | |
| 558 | test "call" { | |
| 559 | expect_insn(Insn.call(.map_lookup_elem), 0x0000000100000085); | |
| 560 | } | |
| 561 | ||
| 562 | test "exit" { | |
| 563 | expect_insn(Insn.exit(), 0x0000000000000095); | |
| 564 | } | |
| 565 | ||
| 566 | pub const Cmd = extern enum(usize) { | |
| 567 | map_create, | |
| 568 | map_lookup_elem, | |
| 569 | map_update_elem, | |
| 570 | map_delete_elem, | |
| 571 | map_get_next_key, | |
| 572 | prog_load, | |
| 573 | obj_pin, | |
| 574 | obj_get, | |
| 575 | prog_attach, | |
| 576 | prog_detach, | |
| 577 | prog_test_run, | |
| 578 | prog_get_next_id, | |
| 579 | map_get_next_id, | |
| 580 | prog_get_fd_by_id, | |
| 581 | map_get_fd_by_id, | |
| 582 | obj_get_info_by_fd, | |
| 583 | prog_query, | |
| 584 | raw_tracepoint_open, | |
| 585 | btf_load, | |
| 586 | btf_get_fd_by_id, | |
| 587 | task_fd_query, | |
| 588 | map_lookup_and_delete_elem, | |
| 589 | map_freeze, | |
| 590 | btf_get_next_id, | |
| 591 | map_lookup_batch, | |
| 592 | map_lookup_and_delete_batch, | |
| 593 | map_update_batch, | |
| 594 | map_delete_batch, | |
| 595 | link_create, | |
| 596 | link_update, | |
| 597 | link_get_fd_by_id, | |
| 598 | link_get_next_id, | |
| 599 | enable_stats, | |
| 600 | iter_create, | |
| 601 | link_detach, | |
| 602 | _, | |
| 603 | }; | |
| 604 | ||
| 605 | pub const MapType = extern enum(u32) { | |
| 606 | unspec, | |
| 607 | hash, | |
| 608 | array, | |
| 609 | prog_array, | |
| 610 | perf_event_array, | |
| 611 | percpu_hash, | |
| 612 | percpu_array, | |
| 613 | stack_trace, | |
| 614 | cgroup_array, | |
| 615 | lru_hash, | |
| 616 | lru_percpu_hash, | |
| 617 | lpm_trie, | |
| 618 | array_of_maps, | |
| 619 | hash_of_maps, | |
| 620 | devmap, | |
| 621 | sockmap, | |
| 622 | cpumap, | |
| 623 | xskmap, | |
| 624 | sockhash, | |
| 625 | cgroup_storage, | |
| 626 | reuseport_sockarray, | |
| 627 | percpu_cgroup_storage, | |
| 628 | queue, | |
| 629 | stack, | |
| 630 | sk_storage, | |
| 631 | devmap_hash, | |
| 632 | struct_ops, | |
| 633 | ringbuf, | |
| 634 | _, | |
| 635 | }; | |
| 636 | ||
| 637 | pub const ProgType = extern enum(u32) { | |
| 638 | unspec, | |
| 639 | socket_filter, | |
| 640 | kprobe, | |
| 641 | sched_cls, | |
| 642 | sched_act, | |
| 643 | tracepoint, | |
| 644 | xdp, | |
| 645 | perf_event, | |
| 646 | cgroup_skb, | |
| 647 | cgroup_sock, | |
| 648 | lwt_in, | |
| 649 | lwt_out, | |
| 650 | lwt_xmit, | |
| 651 | sock_ops, | |
| 652 | sk_skb, | |
| 653 | cgroup_device, | |
| 654 | sk_msg, | |
| 655 | raw_tracepoint, | |
| 656 | cgroup_sock_addr, | |
| 657 | lwt_seg6local, | |
| 658 | lirc_mode2, | |
| 659 | sk_reuseport, | |
| 660 | flow_dissector, | |
| 661 | cgroup_sysctl, | |
| 662 | raw_tracepoint_writable, | |
| 663 | cgroup_sockopt, | |
| 664 | tracing, | |
| 665 | struct_ops, | |
| 666 | ext, | |
| 667 | lsm, | |
| 668 | sk_lookup, | |
| 669 | }; | |
| 670 | ||
| 671 | pub const AttachType = extern enum(u32) { | |
| 672 | cgroup_inet_ingress, | |
| 673 | cgroup_inet_egress, | |
| 674 | cgroup_inet_sock_create, | |
| 675 | cgroup_sock_ops, | |
| 676 | sk_skb_stream_parser, | |
| 677 | sk_skb_stream_verdict, | |
| 678 | cgroup_device, | |
| 679 | sk_msg_verdict, | |
| 680 | cgroup_inet4_bind, | |
| 681 | cgroup_inet6_bind, | |
| 682 | cgroup_inet4_connect, | |
| 683 | cgroup_inet6_connect, | |
| 684 | cgroup_inet4_post_bind, | |
| 685 | cgroup_inet6_post_bind, | |
| 686 | cgroup_udp4_sendmsg, | |
| 687 | cgroup_udp6_sendmsg, | |
| 688 | lirc_mode2, | |
| 689 | flow_dissector, | |
| 690 | cgroup_sysctl, | |
| 691 | cgroup_udp4_recvmsg, | |
| 692 | cgroup_udp6_recvmsg, | |
| 693 | cgroup_getsockopt, | |
| 694 | cgroup_setsockopt, | |
| 695 | trace_raw_tp, | |
| 696 | trace_fentry, | |
| 697 | trace_fexit, | |
| 698 | modify_return, | |
| 699 | lsm_mac, | |
| 700 | trace_iter, | |
| 701 | cgroup_inet4_getpeername, | |
| 702 | cgroup_inet6_getpeername, | |
| 703 | cgroup_inet4_getsockname, | |
| 704 | cgroup_inet6_getsockname, | |
| 705 | xdp_devmap, | |
| 706 | cgroup_inet_sock_release, | |
| 707 | xdp_cpumap, | |
| 708 | sk_lookup, | |
| 709 | xdp, | |
| 710 | _, | |
| 711 | }; | |
| 712 | ||
| 713 | const obj_name_len = 16; | |
| 714 | /// struct used by Cmd.map_create command | |
| 715 | pub const MapCreateAttr = extern struct { | |
| 716 | /// one of MapType | |
| 717 | map_type: u32, | |
| 718 | /// size of key in bytes | |
| 719 | key_size: u32, | |
| 720 | /// size of value in bytes | |
| 721 | value_size: u32, | |
| 722 | /// max number of entries in a map | |
| 723 | max_entries: u32, | |
| 724 | /// .map_create related flags | |
| 725 | map_flags: u32, | |
| 726 | /// fd pointing to the inner map | |
| 727 | inner_map_fd: fd_t, | |
| 728 | /// numa node (effective only if MapCreateFlags.numa_node is set) | |
| 729 | numa_node: u32, | |
| 730 | map_name: [obj_name_len]u8, | |
| 731 | /// ifindex of netdev to create on | |
| 732 | map_ifindex: u32, | |
| 733 | /// fd pointing to a BTF type data | |
| 734 | btf_fd: fd_t, | |
| 735 | /// BTF type_id of the key | |
| 736 | btf_key_type_id: u32, | |
| 737 | /// BTF type_id of the value | |
| 738 | bpf_value_type_id: u32, | |
| 739 | /// BTF type_id of a kernel struct stored as the map value | |
| 740 | btf_vmlinux_value_type_id: u32, | |
| 741 | }; | |
| 742 | ||
| 743 | /// struct used by Cmd.map_*_elem commands | |
| 744 | pub const MapElemAttr = extern struct { | |
| 745 | map_fd: fd_t, | |
| 746 | key: u64, | |
| 747 | result: extern union { | |
| 748 | value: u64, | |
| 749 | next_key: u64, | |
| 750 | }, | |
| 751 | flags: u64, | |
| 752 | }; | |
| 753 | ||
| 754 | /// struct used by Cmd.map_*_batch commands | |
| 755 | pub const MapBatchAttr = extern struct { | |
| 756 | /// start batch, NULL to start from beginning | |
| 757 | in_batch: u64, | |
| 758 | /// output: next start batch | |
| 759 | out_batch: u64, | |
| 760 | keys: u64, | |
| 761 | values: u64, | |
| 762 | /// input/output: | |
| 763 | /// input: # of key/value elements | |
| 764 | /// output: # of filled elements | |
| 765 | count: u32, | |
| 766 | map_fd: fd_t, | |
| 767 | elem_flags: u64, | |
| 768 | flags: u64, | |
| 769 | }; | |
| 770 | ||
| 771 | /// struct used by Cmd.prog_load command | |
| 772 | pub const ProgLoadAttr = extern struct { | |
| 773 | /// one of ProgType | |
| 774 | prog_type: u32, | |
| 775 | insn_cnt: u32, | |
| 776 | insns: u64, | |
| 777 | license: u64, | |
| 778 | /// verbosity level of verifier | |
| 779 | log_level: u32, | |
| 780 | /// size of user buffer | |
| 781 | log_size: u32, | |
| 782 | /// user supplied buffer | |
| 783 | log_buf: u64, | |
| 784 | /// not used | |
| 785 | kern_version: u32, | |
| 786 | prog_flags: u32, | |
| 787 | prog_name: [obj_name_len]u8, | |
| 788 | /// ifindex of netdev to prep for. For some prog types expected attach | |
| 789 | /// type must be known at load time to verify attach type specific parts | |
| 790 | /// of prog (context accesses, allowed helpers, etc). | |
| 791 | prog_ifindex: u32, | |
| 792 | expected_attach_type: u32, | |
| 793 | /// fd pointing to BTF type data | |
| 794 | prog_btf_fd: fd_t, | |
| 795 | /// userspace bpf_func_info size | |
| 796 | func_info_rec_size: u32, | |
| 797 | func_info: u64, | |
| 798 | /// number of bpf_func_info records | |
| 799 | func_info_cnt: u32, | |
| 800 | /// userspace bpf_line_info size | |
| 801 | line_info_rec_size: u32, | |
| 802 | line_info: u64, | |
| 803 | /// number of bpf_line_info records | |
| 804 | line_info_cnt: u32, | |
| 805 | /// in-kernel BTF type id to attach to | |
| 806 | attact_btf_id: u32, | |
| 807 | /// 0 to attach to vmlinux | |
| 808 | attach_prog_id: u32, | |
| 809 | }; | |
| 810 | ||
| 811 | /// struct used by Cmd.obj_* commands | |
| 812 | pub const ObjAttr = extern struct { | |
| 813 | pathname: u64, | |
| 814 | bpf_fd: fd_t, | |
| 815 | file_flags: u32, | |
| 816 | }; | |
| 817 | ||
| 818 | /// struct used by Cmd.prog_attach/detach commands | |
| 819 | pub const ProgAttachAttr = extern struct { | |
| 820 | /// container object to attach to | |
| 821 | target_fd: fd_t, | |
| 822 | /// eBPF program to attach | |
| 823 | attach_bpf_fd: fd_t, | |
| 824 | attach_type: u32, | |
| 825 | attach_flags: u32, | |
| 826 | // TODO: BPF_F_REPLACE flags | |
| 827 | /// previously attached eBPF program to replace if .replace is used | |
| 828 | replace_bpf_fd: fd_t, | |
| 829 | }; | |
| 830 | ||
| 831 | /// struct used by Cmd.prog_test_run command | |
| 832 | pub const TestAttr = extern struct { | |
| 833 | prog_fd: fd_t, | |
| 834 | retval: u32, | |
| 835 | /// input: len of data_in | |
| 836 | data_size_in: u32, | |
| 837 | /// input/output: len of data_out. returns ENOSPC if data_out is too small. | |
| 838 | data_size_out: u32, | |
| 839 | data_in: u64, | |
| 840 | data_out: u64, | |
| 841 | repeat: u32, | |
| 842 | duration: u32, | |
| 843 | /// input: len of ctx_in | |
| 844 | ctx_size_in: u32, | |
| 845 | /// input/output: len of ctx_out. returns ENOSPC if ctx_out is too small. | |
| 846 | ctx_size_out: u32, | |
| 847 | ctx_in: u64, | |
| 848 | ctx_out: u64, | |
| 849 | }; | |
| 850 | ||
| 851 | /// struct used by Cmd.*_get_*_id commands | |
| 852 | pub const GetIdAttr = extern struct { | |
| 853 | id: extern union { | |
| 854 | start_id: u32, | |
| 855 | prog_id: u32, | |
| 856 | map_id: u32, | |
| 857 | btf_id: u32, | |
| 858 | link_id: u32, | |
| 859 | }, | |
| 860 | next_id: u32, | |
| 861 | open_flags: u32, | |
| 862 | }; | |
| 863 | ||
| 864 | /// struct used by Cmd.obj_get_info_by_fd command | |
| 865 | pub const InfoAttr = extern struct { | |
| 866 | bpf_fd: fd_t, | |
| 867 | info_len: u32, | |
| 868 | info: u64, | |
| 869 | }; | |
| 870 | ||
| 871 | /// struct used by Cmd.prog_query command | |
| 872 | pub const QueryAttr = extern struct { | |
| 873 | /// container object to query | |
| 874 | target_fd: fd_t, | |
| 875 | attach_type: u32, | |
| 876 | query_flags: u32, | |
| 877 | attach_flags: u32, | |
| 878 | prog_ids: u64, | |
| 879 | prog_cnt: u32, | |
| 880 | }; | |
| 881 | ||
| 882 | /// struct used by Cmd.raw_tracepoint_open command | |
| 883 | pub const RawTracepointAttr = extern struct { | |
| 884 | name: u64, | |
| 885 | prog_fd: fd_t, | |
| 886 | }; | |
| 887 | ||
| 888 | /// struct used by Cmd.btf_load command | |
| 889 | pub const BtfLoadAttr = extern struct { | |
| 890 | btf: u64, | |
| 891 | btf_log_buf: u64, | |
| 892 | btf_size: u32, | |
| 893 | btf_log_size: u32, | |
| 894 | btf_log_level: u32, | |
| 895 | }; | |
| 896 | ||
| 897 | pub const TaskFdQueryAttr = extern struct { | |
| 898 | /// input: pid | |
| 899 | pid: pid_t, | |
| 900 | /// input: fd | |
| 901 | fd: fd_t, | |
| 902 | /// input: flags | |
| 903 | flags: u32, | |
| 904 | /// input/output: buf len | |
| 905 | buf_len: u32, | |
| 906 | /// input/output: | |
| 907 | /// tp_name for tracepoint | |
| 908 | /// symbol for kprobe | |
| 909 | /// filename for uprobe | |
| 910 | buf: u64, | |
| 911 | /// output: prod_id | |
| 912 | prog_id: u32, | |
| 913 | /// output: BPF_FD_TYPE | |
| 914 | fd_type: u32, | |
| 915 | /// output: probe_offset | |
| 916 | probe_offset: u64, | |
| 917 | /// output: probe_addr | |
| 918 | probe_addr: u64, | |
| 919 | }; | |
| 920 | ||
| 921 | /// struct used by Cmd.link_create command | |
| 922 | pub const LinkCreateAttr = extern struct { | |
| 923 | /// eBPF program to attach | |
| 924 | prog_fd: fd_t, | |
| 925 | /// object to attach to | |
| 926 | target_fd: fd_t, | |
| 927 | attach_type: u32, | |
| 928 | /// extra flags | |
| 929 | flags: u32, | |
| 930 | }; | |
| 931 | ||
| 932 | /// struct used by Cmd.link_update command | |
| 933 | pub const LinkUpdateAttr = extern struct { | |
| 934 | link_fd: fd_t, | |
| 935 | /// new program to update link with | |
| 936 | new_prog_fd: fd_t, | |
| 937 | /// extra flags | |
| 938 | flags: u32, | |
| 939 | /// expected link's program fd, it is specified only if BPF_F_REPLACE is | |
| 940 | /// set in flags | |
| 941 | old_prog_fd: fd_t, | |
| 942 | }; | |
| 943 | ||
| 944 | /// struct used by Cmd.enable_stats command | |
| 945 | pub const EnableStatsAttr = extern struct { | |
| 946 | type: u32, | |
| 947 | }; | |
| 948 | ||
| 949 | /// struct used by Cmd.iter_create command | |
| 950 | pub const IterCreateAttr = extern struct { | |
| 951 | link_fd: fd_t, | |
| 952 | flags: u32, | |
| 953 | }; | |
| 954 | ||
| 955 | pub const Attr = extern union { | |
| 956 | map_create: MapCreateAttr, | |
| 957 | map_elem: MapElemAttr, | |
| 958 | map_batch: MapBatchAttr, | |
| 959 | prog_load: ProgLoadAttr, | |
| 960 | obj: ObjAttr, | |
| 961 | prog_attach: ProgAttachAttr, | |
| 962 | test_run: TestRunAttr, | |
| 963 | get_id: GetIdAttr, | |
| 964 | info: InfoAttr, | |
| 965 | query: QueryAttr, | |
| 966 | raw_tracepoint: RawTracepointAttr, | |
| 967 | btf_load: BtfLoadAttr, | |
| 968 | task_fd_query: TaskFdQueryAttr, | |
| 969 | link_create: LinkCreateAttr, | |
| 970 | link_update: LinkUpdateAttr, | |
| 971 | enable_stats: EnableStatsAttr, | |
| 972 | iter_create: IterCreateAttr, | |
| 973 | }; |