2. 网络协议栈基础回顾:数据包从网卡到应用层的完整路径(RX/TX路径)

在深入 GRO/GSO 卸载技术之前,必须牢固掌握数据包在内核协议栈中的完整生命周期。理解接收(RX)和发送(TX)路径上的每一个关键节点,是后续分析卸载点、瓶颈以及优化收益的前提。本章将拆解这两个路径,并聚焦于协议栈各层之间的数据交互与内存管理。

2.1 接收路径(RX):从线缆到 Socket

数据包到达网卡后,需要经过硬件捕获、内核处理、协议解析,最终交付给用户态应用。整个过程可分为四个主要阶段:

  1. 硬件接收与 DMA:网卡将帧写入预分配的内存缓冲区(Ring Buffer)。
  2. 中断处理与 NAPI:网卡触发中断,内核以轮询方式批量收包。
  3. 协议栈处理:从链路层逐层向上解析,直至传输层。
  4. Socket 交付:数据放入接收队列,唤醒等待的应用进程。
关键指标: 接收路径的延迟通常由“硬中断 → 软中断 → 协议处理”的流水线决定。NAPI 的引入将每次中断处理的收包数从 1 提升到 N,显著降低了高吞吐场景下的 CPU 开销。
数据包接收路径(RX)流程图 数据包接收路径(RX)流程图 ① 网卡硬件 ② DMA Ring Buffer ③ 硬中断 / NAPI 调度 ④ 软中断 (ksoftirqd) ⑤ 协议栈 (L2→L4) ⑥ Socket 接收队列 说明 NAPI 合并了中断与轮询: 首次中断开启轮询,后续不再中断。 批量收包结束后重新开启中断。

2.2 发送路径(TX):从 Socket 到线缆

发送路径是接收路径的逆过程,但逻辑更为复杂,因为内核需要负责分片、校验和计算以及排队规则(Qdisc)。

  1. 系统调用:应用调用 send() 或 write(),数据从用户态拷贝到内核态。
  2. 协议封装:传输层添加 TCP/UDP 头,网络层添加 IP 头,链路层添加 MAC 头。
  3. Qdisc 排队:数据包进入传输队列,等待内核流量控制策略调度。
  4. 驱动发送:驱动将 sk_buff 映射到 DMA 区域,通知网卡发送。
  5. 发送完成中断:网卡发送完毕后触发中断,释放 sk_buff 和 DMA 缓冲区。
性能陷阱: TX 路径上的锁竞争(如 Qdisc 锁、设备队列锁)和过多的内存拷贝是常见的性能瓶颈。GSO 技术正是为了减少协议封装阶段的 CPU 消耗而设计的。
数据包发送路径(TX)流程图 数据包发送路径(TX)流程图 ① Socket 发送缓冲区 ② 协议封装 (L4→L2) ③ Qdisc 排队与调度 ④ 网卡驱动 (xmit) ⑤ DMA 映射与发送 ⑥ 发送完成中断 TX 路径关键点 • Qdisc 可能引入延迟 • 协议封装产生 CPU 开销 • 完成中断释放资源 • GSO 可合并封装步骤

2.3 核心数据结构:sk_buff

在整个 RX/TX 路径中,struct sk_buff(套接字缓冲区)是贯穿始终的核心载体。它承载了从原始帧到协议头的所有元数据。

字段 作用 路径相关性
data / head 指向数据缓冲区的起始和当前数据指针 RX/TX 均需操作
len 当前有效数据长度 协议层校验
protocol L3 协议类型(如 ETH_P_IP) RX 路径分发
dev 关联的网络设备 RX/TX 路由
sk 指向关联的 Socket TX 路径绑定
destructor 释放 sk_buff 时的回调函数 内存管理
优化视角: sk_buff 的分配与释放是协议栈的热点路径。GRO 通过合并多个 sk_buff 为一个巨型 sk_buff,减少了上层协议栈的处理次数;GSO 则推迟了 sk_buff 的分割,降低了协议封装阶段的 CPU 开销。

2.4 协议栈分层处理与卸载切入点

下表总结了各层在 RX/TX 路径上的主要职责,并标注了 GRO/GSO 的卸载切入点:

协议层 RX 职责 TX 职责 卸载切入点
链路层 (L2) 帧校验、类型分发 MAC 头封装 —
网络层 (L3) IP 重组、路由查找 IP 分片、路由选择 GRO 可合并 IP 分片
传输层 (L4) TCP 重组、校验和验证 TCP 分段、校验和计算 GRO 合并 TCP 段;GSO 推迟分段
Socket 层 数据拷贝到用户态 数据从用户态拷贝 —

2.5 路径上的关键性能开销

在未启用卸载技术时,RX/TX 路径存在以下典型开销:

  • 每包中断开销:传统模式下每个数据包触发一次中断,高 PPS(包每秒)场景下 CPU 被中断淹没。
  • 协议头处理:每个包独立进行校验和计算、分片/重组、头部分析。
  • sk_buff 元数据操作:大量小包的 sk_buff 分配、链表操作、引用计数更新。
  • 内存带宽瓶颈:小包场景下,协议头占比高,有效数据吞吐受限。
GRO/GSO 的优化哲学: 通过“合并”减少上层协议栈的处理次数(RX 方向),或通过“推迟分割”减少协议封装的重复计算(TX 方向),从而将 CPU 从 per-packet 开销中解放出来,提升整体吞吐量。