Linux 的 TX/RX Checksum Offload、TSO、GSO、GRO、LRO 和抓包坏校验和有什么区别?
Linux 主机上的抓包经常出现两类“反常”:发出的 TCP/UDP 包被标成 bad checksum,或者单个包远大于网卡 MTU。很多时候这不是线上真的发送了坏包或巨型包,而是抓包点位于协议栈与网卡卸载之间:校验和还没由硬件填完,或大缓冲区还没分割成线速帧;接收方向又可能在多个包被 GRO/LRO 合并后才被抓到。
本文目录(28 节)
快速对照
| 功能 | 方向 | 主要动作 | 通常执行位置 |
|---|---|---|---|
| TX Checksum Offload | 发送 | 延后填写TCP/UDP等校验和 | 网卡硬件或软件回退 |
| RX Checksum Offload | 接收 | 验证校验和并向内核标记结果 | 网卡硬件/驱动 |
| TSO | 发送 | 把一个大TCP缓冲分成多个TCP段 | 网卡硬件 |
| GSO | 发送 | 通用的软件分段框架 | Linux协议栈 |
| GRO | 接收 | 把可兼容的小包合并成较大缓冲 | Linux协议栈,亦有硬件变体 |
| LRO | 接收 | 更积极地合并接收流量 | 常由网卡/驱动实现 |
| MTU | 双向链路约束 | 限制网络层包的常规线速大小 | 网络设备与协议栈 |
校验和与分段是两类功能
校验和卸载回答“谁计算或验证完整性字段”,分段卸载回答“何时把大缓冲拆成网络可发送的小包”。TSO通常依赖TX checksum offload,因为每个分段都需要正确的TCP和IP相关字段。
关闭TX checksum可能导致驱动连带关闭TSO,但不能据此认为两者语义相同。ethtool -k 会显示功能当前状态、是否固定以及相关子特性,排障记录应保留完整输出。
TCP校验和保护哪些内容
RFC 9293规定TCP校验和是必需的,发送方必须生成,接收方必须检查。它覆盖TCP头、数据以及由IP源地址、目的地址、长度和协议等构成的伪首部。
伪首部不作为TCP报文本身在线上传输,却参与计算,用来降低误投递到错误IP端点而未被发现的风险。TCP校验和不是加密认证,无法抵御能够同步修改内容和校验和的攻击者。
UDP校验和的IPv4与IPv6差异
UDP在IPv4中历史上允许零校验和,但RFC 8085建议应用启用校验和。IPv6没有IPv4头校验和,UDP校验和通常必须使用;只有特定隧道场景可依据专门标准采用受限的零校验和模式。
因此看到UDP checksum为0时,必须先区分IP版本、隧道协议和抓包点。不能把IPv4的一般兼容行为直接套用到IPv6普通应用流量。
TX Checksum Offload 的真实含义
发送时,Linux可以把待计算校验和的位置和起点记录在 sk_buff 元数据中,把最终计算交给设备。内核文档用 CHECKSUM_ 表示这类请求:驱动必须保证最终发送包中的校验和正确,要么让硬件完成,要么调用软件辅助函数回退。
“partial”不是说线上允许残缺校验和,而是主机内部当前缓冲仍等待后续完成。若网卡不支持特定封装或头部布局,协议栈应在软件中补算。
为什么本机出站抓包显示 Bad Checksum
抓包程序常在网卡真正填充校验和之前复制出站 skb。抓到的副本仍含中间值,分析器用完整算法验证,自然会标成 incorrect 或 bad;实际帧离开网卡时,硬件已经写入正确结果。
要判断真假,应在另一台物理主机、交换机镜像端口或卸载之后的可信点位抓包。若远端成功接收且远端抓包校验正确,本机发送侧的 bad checksum 多半只是观察位置效应。
RX Checksum Offload 不一定改写包字段
接收网卡可以验证TCP、UDP等校验和,并通过驱动元数据告诉内核结果。Linux内核文档说明,CHECKSUM_ 表示硬件已针对支持的协议验证成功,但 skb->csum 不一定包含完整计算值,设备也不应因验证成功就改写包内字段。
因此抓包工具是否显示“checksum verified”取决于它能否获得并解释相关元数据。缺少硬件验证标记不等于校验失败,只能表示当前点位没有证明。
CHECKSUM_NONE 不是坏校验和
接收路径的 CHECKSUM_NONE 表示设备没有完成校验,包中包含校验和字段但尚未由硬件验证。内核仍可在软件中检查。
名字容易被误解成“协议没有checksum”或“验证结果为零”。它是skb处理状态,不是线上TCP头中的数值,也不能直接从普通pcap字段推断。
TSO 在网卡中分割TCP大缓冲
TCP Segmentation Offload允许协议栈把包含大量TCP数据的缓冲交给网卡,硬件根据GSO size/MSS生成多个实际TCP段,并为每段更新序列号、长度和校验和等字段。
这样协议栈无需为每个MSS段重复走完整发送路径,能显著降低高吞吐场景的CPU开销。TSO只针对发送方向,并不让以太网线真正承载任意大的单帧。
GSO 是软件通用分段框架
Generic Segmentation Offload在软件中把大skb拆为多个符合约束的skb,解决底层设备无法执行特定硬件卸载或数据包转向另一设备的情况。
Linux内核要求在启用相应硬件分段前具备软件GSO支持,否则大缓冲可能被路由到不支持的设备后无法发送。GSO不等于“硬件版TSO”,而是支撑多协议和回退路径的通用机制。
TSO 与 GSO 的关系
两者都延后分段,但执行层不同。TSO通常指网卡完成TCP分段;GSO由内核软件处理,也承载描述待分段skb的框架语义。
在虚拟机、veth、bridge、隧道和物理NIC组合中,一个大skb可能跨越多个软件层,最后在某层用GSO拆分或交给物理网卡TSO。只检查物理口一个开关不足以解释整条路径。
UDP也有发送分段卸载
旧的UFO按IPv4分片方式处理超大UDP数据报,Linux内核文档已说明它被弃用,现代内核不再主动生成常规UFO skb。现代UDP Segmentation Offload则可把一个大UDP payload按指定大小拆成多个独立UDP数据报。
UDP分段与IP分片不同:前者生成多个各自拥有UDP头的datagram,后者把一个IP datagram拆成IP fragments。应用和抓包分析必须区分。
GRO 在接收方向合并包
Generic Receive Offload把同一流中可安全合并的多个接收包聚合成较大skb,让协议栈减少逐包处理开销。Linux文档把它视为GSO的互补机制:理想情况下,GRO合并的流应能由GSO重新分成等价包序列。
GRO发生在线速帧到达之后,所以大skb只是主机内部表示。下游转发若需要重新发出,协议栈仍要依据输出设备和MTU重新分段。
LRO 与 GRO 的区别
Large Receive Offload也合并接收包,常由网卡或驱动执行,历史上可能采用不完全保留原始分段语义的更积极策略。GRO是Linux协议栈的通用机制,对可重分段等要求更明确。
主机作为路由器、桥接器或精确流量观测点时,LRO可能干扰转发或抓包语义,通常需要更谨慎。是否能安全启用要看驱动、内核与工作负载,而不是一律认为LRO比GRO“更快所以更好”。
为什么入站抓包出现超过MTU的大包
若抓包钩子位于GRO/LRO合并之后,它看到的是聚合skb,长度可以远大于物理接口MTU。线缆上原先仍是多个符合链路限制的帧。
反过来,发送抓包可能在TSO/GSO分段之前看到大skb。两种现象方向相反,却都能让pcap出现“巨型包”。首先检查offload与抓包点,不要立即诊断为Jumbo Frame泄漏。
MTU仍然有效
Linux内核网络设备文档说明,普通上层协议不应向设备传递超过MTU的待发送数据,GSO/TSO是明确例外:允许传递大缓冲,由设备或软件之后拆分。
这不取消路径MTU、MSS或分片规则。最终线速包仍须满足输出路径要求;若隧道增加外层头部,还需为封装开销预留空间并支持相应隧道offload。
隧道让卸载更复杂
VXLAN、Geneve、GRE、IPIP等封装拥有内外两层头。分段时可能需要更新内层传输校验和、外层UDP/IP字段和每段长度。网卡是否支持某种组合取决于功能矩阵与驱动。
不支持的组合应回退软件,但驱动bug、错误特性声明或虚拟交换层不兼容会导致丢包。故障只出现在封装流量时,应比较普通流、隧道内层和外层抓包,并查看具体tunnel offload能力。
NAT与校验和卸载可以共存
NAT修改IP地址或端口,而这些字段参与TCP/UDP校验和或伪首部。Linux通过增量修正、partial checksum元数据和后续硬件完成来保持一致。
抓包若位于NAT修改之后但硬件完成之前,可能看到更令人困惑的中间值。不能仅凭该pcap断言NAT没有更新校验和,应在实际发出后的点位复核。
虚拟设备的offload不是物理网卡开关
loopback、veth、tap、bridge、bond、虚拟NIC和容器网络都可能公布或处理GSO/GRO能力。一个接口的 ethtool -K eth0 ... 不会自动关闭所有上游和下游虚拟设备的聚合。
容器内抓包与宿主机物理口抓包可能同时正确却形态不同。报告中应记录网络命名空间、接口索引、方向和相对于NAT/
ethtool -k 用于读取功能状态
ethtool -k eth0
可以查看rx/tx checksumming、scatter-gather、TSO、GSO、GRO、LRO及驱动扩展功能。输出中的 [fixed] 表示当前不能通过常规开关改变。
功能名称可能分解为IPv4、IPv6、隧道或特定协议子项。不要只截取最上面几行;完整输出更能解释某类流量为何回退或异常。
临时关闭用于对照实验
ethtool -K eth0 tx off rx off tso off gso off gro off lro off
这是诊断示例,不是通用修复命令。关闭可能显著增加CPU使用率、降低吞吐,并且某些功能无法修改或会彼此联动。应一次改变有限变量、记录前后状态,并准备恢复原值。
若关闭后只有本机pcap外观改变,而远端性能与正确性无差异,原问题多半是观测伪象;若实际丢包消失,才进一步调查驱动、固件、虚拟层或隧道组合。
抓包点位比工具名称更重要
同样使用tcpdump,在应用命名空间的veth、宿主bridge、隧道接口、物理出口和远端入口抓到的包代表不同处理阶段。Wireshark的“bad checksum”只是对捕获字节的计算结果,不知道网卡之后是否会完成字段。
一份可复核证据至少包括:命令、接口、方向、时间、offload状态、内核与驱动版本、过滤器、是否丢包,以及另一点位的对应流量。
真实坏校验和有哪些表现
真正到达接收方且校验失败的TCP段通常会被丢弃,上层看见重传、吞吐下降或连接超时;接收接口统计、驱动计数器或远端抓包也可能出现错误证据。
若只有发送主机pcap报错,远端pcap正确、应用稳定且无重传,不应把“bad checksum”计数当成链路损坏。反之,远端在线速入口也验证失败,则需要检查网卡、驱动、固件、内存、虚拟交换和中间设备。
关闭offload后性能下降不代表网络变差
关闭TSO/GSO/GRO后,每秒处理包数上升,CPU、中断与软中断负载增加,吞吐可能下降、延迟尾部可能变化。这是优化被移除的预期成本。
对照测试要保持业务负载、CPU亲和、队列、RSS/RPS和包大小一致。不能把“pcap更好看但吞吐下降”简单判为修复成功。
一套分层排障流程
- 确认是校验和告警、超MTU显示、真实丢包还是性能问题。
- 记录本机所有相关接口的
ethtool -k和统计信息。 - 同时在发送主机、远端主机或镜像端口抓取同一五元组。
- 用TCP序列号、IP ID、时间和payload摘要关联两端包。
- 判断大skb是在发送分段前还是接收聚合后看到。
- 检查物理、虚拟、隧道、NAT与容器各层的offload能力。
- 在维护窗口一次关闭一个相关功能做A/B对照。
- 若确认真实故障,升级或回退驱动/固件并保存复现证据。
常见误区
本机出站pcap显示bad checksum就是网卡发坏包
错误。抓包可能发生在TX硬件填充校验和之前,应以卸载后或远端点位验证。
pcap里超过1500字节说明线上有Jumbo Frame
错误。可能是TSO/GSO分段前或GRO/LRO聚合后的主机内部skb。
TSO和GSO都是网卡硬件功能
错误。TSO通常由硬件执行TCP分段,GSO是Linux软件通用分段机制和回退框架。
GRO与LRO完全等价
错误。两者都做接收聚合,但执行层、保留语义和转发适用性不同。
关闭所有offload是永久最佳实践
错误。它会增加CPU成本且可能掩盖根因;应作为受控诊断手段,根据工作负载和已确认缺陷决定长期设置。
FAQ
1. 为什么tcpdump只把发出的包标为坏校验和?
TX checksum offload让抓包发生时字段尚未最终填写;接收包则可能已经由网卡验证,因此方向表现不同。
2. 远端能正常通信是否证明本机bad checksum是假的?
强烈支持观测伪象判断,但仍应在远端抓包或统计中验证,尤其是存在重传或性能问题时。
3. TSO是否突破MTU?
它允许主机内部提交大skb,但最终会分成符合输出约束的线速包,不是让任意大帧直接上链路。
4. GRO会改变应用收到的TCP字节吗?
不应改变字节流语义;它减少协议栈逐包处理。若出现内容错误,应视为实现或硬件故障调查,而非GRO正常语义。
5. 为什么关闭TX checksum后TSO也关闭了?
TSO需要为每个生成段完成正确校验和,Linux文档说明它通常依赖partial checksum offload,功能因此可能联动。
6. UDP大包是USO还是IP分片?
检查线上每个包是否各有UDP头。USO生成多个UDP datagram,IP分片则一个datagram对应多个IP fragments。
7. 容器里关了GRO为何宿主抓包仍有大包?
其他veth、bridge、隧道或物理接口可能仍执行聚合。需要逐层读取状态并标明抓包点。
8. 什么时候应长期关闭某项offload?
只有在可复现的正确性缺陷、转发语义要求或厂商指导下,经性能评估后实施,并记录接口、驱动版本和恢复条件。
参考来源
- Linux Kernel Documentation:Checksum Offloads
https:
- Linux Kernel Documentation:Segmentation Offloads
https:
- Linux Kernel Documentation:Network Devices, the Kernel, and You!
https:
- Linux
ethtool(8)Manual Page
https:
- RFC 9293:Transmission Control Protocol(TCP校验和)
https:
- RFC 8085:UDP Usage Guidelines(UDP校验和)
https:
- RFC 6935:IPv6 and UDP Checksums for Tunneled Packets