BPF sk_lookup 程序¶
BPF sk_lookup 程序类型 (BPF_PROG_TYPE_SK_LOOKUP
) 引入了可编程性到传输层执行的套接字查找中,当数据包要本地交付时。
当调用时,BPF sk_lookup 程序可以通过调用 bpf_sk_assign()
BPF 辅助函数来选择将接收传入数据包的套接字。
对于 TCP 和 UDP,都存在用于通用附加点 (BPF_SK_LOOKUP
) 的钩子。
动机¶
引入 BPF sk_lookup 程序类型是为了解决通过 bind()
套接字调用将套接字绑定到地址不切实际的设置场景,例如
在 IP 地址范围内(例如 192.0.2.0/24)接收连接,当由于端口冲突而无法绑定到通配符地址
INADRR_ANY
时,在所有或范围广泛的端口上接收连接,即 L7 代理用例。
这样的设置将需要创建并将一个套接字 bind()
到范围内的每个 IP 地址/端口,从而导致资源消耗和套接字查找期间潜在的延迟峰值。
附加¶
可以使用 bpf(BPF_LINK_CREATE, ...)
系统调用,使用 BPF_SK_LOOKUP
附加类型和 netns FD 作为附加 target_fd
将 BPF sk_lookup 程序附加到网络命名空间。
可以将多个程序附加到一个网络命名空间。程序将按照它们附加的顺序被调用。
钩子¶
当传输层需要为传入的数据包查找监听 (TCP) 或未连接 (UDP) 的套接字时,将运行附加的 BPF sk_lookup 程序。
到已建立的 (TCP) 和已连接的 (UDP) 套接字的传入流量将照常交付,而不会触发 BPF sk_lookup 钩子。
附加的 BPF 程序必须返回 SK_PASS
或 SK_DROP
判决代码。对于其他作为网络过滤器的 BPF 程序类型,SK_PASS
表示套接字查找应继续到常规的基于哈希表的查找,而 SK_DROP
会导致传输层丢弃数据包。
BPF sk_lookup 程序还可以通过调用 bpf_sk_assign()
BPF 辅助函数来选择接收数据包的套接字。通常,该程序会在保存套接字的映射中(例如 SOCKMAP
或 SOCKHASH
)查找套接字,并将 struct bpf_sock *
传递给 bpf_sk_assign()
辅助函数以记录选择。仅当程序以 SK_PASS
代码终止时,选择套接字才会生效。
当附加多个程序时,最终结果由所有程序的返回代码根据以下规则确定
如果任何程序返回了
SK_PASS
并选择了有效的套接字,则该套接字将用作套接字查找的结果。如果多个程序返回了
SK_PASS
并选择了套接字,则最后一个选择生效。如果任何程序返回了
SK_DROP
,并且没有程序返回SK_PASS
并选择了套接字,则套接字查找失败。如果所有程序都返回了
SK_PASS
,并且它们都没有选择套接字,则套接字查找将继续进行。
API¶
在其上下文中,struct bpf_sk_lookup
的实例,BPF sk_lookup 程序接收有关触发套接字查找的数据包的信息。即
IP 版本 (
AF_INET
或AF_INET6
),L4 协议标识符 (
IPPROTO_TCP
或IPPROTO_UDP
),源和目标 IP 地址,
源和目标 L4 端口,
已使用
bpf_sk_assign()
选择的套接字。
有关详细信息,请参阅 linux/bpf.h
用户 API 标头中的 struct bpf_sk_lookup
声明,以及 bpf-helpers(7) 手册页中关于 bpf_sk_assign()
的部分。
示例¶
有关参考实现,请参阅 tools/testing/selftests/bpf/prog_tests/sk_lookup.c
。