本页目录
eBPF 程序类型
覆盖: 所有 BPF_PROG_TYPE → 挂载点 → 上下文 → 可用 helpers → 使用场景 → 内核实现要点
程序类型总览
每种程序类型定义了:attach 到哪里、context 参数类型、可用的 helper 函数白名单。
| 类型 | 挂载点 | Context | 用途 |
|---|---|---|---|
XDP | 网卡驱动 NAPI poll | xdp_md | DDoS/负载均衡 (最早接触点) |
SCHED_CLS | TC ingress/egress | __sk_buff | 防火墙/Cilium |
SCHED_ACT | TC action | __sk_buff | 包修改/重定向 |
KPROBE | kprobe (函数入口) | pt_regs | 可观测性 |
TRACEPOINT | tracepoint | tracepoint 特定 struct | 事件追踪 |
PERF_EVENT | perf_event_open | bpf_perf_event_data | 性能采样 |
CGROUP_SKB | cgroup egress/ingress | __sk_buff | 容器网络策略 |
CGROUP_SOCK | socket create/release | bpf_sock | socket 选项控制 |
SOCK_OPS | socket 操作 (TCP states) | bpf_sock_ops | TCP 调优/BBR 策略 |
SK_MSG | socket message | sk_msg_md | socket 重定向 |
LSM | LSM hooks | bpf_lsm_ctx | 安全策略 |
SK_LOOKUP | socket lookup | bpf_sk_lookup | socket 绑定覆盖 |
SYSCALL | syscall | bpf_syscall_ctx | syscall 过滤 |
STRUCT_OPS | 内核函数指针替换 | 操作特定 struct | 替换拥塞控制等 |
深入关键程序类型
XDP (eXpress Data Path)
// drivers/net/ 各驱动 → XDP hook → BPF 程序
// 最早处理点: NAPI poll 中, sk_buff 分配之前
// Context: struct xdp_md { data, data_end, data_meta }
// 返回值:
;
// 为何快:
// - 在 sk_buff 分配之前运行 → 零分配开销
// - 驱动内联执行 → 无函数调用开销 (某些驱动)
// - DROP 只需: BPF_JMP XDP_DROP → 驱动释放 DMA buffer → 完成
// 加载:
ip link set dev eth0 xdp obj xdp_drop.o sec xdp
bpftool net attach xdpdrv id <prog_id> dev eth0
kprobe / kretprobe
// 动态探测任意内核函数 (非稳定 API!)
// kprobe: 函数入口 → R0..R5 = 函数参数
// kretprobe: 函数返回 → R0 = 返回值
// 限制:
// - 函数签名版本间可能变化 → CO-RE 不完全覆盖 (需 BTF)
// - 内核可以内联函数 → kprobe 挂不上去
// - 黑名单: 某些函数不能探测 (lock, NMI, ...)
// → /sys/kernel/debug/kprobes/blacklist
// 用户态探测 (uprobe):
// 挂用户态函数的入口/返回
// → 适合调试, 不适合生产 (开销大)
Tracepoint
// 内核预定义的稳定探测点 → 不依赖函数签名
// /sys/kernel/debug/tracing/events/ 目录结构
// 每个 tracepoint 有特定的 context struct (通过 BTF 可知)
// 例: sched_switch
// context: prev_pid, prev_comm, next_pid, next_comm, ...
// 优势:
// - 稳定 API (比 kprobe 可靠)
// - BTF 完整覆盖
// - 开销比 kprobe 低 (少一次函数调用)
// 劣势:
// - 只有内核预定义的点 → 灵活度不如 kprobe
CGROUP_SKB (容器网络策略)
挂载点: cgroup v2 的 egress/ingress
→ 此 cgroup 下所有任务的 socket 流量都经过
→ 容器出口: 挂载点在 cgroup net_cls 上
Cilium 的核心: 用 CGROUP_SKB 实现:
- 容器间 L3/L4 策略 (无隧道, 无 iptables)
- 基于 identity 而不是 IP
- 比 iptables 快 10x (hash lookup vs linear chain)
LSM BPF (5.7+)
// security/ + BPF
// BPF 程序实现 LSM hook → 不修改内核代码就能定制安全策略
// bpf(BPF_PROG_LOAD, BPF_PROG_TYPE_LSM, ...)
// → attach to LSM hook: bpf(BPF_RAW_TRACEPOINT_OPEN, lsm/file_open)
// 适用:
// - 自定义审计策略
// - Android: 设备级别的安全策略
// - 容器安全 (比 seccomp 更灵活)
Helper 可用性矩阵
// 不是所有 helper 对所有程序类型都可用
// 规则由内核编译时决定: include/uapi/linux/bpf.h
// 例: bpf_skb_load_bytes() 只对 SKB 类型可用
// bpf_xdp_adjust_head() 只对 XDP 可用
// bpf_get_current_pid_tgid() 对所有 tracing 类型可用
// 工具: bpftool feature probe 检查当前内核支持哪些
参考
- 源码:
include/uapi/linux/bpf.h(所有类型定义),kernel/bpf/syscall.c(加载路径),net/core/filter.c(网络相关 helpers) - 内核文档:
Documentation/bpf/libbpf/ - Cilium BPF 文档: docs.cilium.io (最好的 BPF 网络实践文档)
关键词: BPF_PROG_TYPE, XDP, kprobe, tracepoint, CGROUP_SKB, LSM BPF, helper 白名单