authorgravatar for mattnite@protonmail.comMatthew Knight <mattnite@protonmail.com> 2020-08-22 12:08:01-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-22 15:08:01-04:00
log0fa3cfdb4aa04bf92c5d9344cd4d265ccb40e0dc
tree0fe31975cdd13b41adf998308258604225a86a13
parent9605e5363b22874550687f5f96dc6cc8bf462115
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Bpf: move under os/linux instead of bits (#6126)

* 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 imports

4 files changed, 974 insertions(+), 976 deletions(-)

lib/std/os/bits/linux.zig-1
......@@ -24,7 +24,6 @@ pub usingnamespace switch (builtin.arch) {
2424};
2525
2626pub usingnamespace @import("linux/netlink.zig");
27pub const BPF = @import("linux/bpf.zig");
2827
2928const is_mips = builtin.arch.isMIPS();
3029
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.
6usingnamespace std.os;
7const std = @import("../../../std.zig");
8const expectEqual = std.testing.expectEqual;
9const fd_t = std.os.fd_t;
10const pid_t = std.os.pid_t;
11
12// instruction classes
13pub const LD = 0x00;
14pub const LDX = 0x01;
15pub const ST = 0x02;
16pub const STX = 0x03;
17pub const ALU = 0x04;
18pub const JMP = 0x05;
19pub const RET = 0x06;
20pub const MISC = 0x07;
21
22/// 32-bit
23pub const W = 0x00;
24/// 16-bit
25pub const H = 0x08;
26/// 8-bit
27pub const B = 0x10;
28/// 64-bit
29pub const DW = 0x18;
30
31pub const IMM = 0x00;
32pub const ABS = 0x20;
33pub const IND = 0x40;
34pub const MEM = 0x60;
35pub const LEN = 0x80;
36pub const MSH = 0xa0;
37
38// alu fields
39pub const ADD = 0x00;
40pub const SUB = 0x10;
41pub const MUL = 0x20;
42pub const DIV = 0x30;
43pub const OR = 0x40;
44pub const AND = 0x50;
45pub const LSH = 0x60;
46pub const RSH = 0x70;
47pub const NEG = 0x80;
48pub const MOD = 0x90;
49pub const XOR = 0xa0;
50
51// jmp fields
52pub const JA = 0x00;
53pub const JEQ = 0x10;
54pub const JGT = 0x20;
55pub const JGE = 0x30;
56pub const JSET = 0x40;
57
58//#define BPF_SRC(code) ((code) & 0x08)
59pub const K = 0x00;
60pub const X = 0x08;
61
62pub const MAXINSNS = 4096;
63
64// instruction classes
65/// jmp mode in word width
66pub const JMP32 = 0x06;
67/// alu mode in double word width
68pub const ALU64 = 0x07;
69
70// ld/ldx fields
71/// exclusive add
72pub const XADD = 0xc0;
73
74// alu/jmp fields
75/// mov reg to reg
76pub const MOV = 0xb0;
77/// sign extending arithmetic shift right */
78pub const ARSH = 0xc0;
79
80// change endianness of a register
81/// flags for endianness conversion:
82pub const END = 0xd0;
83/// convert to little-endian */
84pub const TO_LE = 0x00;
85/// convert to big-endian
86pub const TO_BE = 0x08;
87pub const FROM_LE = TO_LE;
88pub const FROM_BE = TO_BE;
89
90// jmp encodings
91/// jump != *
92pub const JNE = 0x50;
93/// LT is unsigned, '<'
94pub const JLT = 0xa0;
95/// LE is unsigned, '<=' *
96pub const JLE = 0xb0;
97/// SGT is signed '>', GT in x86
98pub const JSGT = 0x60;
99/// SGE is signed '>=', GE in x86
100pub const JSGE = 0x70;
101/// SLT is signed, '<'
102pub const JSLT = 0xc0;
103/// SLE is signed, '<='
104pub const JSLE = 0xd0;
105/// function call
106pub const CALL = 0x80;
107/// function return
108pub 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.
112pub 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.
115pub const F_ALLOW_MULTI = 0x2;
116/// Flag for prog_attach command.
117pub 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.
122pub 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.
133pub 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.
150pub 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
160pub const PSEUDO_MAP_FD = 1;
161pub 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
165pub const PSEUDO_CALL = 1;
166
167/// flag for BPF_MAP_UPDATE_ELEM command. create new element or update existing
168pub const ANY = 0;
169/// flag for BPF_MAP_UPDATE_ELEM command. create new element if it didn't exist
170pub const NOEXIST = 1;
171/// flag for BPF_MAP_UPDATE_ELEM command. update existing element
172pub const EXIST = 2;
173/// flag for BPF_MAP_UPDATE_ELEM command. spin_lock-ed map_lookup/map_update
174pub const F_LOCK = 4;
175
176/// flag for BPF_MAP_CREATE command */
177pub 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.
182pub const BPF_F_NO_COMMON_LRU = 0x2;
183/// flag for BPF_MAP_CREATE command. Specify numa node during map creation
184pub const BPF_F_NUMA_NODE = 0x4;
185/// flag for BPF_MAP_CREATE command. Flags for BPF object read access from
186/// syscall side
187pub const BPF_F_RDONLY = 0x8;
188/// flag for BPF_MAP_CREATE command. Flags for BPF object write access from
189/// syscall side
190pub const BPF_F_WRONLY = 0x10;
191/// flag for BPF_MAP_CREATE command. Flag for stack_map, store build_id+offset
192/// instead of pointer
193pub 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.
196pub const BPF_F_ZERO_SEED = 0x40;
197/// flag for BPF_MAP_CREATE command Flags for accessing BPF object from program
198/// side.
199pub const BPF_F_RDONLY_PROG = 0x80;
200/// flag for BPF_MAP_CREATE command. Flags for accessing BPF object from program
201/// side.
202pub const BPF_F_WRONLY_PROG = 0x100;
203/// flag for BPF_MAP_CREATE command. Clone map from listener for newly accepted
204/// socket
205pub const BPF_F_CLONE = 0x200;
206/// flag for BPF_MAP_CREATE command. Enable memory-mapping BPF map
207pub const BPF_F_MMAPABLE = 0x400;
208
209/// These values correspond to "syscalls" within the BPF program's environment
210pub 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
334pub 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
513fn expect_insn(insn: Insn, val: u64) void {
514 expectEqual(@bitCast(u64, insn), val);
515}
516
517test "insn bitsize" {
518 expectEqual(@bitSizeOf(Insn), 64);
519}
520
521// mov instructions
522test "mov imm" {
523 expect_insn(Insn.mov(.r1, 1), 0x00000001000001b7);
524}
525
526test "mov reg" {
527 expect_insn(Insn.mov(.r6, .r1), 0x00000000000016bf);
528}
529
530// alu instructions
531test "add imm" {
532 expect_insn(Insn.add(.r2, -4), 0xfffffffc00000207);
533}
534
535// ld instructions
536test "ld_abs" {
537 expect_insn(Insn.ld_abs(.byte, 42), 0x0000002a00000030);
538}
539
540test "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
546test "stx_mem" {
547 expect_insn(Insn.stx_mem(.word, .r10, .r0, -4), 0x00000000fffc0a63);
548}
549
550test "xadd" {
551 expect_insn(Insn.xadd(.r0, .r1), 0x00000000000010db);
552}
553
554// jmp instructions
555test "jeq imm" {
556 expect_insn(Insn.jeq(.r0, 0, 2), 0x0000000000020015);
557}
558
559// other instructions
560test "call" {
561 expect_insn(Insn.call(.map_lookup_elem), 0x0000000100000085);
562}
563
564test "exit" {
565 expect_insn(Insn.exit(), 0x0000000000000095);
566}
567
568pub 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
607pub 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
639pub 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
673pub 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
715const obj_name_len = 16;
716/// struct used by Cmd.map_create command
717pub 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
746pub 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
757pub 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
774pub 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
814pub 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
821pub 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
834pub 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
854pub 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
867pub 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
874pub 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
885pub const RawTracepointAttr = extern struct {
886 name: u64,
887 prog_fd: fd_t,
888};
889
890/// struct used by Cmd.btf_load command
891pub 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
899pub 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
924pub 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
935pub 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
947pub const EnableStatsAttr = extern struct {
948 type: u32,
949};
950
951/// struct used by Cmd.iter_create command
952pub const IterCreateAttr = extern struct {
953 link_fd: fd_t,
954 flags: u32,
955};
956
957pub 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) {
2929};
3030pub usingnamespace @import("bits.zig");
3131pub const tls = @import("linux/tls.zig");
32pub const BPF = @import("linux/bpf.zig");
3233
3334/// Set by startup code, used by `getauxval`.
3435pub 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.
6usingnamespace std.os;
7const std = @import("../../std.zig");
8const expectEqual = std.testing.expectEqual;
9
10// instruction classes
11pub const LD = 0x00;
12pub const LDX = 0x01;
13pub const ST = 0x02;
14pub const STX = 0x03;
15pub const ALU = 0x04;
16pub const JMP = 0x05;
17pub const RET = 0x06;
18pub const MISC = 0x07;
19
20/// 32-bit
21pub const W = 0x00;
22/// 16-bit
23pub const H = 0x08;
24/// 8-bit
25pub const B = 0x10;
26/// 64-bit
27pub const DW = 0x18;
28
29pub const IMM = 0x00;
30pub const ABS = 0x20;
31pub const IND = 0x40;
32pub const MEM = 0x60;
33pub const LEN = 0x80;
34pub const MSH = 0xa0;
35
36// alu fields
37pub const ADD = 0x00;
38pub const SUB = 0x10;
39pub const MUL = 0x20;
40pub const DIV = 0x30;
41pub const OR = 0x40;
42pub const AND = 0x50;
43pub const LSH = 0x60;
44pub const RSH = 0x70;
45pub const NEG = 0x80;
46pub const MOD = 0x90;
47pub const XOR = 0xa0;
48
49// jmp fields
50pub const JA = 0x00;
51pub const JEQ = 0x10;
52pub const JGT = 0x20;
53pub const JGE = 0x30;
54pub const JSET = 0x40;
55
56//#define BPF_SRC(code) ((code) & 0x08)
57pub const K = 0x00;
58pub const X = 0x08;
59
60pub const MAXINSNS = 4096;
61
62// instruction classes
63/// jmp mode in word width
64pub const JMP32 = 0x06;
65/// alu mode in double word width
66pub const ALU64 = 0x07;
67
68// ld/ldx fields
69/// exclusive add
70pub const XADD = 0xc0;
71
72// alu/jmp fields
73/// mov reg to reg
74pub const MOV = 0xb0;
75/// sign extending arithmetic shift right */
76pub const ARSH = 0xc0;
77
78// change endianness of a register
79/// flags for endianness conversion:
80pub const END = 0xd0;
81/// convert to little-endian */
82pub const TO_LE = 0x00;
83/// convert to big-endian
84pub const TO_BE = 0x08;
85pub const FROM_LE = TO_LE;
86pub const FROM_BE = TO_BE;
87
88// jmp encodings
89/// jump != *
90pub const JNE = 0x50;
91/// LT is unsigned, '<'
92pub const JLT = 0xa0;
93/// LE is unsigned, '<=' *
94pub const JLE = 0xb0;
95/// SGT is signed '>', GT in x86
96pub const JSGT = 0x60;
97/// SGE is signed '>=', GE in x86
98pub const JSGE = 0x70;
99/// SLT is signed, '<'
100pub const JSLT = 0xc0;
101/// SLE is signed, '<='
102pub const JSLE = 0xd0;
103/// function call
104pub const CALL = 0x80;
105/// function return
106pub 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.
110pub 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.
113pub const F_ALLOW_MULTI = 0x2;
114/// Flag for prog_attach command.
115pub 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.
120pub 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.
131pub 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.
148pub 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
158pub const PSEUDO_MAP_FD = 1;
159pub 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
163pub const PSEUDO_CALL = 1;
164
165/// flag for BPF_MAP_UPDATE_ELEM command. create new element or update existing
166pub const ANY = 0;
167/// flag for BPF_MAP_UPDATE_ELEM command. create new element if it didn't exist
168pub const NOEXIST = 1;
169/// flag for BPF_MAP_UPDATE_ELEM command. update existing element
170pub const EXIST = 2;
171/// flag for BPF_MAP_UPDATE_ELEM command. spin_lock-ed map_lookup/map_update
172pub const F_LOCK = 4;
173
174/// flag for BPF_MAP_CREATE command */
175pub 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.
180pub const BPF_F_NO_COMMON_LRU = 0x2;
181/// flag for BPF_MAP_CREATE command. Specify numa node during map creation
182pub const BPF_F_NUMA_NODE = 0x4;
183/// flag for BPF_MAP_CREATE command. Flags for BPF object read access from
184/// syscall side
185pub const BPF_F_RDONLY = 0x8;
186/// flag for BPF_MAP_CREATE command. Flags for BPF object write access from
187/// syscall side
188pub const BPF_F_WRONLY = 0x10;
189/// flag for BPF_MAP_CREATE command. Flag for stack_map, store build_id+offset
190/// instead of pointer
191pub 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.
194pub const BPF_F_ZERO_SEED = 0x40;
195/// flag for BPF_MAP_CREATE command Flags for accessing BPF object from program
196/// side.
197pub const BPF_F_RDONLY_PROG = 0x80;
198/// flag for BPF_MAP_CREATE command. Flags for accessing BPF object from program
199/// side.
200pub const BPF_F_WRONLY_PROG = 0x100;
201/// flag for BPF_MAP_CREATE command. Clone map from listener for newly accepted
202/// socket
203pub const BPF_F_CLONE = 0x200;
204/// flag for BPF_MAP_CREATE command. Enable memory-mapping BPF map
205pub const BPF_F_MMAPABLE = 0x400;
206
207/// These values correspond to "syscalls" within the BPF program's environment
208pub 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
332pub 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
511fn expect_insn(insn: Insn, val: u64) void {
512 expectEqual(@bitCast(u64, insn), val);
513}
514
515test "insn bitsize" {
516 expectEqual(@bitSizeOf(Insn), 64);
517}
518
519// mov instructions
520test "mov imm" {
521 expect_insn(Insn.mov(.r1, 1), 0x00000001000001b7);
522}
523
524test "mov reg" {
525 expect_insn(Insn.mov(.r6, .r1), 0x00000000000016bf);
526}
527
528// alu instructions
529test "add imm" {
530 expect_insn(Insn.add(.r2, -4), 0xfffffffc00000207);
531}
532
533// ld instructions
534test "ld_abs" {
535 expect_insn(Insn.ld_abs(.byte, 42), 0x0000002a00000030);
536}
537
538test "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
544test "stx_mem" {
545 expect_insn(Insn.stx_mem(.word, .r10, .r0, -4), 0x00000000fffc0a63);
546}
547
548test "xadd" {
549 expect_insn(Insn.xadd(.r0, .r1), 0x00000000000010db);
550}
551
552// jmp instructions
553test "jeq imm" {
554 expect_insn(Insn.jeq(.r0, 0, 2), 0x0000000000020015);
555}
556
557// other instructions
558test "call" {
559 expect_insn(Insn.call(.map_lookup_elem), 0x0000000100000085);
560}
561
562test "exit" {
563 expect_insn(Insn.exit(), 0x0000000000000095);
564}
565
566pub 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
605pub 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
637pub 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
671pub 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
713const obj_name_len = 16;
714/// struct used by Cmd.map_create command
715pub 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
744pub 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
755pub 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
772pub 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
812pub 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
819pub 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
832pub 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
852pub 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
865pub 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
872pub 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
883pub const RawTracepointAttr = extern struct {
884 name: u64,
885 prog_fd: fd_t,
886};
887
888/// struct used by Cmd.btf_load command
889pub 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
897pub 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
922pub 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
933pub 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
945pub const EnableStatsAttr = extern struct {
946 type: u32,
947};
948
949/// struct used by Cmd.iter_create command
950pub const IterCreateAttr = extern struct {
951 link_fd: fd_t,
952 flags: u32,
953};
954
955pub 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};