3. 网络观测数据采集:网络数据包捕获原理、XDP与TC程序、套接字过滤、网络延迟与吞吐量指标

网络观测是 eBPF 最成熟、应用最广泛的能力领域。本章深入解析 eBPF 在网络数据包捕获路径上的核心技术原理,涵盖从硬件中断到用户态套接字的完整链路,并重点阐述 XDP、TC 以及套接字过滤三种编程模型的适用场景与性能差异。同时,定义网络延迟与吞吐量的关键观测指标,为后续构建自动化运维制品库奠定数据采集基础。

3.1 网络数据包捕获原理与内核路径

理解 eBPF 网络观测,首先需要掌握数据包从网卡到用户态应用程序的完整内核路径。eBPF 程序可以挂载到该路径的不同“钩子”点,从而实现对网络流量的观测、过滤或修改。

核心路径概览: 网卡 (NIC) → 驱动层 → 内核协议栈 → 套接字 (Socket) → 用户态应用。eBPF 主要在驱动层之后、协议栈处理之前(XDP)以及协议栈处理过程中(TC、套接字过滤)进行干预。

下表对比了不同捕获点的关键特性:

捕获点 内核层级 触发时机 性能开销 典型应用
XDP 驱动层 (RX 队列) 最早,分配 skb 之前 极低 (无协议栈开销) DDoS 防御、负载均衡、高速包过滤
TC (ingress) 协议栈入口 (dev_queue_xmit) 分配 skb 后,协议栈处理前 低 流量整形、QoS、容器网络策略
套接字过滤 (BPF_PROG_TYPE_SOCKET_FILTER) 套接字层 数据到达套接字接收队列前 中等 tcpdump、应用层协议过滤、安全审计

下图展示了 eBPF 程序在数据包内核路径上的挂载位置:

eBPF 网络数据包捕获路径与钩子点 网卡 (NIC) 驱动层 (RX Queue) XDP 钩子 内核协议栈 TC (ingress) 钩子 套接字 (Socket) 套接字过滤钩子 用户态应用 关键说明 • XDP:最早介入,性能最高 • TC:协议栈入口,功能丰富 • 套接字过滤:应用层视角 • 越早捕获,性能开销越低 • 越晚捕获,语义信息越丰富

3.2 XDP 与 TC 程序:内核态网络处理

XDP (eXpress Data Path) 和 TC (Traffic Control) 是 eBPF 在网络观测与处理中最核心的两个程序类型。它们运行在内核态,能够以极低的开销处理高速网络流量。

3.2.1 XDP 程序

XDP 程序挂载在网卡驱动层,在数据包被分配为 sk_buff 结构体之前执行。这意味着 XDP 可以访问原始的、未经内核协议栈处理的网络帧数据。XDP 程序通过返回一个动作码来决定数据包的命运:

  • XDP_PASS:将数据包传递给内核协议栈继续处理。
  • XDP_DROP:直接丢弃数据包,性能极高,适用于 DDoS 防御。
  • XDP_TX:将数据包从接收到的网卡原路转发出去,适用于负载均衡。
  • XDP_REDIRECT:将数据包重定向到其他网卡或 CPU,适用于高级转发场景。
  • XDP_ABORTED:程序出错,丢弃数据包并记录错误。
性能提示: XDP 通常需要网卡驱动和硬件的原生支持(Native XDP)。在虚拟化环境或驱动不支持时,可以回退到通用模式(Generic XDP),但性能会显著下降。在物理机上,XDP 可以实现每秒数百万甚至千万级的数据包处理能力。

3.2.2 TC 程序

TC 程序挂载在 Linux 流量控制子系统的入口(ingress)或出口(egress)处。与 XDP 不同,TC 程序在数据包已被分配 sk_buff 结构体后执行,因此可以访问更丰富的协议元数据。TC 程序常用于:

  • 流量整形与 QoS(服务质量)
  • 容器网络策略(如 Cilium 网络策略)
  • 网络地址转换(NAT)
  • 更复杂的包修改与封装/解封装

下表对比了 XDP 与 TC 的核心差异:

特性 XDP TC (ingress)
执行位置 驱动层,skb 分配前 协议栈入口,skb 分配后
数据访问 原始网络帧 (xdp_md) sk_buff 结构体
性能 极高 (无协议栈开销) 高 (少量协议栈开销)
可编程性 有限 (不能直接修改 skb) 丰富 (可修改 skb 元数据)
典型场景 DDoS 防御、负载均衡 容器网络策略、QoS
硬件依赖 需要网卡驱动支持 无特殊硬件依赖

3.3 套接字过滤:用户态视角的观测

套接字过滤(Socket Filter)是 eBPF 最早的应用之一,其程序类型为 BPF_PROG_TYPE_SOCKET_FILTER。它允许用户将 eBPF 程序附加到特定的套接字上,对进出该套接字的数据包进行过滤和观测。

与 XDP 和 TC 不同,套接字过滤工作在协议栈之上、用户态应用之下。这意味着它看到的是已经经过内核协议栈处理的数据,例如已经完成 TCP 重组、IP 分片重组的流数据。套接字过滤的典型应用是 tcpdump 和 seccomp。

注意: 套接字过滤虽然灵活,但由于其工作在协议栈上层,性能开销相对较大。对于需要处理海量数据包的高性能场景,应优先考虑 XDP 或 TC。套接字过滤更适合于应用层协议分析、安全审计或特定进程的网络监控。

一个简单的套接字过滤 eBPF 程序示例(仅捕获 TCP 数据包):

#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>

SEC("socket")
int tcp_filter(struct __sk_buff *skb) {
    // 获取网络层头部偏移
    void *data = (void *)(long)skb->data;
    void *data_end = (void *)(long)skb->data_end;

    struct ethhdr *eth = data;
    if (eth + 1 > data_end)
        return 0;

    // 仅处理 IPv4 数据包
    if (eth->h_proto != __constant_htons(ETH_P_IP))
        return 0;

    struct iphdr *ip = data + sizeof(*eth);
    if (ip + 1 > data_end)
        return 0;

    // 仅处理 TCP 数据包
    if (ip->protocol != IPPROTO_TCP)
        return 0;

    // 捕获 TCP 数据包,返回非零值
    return -1;
}

3.4 网络延迟与吞吐量指标

网络观测的最终目的是量化网络性能。eBPF 能够以纳秒级精度采集关键指标,为自动化运维提供数据支撑。以下是核心的网络性能指标:

3.4.1 网络延迟指标

延迟衡量数据包从源端到目的端所花费的时间。eBPF 可以测量路径上不同阶段的延迟:

  • RTT (Round-Trip Time): 数据包从发送到收到 ACK 确认的总时间。eBPF 可以通过跟踪 TCP 套接字的 tcp_rcv_established 等函数来精确计算 RTT。
  • 队列延迟 (Queueing Delay): 数据包在内核队列中等待处理的时间。通过 TC 或 XDP 程序可以测量数据包到达与开始处理的时间差。
  • 处理延迟 (Processing Delay): 内核协议栈处理数据包所花费的时间。eBPF 可以在协议栈关键函数(如 ip_rcv、tcp_v4_rcv)的入口和出口处打点,计算处理耗时。
  • 应用延迟 (Application Delay): 数据从套接字传递到用户态应用并被应用处理的时间。这通常需要结合用户态探针 (uprobe) 来测量。

3.4.2 吞吐量指标

吞吐量衡量单位时间内成功传输的数据量。eBPF 可以按流、按协议、按容器粒度进行统计:

  • PPS (Packets Per Second): 每秒处理的数据包数量。XDP 程序可以直接在驱动层统计,性能损耗极小。
  • BPS (Bytes Per Second): 每秒处理的字节数,即带宽。TC 程序可以方便地统计每个 sk_buff 的长度。
  • 连接数 (Connections Per Second): 每秒新建的 TCP 连接数。通过跟踪 tcp_connect 或 inet_csk_accept 函数可以精确统计。
  • 重传率 (Retransmission Rate): 重传数据包占总发送数据包的比例。高重传率通常意味着网络拥塞或链路质量问题。
指标采集最佳实践: 在 eBPF 程序中,应优先使用 BPF_MAP_TYPE_PERCPU_HASH 或 BPF_MAP_TYPE_PERCPU_ARRAY 来存储计数器,以避免多核竞争。用户态程序定期(如每 1 秒)读取这些 percpu map 并汇总,即可得到全局的延迟和吞吐量指标。

下表总结了关键指标及其 eBPF 采集方法:

指标类别 指标名称 eBPF 采集方法 挂载点
延迟 RTT 跟踪 tcp_rcv_established,计算时间戳差 kprobe / fentry
队列延迟 在 TC 入口记录时间戳,与 XDP 时间戳对比 XDP + TC
吞吐量 PPS / BPS 在 XDP 或 TC 程序中递增 percpu 计数器 XDP / TC
连接数 跟踪 tcp_connect / inet_csk_accept kprobe / tracepoint
可靠性 重传率 跟踪 tcp_retransmit_skb kprobe

下图展示了 eBPF 如何从不同层级采集延迟与吞吐量指标:

eBPF 网络延迟与吞吐量指标采集架构 用户态应用 uprobe: 应用延迟 套接字层 套接字过滤: 连接数 内核协议栈 kprobe: RTT, 重传率 驱动层 / 网卡 XDP: PPS, BPS, 队列延迟 采集的指标汇总 • 延迟: RTT, 队列延迟, 应用延迟 • 吞吐量: PPS, BPS, 连接数 • 可靠性: 重传率, 丢包率 • 每个指标都带有时间戳和元数据 • 数据通过 Perf Event 或 Map 输出