eBPF 系统调用

作者:

关于 bpf 系统调用的主要信息可在 man-pagesbpf(2) 中找到。

bpf() 子命令参考

bpf() 系统调用要执行的操作由 cmd 参数确定。每个操作都带有一个伴随参数,通过 attr 提供,该参数是指向 bpf_attr 类型联合的指针(参见下文)。size 参数是 attr 指向的联合的大小。

BPF_MAP_CREATE
描述

创建一个映射并返回一个引用该映射的文件描述符。新文件描述符的 close-on-exec 文件描述符标志(参见 fcntl(2))会自动启用。

BPF_MAP_CREATE 返回的文件描述符应用 close(2) 将删除该映射(但请参阅注意事项)。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_MAP_LOOKUP_ELEM
描述

map_fd 文件描述符所引用的映射中,根据给定的 key 查找元素。

flags 参数可以指定为以下之一:

BPF_F_LOCK

查找自旋锁映射的值而不返回锁。如果元素包含自旋锁,则必须指定此项。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_MAP_UPDATE_ELEM
描述

在指定的映射中创建或更新元素(键/值对)。

flags 参数应指定为以下之一:

BPF_ANY

创建新元素或更新现有元素。

BPF_NOEXIST

仅当元素不存在时才创建新元素。

BPF_EXIST

更新现有元素。

BPF_F_LOCK

更新一个自旋锁(spin_lock)映射元素。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

可能将 errno 设置为 EINVALEPERMENOMEME2BIGEEXISTENOENT

E2BIG

映射中的元素数量达到了映射创建时指定的 max_entries 限制。

EEXIST

如果 flags 指定 BPF_NOEXIST 且具有 key 的元素已存在于映射中。

ENOENT

如果 flags 指定 BPF_EXIST 且具有 key 的元素不存在于映射中。

BPF_MAP_DELETE_ELEM
描述

在指定的映射中按键查找并删除元素。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_MAP_GET_NEXT_KEY
描述

在指定映射中按键查找元素并返回下一个元素的键。可用于遍历映射中的所有元素。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

以下情况可用于遍历映射中的所有元素:

  • 如果未找到 key,操作返回零并将 next_key 指针设置为第一个元素的键。

  • 如果找到 key,操作返回零并将 next_key 指针设置为下一个元素的键。

  • 如果 key 是最后一个元素,返回 -1 且 errno 设置为 ENOENT

错误时可能将 errno 设置为 ENOMEMEFAULTEPERMEINVAL

BPF_PROG_LOAD
描述

验证并加载 eBPF 程序,返回与程序关联的新文件描述符。

BPF_PROG_LOAD 返回的文件描述符应用 close(2) 将卸载 eBPF 程序(但请参阅注意事项)。

新文件描述符的 close-on-exec 文件描述符标志(参见 fcntl(2))会自动启用。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_OBJ_PIN
描述

将由指定 bpf_fd 引用的 eBPF 程序或映射固定到文件系统上的指定 pathname

pathname 参数不得包含点(“.”)。

成功时,pathname 保留对 eBPF 对象的引用,防止在原始 bpf_fd 关闭时对象被解除分配。这允许 eBPF 对象在 close(bpf_fd) 之后以及父进程的生命周期之后继续存在。

pathname 应用 unlink(2) 或类似调用将对象从文件系统中解除固定,从而移除引用。如果没有其他文件描述符或文件系统节点引用同一对象,它将被解除分配(参见 NOTES)。

pathname 父目录的文件系统类型必须是 BPF_FS_MAGIC

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_OBJ_GET
描述

为固定到指定 pathname 的 eBPF 对象打开文件描述符。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_PROG_ATTACH
描述

将 eBPF 程序附加到指定 attach_type 挂钩处的 target_fd

attach_type 指定了将程序附加到的 eBPF 附加点,并且必须是 bpf_attach_type 之一(参见下文)。

attach_bpf_fd 必须是已加载的 cgroup、流分解器、LIRC、sockmap 或 sock_ops 类型的 eBPF 程序的有效文件描述符,对应于指定的 attach_type

target_fd 必须是内核对象的有效文件描述符,该内核对象取决于 attach_bpf_fd 的附加类型

BPF_PROG_TYPE_CGROUP_DEVICE, BPF_PROG_TYPE_CGROUP_SKB, BPF_PROG_TYPE_CGROUP_SOCK, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_PROG_TYPE_SOCK_OPS

启用 eBPF 控制器的控制组 v2 层级结构。需要内核编译时带 CONFIG_CGROUP_BPF

BPF_PROG_TYPE_FLOW_DISSECTOR

网络命名空间(例如 /proc/self/ns/net)。

BPF_PROG_TYPE_LIRC_MODE2

LIRC 设备路径(例如 /dev/lircN)。需要内核编译时带 CONFIG_BPF_LIRC_MODE2

BPF_PROG_TYPE_SK_SKB, BPF_PROG_TYPE_SK_MSG

套接字类型的 eBPF 映射(例如 BPF_MAP_TYPE_SOCKHASH)。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_PROG_DETACH
描述

attach_type 指定的挂钩处分离与 target_fd 关联的 eBPF 程序。该程序必须已通过 BPF_PROG_ATTACH 附加。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_PROG_TEST_RUN
描述

针对提供的程序上下文 ctx_in 和数据 data_in,运行与 prog_fd 关联的 eBPF 程序 repeat 次,并返回修改后的程序上下文 ctx_outdata_out(例如,数据包数据)、执行结果 retval 和测试运行的 duration

作为输入和输出参数提供的缓冲区 ctx_inctx_outdata_indata_out 的大小必须在相应的变量 ctx_size_inctx_size_outdata_size_in 和/或 data_size_out 中提供。如果这些参数中的任何一个未提供(即设置为 NULL),则相应的 size 字段必须为零。

某些程序类型有特定要求

BPF_PROG_TYPE_SK_LOOKUP

data_indata_out 必须为 NULL。

BPF_PROG_TYPE_RAW_TRACEPOINT, BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE

ctx_out, data_indata_out 必须为 NULL。repeat 必须为零。

BPF_PROG_RUN 是 BPF_PROG_TEST_RUN 的别名。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

ENOSPC

data_size_outctx_size_out 太小。

ENOTSUPP

此命令不受 prog_fd 所引用程序的程序类型支持。

BPF_PROG_GET_NEXT_ID
描述

获取当前加载到内核中的下一个 eBPF 程序。

查找 ID 大于 start_id 的 eBPF 程序,并在成功时更新 next_id。如果没有其他 ID 高于 start_id 的 eBPF 程序,则返回 -1 并将 errno 设置为 ENOENT

返回

成功时返回零。发生错误或没有剩余 ID 时,返回 -1 并适当设置 errno

BPF_MAP_GET_NEXT_ID
描述

获取当前加载到内核中的下一个 eBPF 映射。

查找 ID 大于 start_id 的 eBPF 映射,并在成功时更新 next_id。如果没有其他 ID 高于 start_id 的 eBPF 映射,则返回 -1 并将 errno 设置为 ENOENT

返回

成功时返回零。发生错误或没有剩余 ID 时,返回 -1 并适当设置 errno

BPF_PROG_GET_FD_BY_ID
描述

打开与 prog_id 对应的 eBPF 程序的文件描述符。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_MAP_GET_FD_BY_ID
描述

打开与 map_id 对应的 eBPF 映射的文件描述符。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_OBJ_GET_INFO_BY_FD
描述

获取有关与 bpf_fd 对应的 eBPF 对象的信息。

根据 bpf_fd 的 eBPF 对象类型,填充 info 最多 info_len 字节,其格式将是以下之一:

  • struct bpf_prog_info

  • struct bpf_map_info

  • struct bpf_btf_info

  • struct bpf_link_info

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_PROG_QUERY
描述

获取与指定 attach_type 挂钩关联的 eBPF 程序信息。

target_fd 必须是内核对象的有效文件描述符,该内核对象取决于 attach_bpf_fd 的附加类型

BPF_PROG_TYPE_CGROUP_DEVICE, BPF_PROG_TYPE_CGROUP_SKB, BPF_PROG_TYPE_CGROUP_SOCK, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_PROG_TYPE_SOCK_OPS

启用 eBPF 控制器的控制组 v2 层级结构。需要内核编译时带 CONFIG_CGROUP_BPF

BPF_PROG_TYPE_FLOW_DISSECTOR

网络命名空间(例如 /proc/self/ns/net)。

BPF_PROG_TYPE_LIRC_MODE2

LIRC 设备路径(例如 /dev/lircN)。需要内核编译时带 CONFIG_BPF_LIRC_MODE2

BPF_PROG_QUERY 总是获取附加程序的数量以及用于附加这些程序的 attach_flags。此外,如果 prog_ids 非零且附加程序的数量小于 prog_cnt,则用 target_fd 处附加的 eBPF 程序的 ID 填充 prog_ids

以下标志可能会改变结果

BPF_F_QUERY_EFFECTIVE

仅返回有关当前在指定 target_fd 处有效的程序的信息。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_RAW_TRACEPOINT_OPEN
描述

将 eBPF 程序附加到追踪点 name,以原始形式访问追踪点的内核内部参数。

prog_fd 必须是与类型为 BPF_PROG_TYPE_RAW_TRACEPOINT 的已加载 eBPF 程序关联的有效文件描述符。

对于暴露给相应 eBPF 程序的追踪点参数内容,不提供任何 ABI 保证。

BPF_RAW_TRACEPOINT_OPEN 返回的文件描述符应用 close(2) 将删除映射(但请参阅注意事项)。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_BTF_LOAD
描述

验证并将 BPF 类型格式(BTF)元数据加载到内核中,返回一个与该元数据关联的新文件描述符。BTF 的详细信息请参见 https://linuxkernel.org.cn/doc/html/latest/bpf/btf.html

btf 参数必须指向有效内存,提供 btf_size 字节的 BTF 二进制元数据。

返回的文件描述符可以传递给其他 bpf() 子命令,例如 BPF_PROG_LOADBPF_MAP_CREATE,以将 BTF 与这些对象关联起来。

BPF_PROG_LOAD 类似,BPF_BTF_LOAD 具有可选参数,用于指定 btf_log_bufbtf_log_sizebtf_log_level,允许内核返回有关 BTF 验证过程的自由格式日志输出。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_BTF_GET_FD_BY_ID
描述

为与 btf_id 对应的 BPF 类型格式 (BTF) 打开文件描述符。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_TASK_FD_QUERY
描述

获取有关与由 pidfd 标识的目标进程关联的 eBPF 程序的信息。

如果 pidfd 与 tracepoint、kprobe 或 uprobe perf 事件关联,则 prog_idfd_type 将填充 eBPF 程序 ID 和类型为 bpf_task_fd_type 的文件描述符类型。如果与 kprobe 或 uprobe 关联,则 probe_offsetprobe_addr 也将填充。可选地,如果提供了 buf,则 buf 中最多 buf_len 字节将填充 tracepoint、kprobe 或 uprobe 的名称。

结果 prog_id 可以使用 BPF_PROG_GET_FD_BY_IDBPF_OBJ_GET_INFO_BY_FD 进行更深入的内省。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_MAP_LOOKUP_AND_DELETE_ELEM
描述

fd 文件描述符引用的映射中查找给定 key 的元素,如果找到则删除该元素。

对于 BPF_MAP_TYPE_QUEUEBPF_MAP_TYPE_STACK 映射类型,flags 参数需要设置为 0,但对于其他映射类型,可以指定为:

BPF_F_LOCK

查找并删除自旋锁映射的值而不返回锁。如果元素包含自旋锁,则必须指定此项。

BPF_MAP_TYPE_QUEUEBPF_MAP_TYPE_STACK 映射类型将此命令实现为“pop”操作,删除顶部元素而不是与 key 对应的元素。当对这些映射类型发出此操作时,keykey_len 参数应清零。

此命令仅对以下映射类型有效: * BPF_MAP_TYPE_QUEUE * BPF_MAP_TYPE_STACK * BPF_MAP_TYPE_HASH * BPF_MAP_TYPE_PERCPU_HASH * BPF_MAP_TYPE_LRU_HASH * BPF_MAP_TYPE_LRU_PERCPU_HASH

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_MAP_FREEZE
描述

冻结指定映射的权限。

可以通过传递零 flags 来冻结写入权限。成功后,未来的系统调用调用将不能更改 map_fd 的映射状态。eBPF 程序对冻结的映射仍然可以执行写入操作。

不支持 BPF_MAP_TYPE_STRUCT_OPS 类型的映射。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_BTF_GET_NEXT_ID
描述

获取当前加载到内核中的下一个 BPF 类型格式(BTF)对象。

查找 ID 大于 start_id 的 BTF 对象,并在成功时更新 next_id。如果没有其他 ID 高于 start_id 的 BTF 对象,则返回 -1 并将 errno 设置为 ENOENT

返回

成功时返回零。发生错误或没有剩余 ID 时,返回 -1 并适当设置 errno

BPF_MAP_LOOKUP_BATCH
描述

迭代并获取映射中的多个元素。

使用两个不透明值 in_batchout_batch 来管理批处理操作。最初,in_batch 必须设置为 NULL 以开始批处理操作。在每次后续的 BPF_MAP_LOOKUP_BATCH 之后,调用者应将结果 out_batch 作为 in_batch 传递,以从当前点继续迭代。in_batchout_batch 都必须指向足够大的内存以容纳一个键,但 BPF_MAP_TYPE_{HASH, PERCPU_HASH, LRU_HASH, LRU_PERCPU_HASH} 类型的映射除外,对于这些映射,批处理参数的宽度必须至少为 4 字节,无论键大小如何。

keysvalues 是输出参数,它们必须指向足够大的内存,以根据映射 map_fd 的键和值大小容纳 count 个项目。keys 缓冲区的大小必须为 key_size * countvalues 缓冲区的大小必须为 value_size * count

elem_flags 参数可以指定为以下之一:

BPF_F_LOCK

查找自旋锁映射的值而不返回锁。如果元素包含自旋锁,则必须指定此项。

成功时,count 个元素从映射复制到用户缓冲区,键复制到 keys,值复制到 values 中对应的索引。

如果返回错误且 errno 不是 EFAULT,则 count 设置为成功处理的元素数量。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

可能将 errno 设置为 ENOSPC,表示在迭代基于哈希的映射类型时,keysvalues 太小,无法转储整个桶。

BPF_MAP_LOOKUP_AND_DELETE_BATCH
描述

迭代并删除映射中的所有元素。

此操作的行为与 BPF_MAP_LOOKUP_BATCH 相同,但有两个例外:

  • 每个成功返回的元素也会从映射中删除。这至少是 count 个元素。注意,count 既是输入参数也是输出参数。

  • 当返回时 errno 设置为 EFAULT,最多 count 个元素可能已被删除,但未返回已删除元素的键和值。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_MAP_UPDATE_BATCH
描述

key 批量更新映射中的多个元素。

keysvalues 是输入参数,它们必须指向足够大的内存,以根据映射 map_fd 的键和值大小容纳 count 个项目。keys 缓冲区的大小必须为 key_size * countvalues 缓冲区的大小必须为 value_size * count

keys 中指定的每个元素都会依次更新为 values 中相应索引的值。in_batchout_batch 参数被忽略,应清零。

elem_flags 参数应指定为以下之一

BPF_ANY

创建新元素或更新现有元素。

BPF_NOEXIST

仅当新元素不存在时才创建。

BPF_EXIST

更新现有元素。

BPF_F_LOCK

更新自旋锁映射元素。如果映射值包含自旋锁,则必须指定此项。

成功时,映射中的 count 个元素被更新。

如果返回错误且 errno 不是 EFAULT,则 count 设置为成功处理的元素数量。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

可能将 errno 设置为 EINVALEPERMENOMEME2BIGE2BIG 表示映射中的元素数量已达到映射创建时指定的 max_entries 限制。

在特定情况下可能将 errno 设置为以下错误代码之一

EEXIST

如果 flags 指定 BPF_NOEXIST 且具有 key 的元素已存在于映射中。

ENOENT

如果 flags 指定 BPF_EXIST 且具有 key 的元素不存在于映射中。

BPF_MAP_DELETE_BATCH
描述

key 批量删除映射中的多个元素。

keys 参数是一个输入参数,它必须指向足够大的内存,以根据映射 map_fd 的键大小容纳 count 个项目,即 key_size * count

keys 中指定的每个元素将依次删除。in_batchout_batchvalues 参数将被忽略并应清零。

elem_flags 参数可以指定为以下之一:

BPF_F_LOCK

查找自旋锁映射的值而不返回锁。如果元素包含自旋锁,则必须指定此项。

成功时,映射中的 count 个元素被更新。

如果返回错误且 errno 不是 EFAULT,则 count 设置为成功处理的元素数量。如果 errnoEFAULT,则最多 count 个元素可能已被删除。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_LINK_CREATE
描述

将 eBPF 程序附加到指定 attach_type 挂钩处的 target_fd,并返回用于管理链接的文件描述符句柄。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_LINK_UPDATE
描述

将指定 link_fd 中的 eBPF 程序更新为 new_prog_fd

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_LINK_GET_FD_BY_ID
描述

打开与 link_id 对应的 eBPF 链接的文件描述符。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_LINK_GET_NEXT_ID
描述

获取当前加载到内核中的下一个 eBPF 链接。

查找 ID 大于 start_id 的 eBPF 链接,并在成功时更新 next_id。如果没有其他 ID 高于 start_id 的 eBPF 链接,则返回 -1 并将 errno 设置为 ENOENT

返回

成功时返回零。发生错误或没有剩余 ID 时,返回 -1 并适当设置 errno

BPF_ENABLE_STATS
描述

启用 eBPF 运行时统计信息收集。

eBPF 运行时的统计信息收集默认禁用,以最大程度地减少相应的性能开销。此命令会全局启用统计信息。

多个程序可以独立启用统计信息。在收集到所需的统计信息后,可以通过对本函数返回的文件描述符调用 close(2) 来再次禁用 eBPF 运行时统计信息。只有当通过此子命令先前调用返回的所有未关闭的文件描述符都关闭后,统计信息才会在系统范围内禁用。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_ITER_CREATE
描述

在指定的 link_fd(先前使用 BPF_LINK_CREATE 创建)之上创建一个迭代器,并返回一个可用于触发迭代的文件描述符。

如果结果文件描述符使用 BPF_OBJ_PIN 固定到文件系统,则对该路径的后续 read(2) 系统调用将触发迭代器使用附加到 link_fd 的 eBPF 程序读取内核状态。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

BPF_LINK_DETACH
描述

强制将指定的 link_fd 从其对应的附着点分离。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_PROG_BIND_MAP
描述

将映射绑定到 eBPF 程序的生命周期。

map_fd 标识的映射绑定到由 prog_fd 标识的程序,并且仅当 prog_fd 释放时才释放。这可用于元数据应与程序关联的情况,否则该程序不包含对映射的任何引用(例如,嵌入在 eBPF 程序指令中)。

返回

成功时返回零。发生错误时,返回 -1 并适当设置 errno

BPF_TOKEN_CREATE
描述

创建 BPF 令牌,其中嵌入了有关其允许哪些 BPF 相关功能的信息:- 允许的 bpf() 系统调用命令集;- 如果允许 BPF_MAP_CREATE 命令,则允许使用该命令创建的 BPF 映射类型集;- 如果允许 BPF_PROG_LOAD 命令,则允许使用该命令加载的 BPF 程序类型和 BPF 程序附加类型集。

BPF 令牌是从 BPF FS 的实例创建(派生)的,假设它已指定了必要的委派挂载选项。此 BPF 令牌可以作为额外参数传递给各种 bpf() 系统调用命令,以授予非特权进程 BPF 子系统功能。

BPF 令牌创建后,会与派生它的 BPF FS 实例(超级块)的拥有用户命名空间“关联”,后续使用 BPF 令牌执行的 BPF 操作将在该用户命名空间内执行能力检查(即 CAP_BPF、CAP_PERFMON、CAP_NET_ADMIN、CAP_SYS_ADMIN)。如果没有 BPF 令牌,这些能力必须在 init 用户命名空间中授予,这使得 bpf() 系统调用在大多数情况下与用户命名空间不兼容。

返回

一个新的文件描述符(一个非负整数),如果发生错误则返回 -1(此时,errno 会被适当地设置)。

注意事项

eBPF 对象(映射和程序)可以在进程之间共享。

  • fork(2) 后,子进程会继承引用相同 eBPF 对象的文件描述符。

  • 引用 eBPF 对象的文件描述符可以通过 unix(7) 域套接字传输。

  • 引用 eBPF 对象的文件描述符可以使用 dup(2) 及类似调用以通常方式复制。

  • 引用 eBPF 对象的文件描述符可以使用 bpf(2) 的 BPF_OBJ_PIN 命令固定到文件系统。

eBPF 对象只有在所有引用该对象的文件描述符都已关闭且没有引用被固定到文件系统或已附加(例如,绑定到程序或设备)后才会被解除分配。