本页目录

eBPF 程序类型

覆盖: 所有 BPF_PROG_TYPE → 挂载点 → 上下文 → 可用 helpers → 使用场景 → 内核实现要点

程序类型总览

每种程序类型定义了:attach 到哪里、context 参数类型、可用的 helper 函数白名单。

类型挂载点Context用途
XDP网卡驱动 NAPI pollxdp_mdDDoS/负载均衡 (最早接触点)
SCHED_CLSTC ingress/egress__sk_buff防火墙/Cilium
SCHED_ACTTC action__sk_buff包修改/重定向
KPROBEkprobe (函数入口)pt_regs可观测性
TRACEPOINTtracepointtracepoint 特定 struct事件追踪
PERF_EVENTperf_event_openbpf_perf_event_data性能采样
CGROUP_SKBcgroup egress/ingress__sk_buff容器网络策略
CGROUP_SOCKsocket create/releasebpf_socksocket 选项控制
SOCK_OPSsocket 操作 (TCP states)bpf_sock_opsTCP 调优/BBR 策略
SK_MSGsocket messagesk_msg_mdsocket 重定向
LSMLSM hooksbpf_lsm_ctx安全策略
SK_LOOKUPsocket lookupbpf_sk_lookupsocket 绑定覆盖
SYSCALLsyscallbpf_syscall_ctxsyscall 过滤
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 }

// 返回值:
enum xdp_action {
    XDP_DROP,       // 丢弃 (最快!)
    XDP_PASS,       // 放行, 交给协议栈
    XDP_TX,         // 从同一网卡发回 (hairpin)
    XDP_REDIRECT,   // 重定向到其他网卡/CPU
};

// 为何快:
//   - 在 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 白名单