我正在查看不同类型的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
。
所以我查看了struct bpf_verifier_ops
函数回调,但它们似乎只调整 BPF 指令中的偏移量,因为它们是由 BPF 验证器调用的。
如果有人能阐明如何定义 BPF 上下文,我会很高兴。谢谢。
作为参数传递的镜像对象(例如,struct bpf_sock_ops
)将原始对象的字段子集暴露给BPF程序。镜像结构还可以具有来自几个不同原始结构的场;在这种情况下,镜像对象充当聚合。将原始对象传递给 BPF 程序也会产生误导,因为用户可能认为他们有权访问所有字段。例如,他们可能认为自己可以访问bpf_sock_ops_kern.sk
,而事实并非如此。
然后,验证程序将在首次执行程序之前,将对镜像对象的访问转换为对原始对象的访问。每种类型的镜像对象都有一个转换函数(例如,sock_ops_convert_ctx_access
用于将访问转换为struct bpf_sock_ops
)。然后,对于镜像对象的每个字段(即,对于每个偏移量),转换函数使用原始字段的偏移量重写加载或存储指令。
请注意,所有原始字段可能不在同一对象中。例如,在镜像对象struct bpf_sock_ops
中,字段op
和family
分别以bpf_sock_ops_kern.op
和bpf_sock_ops_kern.sk->skc_family
格式检索。