为什么load_half在bpf_helpers中有定义,但在filter.c中却没有出现?

Why load_half is defined in bpf_helpers but it doesn't appear in filter.c?

如果我在 tools/testing/selftests/bpf/bpf_helpers.h 中理解 "well" bpf heleprs 原型已定义。

如果我现在想知道哪些助手可用于特定程序类型,我需要在 'func_proto(enum bpf_func_id func_id' kernel/ net/ drivers/

的结果中进行搜索

例如检查套接字过滤器程序可以调用的助手我可以阅读以下定义

static const struct bpf_func_proto *
sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
{
        switch (func_id) {
        /* inet and inet6 sockets are created in a process
         * context so there is always a valid uid/gid
         */
        case BPF_FUNC_get_current_uid_gid:
                return &bpf_get_current_uid_gid_proto;
        case BPF_FUNC_get_local_storage:
                return &bpf_get_local_storage_proto;
        default:
                return bpf_base_func_proto(func_id);
        }
}

问题:

1)我看不到 load_half,但我仍然可以从我的套接字过滤器程序中调用它。为什么? 2) socket_filtersk_filter 有什么区别?

  1. load_half() 不是 BPF 助手。您提到的文件 bpf_helpers.h 确实声明了 BPF 辅助函数的原型,但它还包含其他有用的定义,例如 SEC()bpf_printk() 宏。特别是,它声明 load_half() 并带有以下注释:

    /* llvm builtin functions that eBPF C program may use to
     * emit BPF_LD_ABS and BPF_LD_IND instructions
     */
    [...]
    unsigned long long load_half(void *skb,
                                 unsigned long long off) asm("llvm.bpf.load.half");
    

    如您所见,load_half() 是一个 LLVM 内置函数,clang/LLVM 支持的汇编原语,为方便起见包装为 load_half()。而且因为它不是 BPF 助手,所以在内核中 grep 查找它的原型时你不会看到它。

  2. 前缀 sk_filter 用于附加到套接字的 eBPF 过滤器,其方式与使用传统 cBPF 的方式类似,用于过滤传入数据包。虽然可能会造成混淆,但您可以看到内核文件 net/core/filter.c 中的 sock_filter_is_valid_access 用于 cg_sock_verifier_ops,它在 include/uapi/linux/bpf.h 中关联到程序类型 BPF_PROG_TYPE_CGROUP_SOCK_ADDR。所以它指的是在cgroups中使用的程序正确help (containerised) applications to bind and connect它们的套接字。