Please enable Javascript to view the contents

eBPF API

 ·  ☕ 1 åˆ†é’Ÿ

User Space API

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# strace -ebpf ./execsnoop 
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_PERF_EVENT_ARRAY, key_size=4, value_size=4, max_entries=4, map_flags=0, inner_map_fd=0, map_name="events", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0}, 120) = -1 EPERM (Operation not permitted)
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_PERF_EVENT_ARRAY, key_size=4, value_size=4, max_entries=4, map_flags=0, inner_map_fd=0, map_name="events", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0}, 120) = 3
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=508, insns=0x7fbdc7157000, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(5, 3, 18), prog_flags=0, prog_name="syscall__execve", prog_ifindex=0, expected_attach_type=BPF_CGROUP_INET_INGRESS, prog_btf_fd=0, func_info_rec_size=0, func_info=NULL, func_info_cnt=0, line_info_rec_size=0, line_info=NULL, line_info_cnt=0}, 120) = 4
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=60, insns=0x7fbdc71587d8, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(5, 3, 18), prog_flags=0, prog_name="do_ret_sys_exec", prog_ifindex=0, expected_attach_type=BPF_CGROUP_INET_INGRESS, prog_btf_fd=0, func_info_rec_size=0, func_info=NULL, func_info_cnt=0, line_info_rec_size=0, line_info=NULL, line_info_cnt=0}, 120) = 6
PCOMM            PID    PPID   RET ARGS
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x7fbdbd440780, value=0x7fbdbd4406f8, flags=BPF_ANY}, 120) = 0
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x7fbdbd440808, value=0x7fbdbd4406f8, flags=BPF_ANY}, 120) = 0
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x7fbdbd440890, value=0x7fbdbd4406f8, flags=BPF_ANY}, 120) = 0
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x7fbdbd440918, value=0x7fbdbd4406f8, flags=BPF_ANY}, 120) = 0
sh               12945  3906     0 /bin/sh -c ls -l /proc/[0-9]*/fd/[0-9]* | grep socket:

BPF 并发控制

使用 BPF_MAP_TYPE_PERCPU_HASH

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# strace -febpf bpftrace -e 'k:vfs_read { @ = count(); }'

bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_PERCPU_HASH, key_size=8, value_size=8, max_entries=4096, map_flags=0, inner_map_fd=0, map_name="@", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0}, 120) = -1 EINVAL (Invalid argument)
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_PERCPU_HASH, key_size=8, value_size=8, max_entries=4096, map_flags=0, inner_map_fd=0, map_name="", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0}, 120) = 3
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_PERF_EVENT_ARRAY, key_size=4, value_size=4, max_entries=4, map_flags=0, inner_map_fd=0, map_name="printf", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0}, 120) = 4
Attaching 1 probe...
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=4, key=0x7ffd6117da44, value=0x7ffd6117da34, flags=BPF_ANY}, 120) = 0
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=4, key=0x7ffd6117da44, value=0x7ffd6117da34, flags=BPF_ANY}, 120) = 0
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=4, key=0x7ffd6117da44, value=0x7ffd6117da34, flags=BPF_ANY}, 120) = 0
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=4, key=0x7ffd6117da44, value=0x7ffd6117da34, flags=BPF_ANY}, 120) = 0
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=22, insns=0x7f88e2c51000, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(5, 3, 18), prog_flags=0, prog_name="vfs_read", prog_ifindex=0, expected_attach_type=BPF_CGROUP_INET_INGRESS, prog_btf_fd=0, func_info_rec_size=0, func_info=NULL, func_info_cnt=0, line_info_rec_size=0, line_info=NULL, line_info_cnt=0}, 120) = 11
^Cstrace: Process 21764 detached

BPF sysfs Interface

从 Kernel 4.4 后,支持虚拟文件: /sys/fs/bpf。有了它, BPF 程序可以持久运行而不需要 BPF 主进程存在。它也让用户进程可以读写 BPF maps。这种能力叫pinning。这个能力在 Cilium 中大量使用。

参考

[BPF Performance Tools]

分享

Mark Zhu
作者
Mark Zhu
Old Developer