概述

eBPF 全程是扩展伯克利包过滤(extended Berkeley Packet Filter),用于实现内核不支持的功能,通常情况下你只能通过 ePBF 读取系统的各种信息(主要是系统调用和网络包),少数情况下允许你修改信息(主要是网络包)。

eBPF 有多种开发工具,例如常见的:

关键名词

eBPF Maps

helloworld

  1. [root@liqiang.io]# cat test.py
  2. #!/usr/bin/python
  3. from bcc import BPF
  4. program = r"""
  5. int hello(void *ctx) {
  6. bpf_trace_printk("Hello World!");
  7. return 0;
  8. }
  9. """
  10. b = BPF(text=program)
  11. syscall = b.get_syscall_fnname("execve")
  12. b.attach_kprobe(event=syscall, fn_name="hello")
  13. b.trace_print()

这一段程序中包含了两个部分,分别是:

bpf 系统调用

BCC 提供了很简单的应用层接口,但是,实际上都是通过 bpf 系统调用完成的,而 bpf 系统调用的函数原型为:

  1. int bpf(int cmd, union bpf_attr *attr, unsigned int size);

一些 bpf 系统调用(可以通过 strace -e bpf python3 test.py 看到)的示例:

  1. [root@liqiang.io]# strace -e bpf python3 00_ring_buffer_config.py
  2. bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=2, insns=0x7ffee2cf1330, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(0, 0, 0), prog_flags=0, prog_name="", 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, attach_btf_id=0, attach_prog_fd=0}, 116) = 3
  3. bpf(BPF_BTF_LOAD, {btf="\237\353\1\0\30\0\0\0\0\0\0\0$\5\0\0$\5\0\0\377\3\0\0\1\0\0\0\0\0\0\10"..., btf_log_buf=NULL, btf_size=2363, btf_log_size=0, btf_log_level=0}, 28) = 3
  4. bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=2, insns=0x7ffee2cf0fa0, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(0, 0, 0), prog_flags=0, prog_name="libbpf_nametest"}, 64) = 4
  5. bpf(BPF_MAP_CREATE, {map_type=0x1b /* BPF_MAP_TYPE_??? */, key_size=0, value_size=0, max_entries=4096, map_flags=0, inner_map_fd=0, map_name="output", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0, btf_vmlinux_value_type_id=0}, 72) = 4
  6. bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_HASH, key_size=4, value_size=12, max_entries=10240, map_flags=0, inner_map_fd=0, map_name="config", map_ifindex=0, btf_fd=3, btf_key_type_id=1, btf_value_type_id=4, btf_vmlinux_value_type_id=0}, 72) = 5
  7. bpf(BPF_MAP_UPDATE_ELEM, {map_fd=5, key=0x7fd55bc70f78, value=0x7fd55bc812b8, flags=BPF_ANY}, 32) = 0
  8. bpf(BPF_MAP_UPDATE_ELEM, {map_fd=5, key=0x7fd55bc812b8, value=0x7fd55bc70f78, flags=BPF_ANY}, 32) = 0
  9. bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=41, insns=0x7fd55be38000, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(6, 1, 0), prog_flags=0, prog_name="hello", prog_ifindex=0, expected_attach_type=BPF_CGROUP_INET_INGRESS, prog_btf_fd=3, func_info_rec_size=8, func_info=0x555ef73a9e80, func_info_cnt=1, line_info_rec_size=16, line_info=0x555ef726a9b0, line_info_cnt=21, attach_btf_id=0, attach_prog_fd=0}, 128) = 6
  10. bpf(BPF_OBJ_GET_INFO_BY_FD, {info={bpf_fd=4, info_len=88, info=0x7ffee2cf19d0}}, 16) = 0

tips