关闭TSO/GSO导致吞吐下降主因是MTU不匹配引发分片或丢包,而非单纯CPU瓶颈;需确保端到端MTU一致(如全设9000)、调大tcp_rmem/wmem及netdev_max_backlog,并用tcpdump验证分片与重组失败。

为什么 ethtool -K tso off gso off 会导致吞吐下降
关闭 TSO(TCP Segmentation Offload)和 GSO(Generic Segmentation Offload)后,内核必须在协议栈中完成 TCP 分段,CPU 负担显著上升,尤其在高吞吐场景下。但吞吐骤降不单是 CPU 瓶颈问题——更常见的是 MTU 不匹配引发的分片或丢包,尤其是当链路实际支持 jumbo frame(如 9000),而接口或对端仍按默认 1500 设置时,小包激增 + 中断风暴会直接压垮性能。
验证当前 MTU 和 jumbo frame 支持状态
先确认物理链路是否真能跑 jumbo frame,而不是仅“配置了”:
- 查网卡最大支持 MTU:
ethtool eth0 | grep "Supported pause” 不够,要看ethtool -i eth0查驱动型号,再结合厂商文档确认硬件级 jumbo 支持;更直接的是运行ethtool -k eth0 | grep "receive-jumbo”(部分驱动暴露此字段) - 查当前生效 MTU:
ip link show eth0 | grep mtu - 查交换机端口 MTU:需登录交换机,例如 Cisco:
show interfaces gigabitethernet 1/0/1 | include mtu;华为:display interface gigabitethernet 0/0/1 - 用
ping -M do -s 8972 192.168.1.1测试路径 MTU(8972 = 9000 − 28 字节 IP+ICMP 头),若返回ping: local error: Message too long,说明某处卡在 1500
关闭 offload 后必须同步检查的三个参数
TSO/GSO 关闭后,MTU 错配的影响会被放大,以下三项必须一致且合理:
-
ip link set eth0 mtu 9000—— 接口 MTU 必须与链路能力对齐;设为 1500 时,即使物理通路支持 jumbo,也会强制分片,吞吐归零 -
sysctl net.ipv4.tcp_rmem和net.ipv4.tcp_wmem—— 关闭 offload 后,大窗口 + 小缓冲区易触发频繁 ACK 和重传;建议调高 min/default/max,例如4096 65536 16777216 -
sysctl net.core.netdev_max_backlog—— 默认 1000 不够用,关闭 GSO 后软中断处理包速下降,队列溢出导致丢包;建议设为5000或更高
抓包定位 MTU / 分片问题的关键位置
不要只看 tcpdump -i eth0,重点过滤异常帧:
- 查 IP 分片:
tcpdump -i eth0 'ip[6:2] & 0x1fff != 0'(IP 分片标志或 fragment offset 非零) - 查 ICMP “need to frag”:
tcpdump -i eth0 'icmp[0] == 3 and icmp[1] == 4' - 对比收发包大小分布:
tcpdump -i eth0 -w cap.pcap -c 1000后用 Wireshark → Statistics → Packet Lengths,看是否大量集中在 1500± 附近(说明被截断) - 特别注意:如果对端没关 TSO,它发出的超大 TCP 段(>1500)经你关 offload 的机器接收时,可能因 IP 层无法重组而静默丢弃 —— 此时
netstat -s | grep -i "reasm"会显示reasm fails
MTU 验证不是改一个值就完事,关键在端到端一致性;jumbo frame 的收益必须由整条路径共同支撑,缺一不可。最容易被忽略的是交换机 MTU 和中间防火墙/负载均衡器的分片策略,它们往往静默丢弃大包而不报错。










