【发布时间】:2018-03-01 14:21:52
【问题描述】:
我查看了不同类型的 BPF 程序,并注意到对于不同的程序类型,传递的上下文是不同的。
例子:
对于程序类型
BPF_PROG_TYPE_SOCK_OPS,传递了struct bpf_sock_ops_kern类型的对象。但是,这种类型的 BPF 程序引用了struct bpf_sock_ops。为什么要这样做?从bpf_sock_ops_kern到bpf_sock_ops的“翻译”在哪里?-
对于程序类型
李>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