首页 / 内容指南 / 当前文章

Linux 的 TX/RX Checksum Offload、TSO、GSO、GRO、LRO 和抓包坏校验和有什么区别?

发布于 2026-08-26 · xieyipai.com 编辑部

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 表示这类请求:驱动必须保证最终发送包中的校验和正确,要么让硬件完成,要么调用软件辅助函数回退。

“partial”不是说线上允许残缺校验和,而是主机内部当前缓冲仍等待后续完成。若网卡不支持特定封装或头部布局,协议栈应在软件中补算。

为什么本机出站抓包显示 Bad Checksum

抓包程序常在网卡真正填充校验和之前复制出站 skb。抓到的副本仍含中间值,分析器用完整算法验证,自然会标成 incorrect 或 bad;实际帧离开网卡时,硬件已经写入正确结果。

要判断真假,应在另一台物理主机、交换机镜像端口或卸载之后的可信点位抓包。若远端成功接收且远端抓包校验正确,本机发送侧的 bad checksum 多半只是观察位置效应。

RX Checksum Offload 不一定改写包字段

接收网卡可以验证TCP、UDP等校验和,并通过驱动元数据告诉内核结果。Linux内核文档说明,CHECKSUM_UNNECESSARY 表示硬件已针对支持的协议验证成功,但 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/bridge/tunnel的位置。

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更好看但吞吐下降”简单判为修复成功。

一套分层排障流程

  1. 确认是校验和告警、超MTU显示、真实丢包还是性能问题。
  2. 记录本机所有相关接口的 ethtool -k 和统计信息。
  3. 同时在发送主机、远端主机或镜像端口抓取同一五元组。
  4. 用TCP序列号、IP ID、时间和payload摘要关联两端包。
  5. 判断大skb是在发送分段前还是接收聚合后看到。
  6. 检查物理、虚拟、隧道、NAT与容器各层的offload能力。
  7. 在维护窗口一次关闭一个相关功能做A/B对照。
  8. 若确认真实故障,升级或回退驱动/固件并保存复现证据。

常见误区

本机出站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?

只有在可复现的正确性缺陷、转发语义要求或厂商指导下,经性能评估后实施,并记录接口、驱动版本和恢复条件。

参考来源

  1. Linux Kernel Documentation:Checksum Offloads

https://www.kernel.org/doc/html/latest/networking/checksum-offloads.html

  1. Linux Kernel Documentation:Segmentation Offloads

https://www.kernel.org/doc/html/latest/networking/segmentation-offloads.html

  1. Linux Kernel Documentation:Network Devices, the Kernel, and You!

https://www.kernel.org/doc/html/latest/networking/netdevices.html

  1. Linux ethtool(8) Manual Page

https://man7.org/linux/man-pages/man8/ethtool.8.html

  1. RFC 9293:Transmission Control Protocol(TCP校验和)

https://www.rfc-editor.org/rfc/rfc9293.html

  1. RFC 8085:UDP Usage Guidelines(UDP校验和)

https://www.rfc-editor.org/rfc/rfc8085.html

  1. RFC 6935:IPv6 and UDP Checksums for Tunneled Packets

https://www.rfc-editor.org/rfc/rfc6935.html