【问题标题】:BPF: translation of program contextsBPF:程序上下文的翻译
【发布时间】:2018-03-01 14:21:52
【问题描述】:

我查看了不同类型的 BPF 程序,并注意到对于不同的程序类型,传递的上下文是不同的。

例子:

  1. 对于程序类型BPF_PROG_TYPE_SOCK_OPS,传递了struct bpf_sock_ops_kern 类型的对象。但是,这种类型的 BPF 程序引用了struct bpf_sock_ops。为什么要这样做?从bpf_sock_ops_kernbpf_sock_ops 的“翻译”在哪里?

  2. 对于程序类型BPF_PROG_TYPE_CGROUP_SKB,传递了一个struct sk_buff 类型的对象(例如,在__cgroup_bpf_run_filter_skb 中),但BPF 程序需要一个最小化版本,struct __sk_buff

    李>

所以我查看了the struct bpf_verifier_ops function callbacks,但它们似乎只调整 BPF 指令中的偏移量,因为它们是由 BPF 验证程序调用的。

如果有人能阐明如何定义 BPF 上下文,我会很高兴。谢谢。

【问题讨论】:

  • 对于第一个,bpf_sock_ops_kern 只是bpf_sock_ops 的一个子集。要进行转换,sock_filter_convert_ctx_access 只需将指针前移到第一个 sk 字段之后。然后,验证者将确保不会访问联合之后的字段。我已经调查了第二种情况。
  • 好的,所以对于第二个:bpf_convert_ctx_access 逐一匹配__sk_buff 上每个可能需要的偏移量,并将它们转换为sk_buff 对象中的等效偏移量。这是否回答你的问题?如果是这样,我会做出正确的回答。
  • 我认为这与性能无关。这些数据结构用于限制 BPF 程序对少数字段的访问;只有程序应该能够访问的字段位于镜像结构中(例如,bpf_sock_ops__sk_buff)。例如,您可以查看 Alexei here 描述的 __sk_buff 的流程,更多详细信息请参见 the PATCH description
  • 据我所知 pchaigno 是对的,struct __sk_buff 与性能无关,但主要用于为 BPF 用户提供更简洁的界面(仅提供可以从 BPF 访问)。如前所述,它在验证器中使用bpf_convert_ctx_access 进行转换。然后在net/core/filter.c(用于网络)中进行额外检查,以确保用户可以读取,可能写入结构的每个字段。例如,参见tc_cls_act_is_valid_access() 函数。 (我对跟踪位不太熟悉。)
  • @pchaigno,感谢您的回复!您可以做出我可以接受的官方答案,以便其他人可以受益:-)您可能可以合并Qeole的评论,因为它也很有用。

标签: linux networking linux-kernel bpf ebpf


【解决方案1】:

作为参数传递的镜像对象(例如,struct bpf_sock_ops)将原始对象字段的子集暴露给 BPF 程序。镜像结构也可以有来自几个不同原始结构的字段;在这种情况下,镜像对象用作聚合。将原始对象传递给 BPF 程序也会产生误导,因为用户可能认为他们可以访问所有字段。例如,他们可能认为他们可以访问bpf_sock_ops_kern.sk,但实际上并非如此。

然后,在程序第一次执行之前,验证者将对镜像对象的访问转换为对原始对象的访问。每种类型的镜像对象都有一个转换函数(例如,sock_ops_convert_ctx_access 用于转换对struct bpf_sock_ops 的访问)。然后,对于镜像对象的每个字段(即对于每个偏移量),转换函数都会将带有偏移量的加载或存储指令重写为原始字段。

请注意,所有原始字段可能不在同一个对象中。例如,在镜像对象struct bpf_sock_ops中,分别在bpf_sock_ops_kern.opbpf_sock_ops_kern.sk->skc_family中检索到opfamily字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多