关闭TSO后吞吐下降是因为内核转为软件分段,CPU开销增大,且GSO fallback导致额外封装、cache miss和延迟;需按顺序关闭TSO和GSO,并确认相关内核参数与队列限制。

为什么 ethtool -K tso off 会导致吞吐下降
关闭 TCP 分段卸载(TSO)后,内核必须在协议栈中完成 TCP 段的分片和 IP 封装,这会显著增加 CPU 开销,尤其在高吞吐、大包场景下。关键在于:TSO 关闭后,generic-segmentation-offload(GSO)路径仍可能被触发,但此时已无硬件配合,反而因额外封装和 skb 分割引入延迟与 cache miss。
如何确认 GSO 是否仍在生效并造成干扰
用 ethtool -k 查看当前卸载状态,重点检查:generic-segmentation-offload 和 tcp-segmentation-offload 两项是否均为 off;若前者为 on 而后者为 off,说明 GSO 正在强制 fallback 到软件分段,这是性能下降的典型诱因。
-
ethtool -k eth0 | grep -E "(generic|tcp)-segmentation"—— 必须两者都 off 才算干净回滚 - 抓包验证:
tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'观察是否有异常的超小 MSS 分段或重传激增 -
cat /proc/net/snmp | grep -A1 Tcp中TCPSegsOut增速若远高于应用发包速率,说明 GSO fallback 导致重复分段
安全关闭 GSO 的正确顺序
不能只关 TSO——GSO 是上层通用机制,TSO 只是其一个后端。直接关 GSO 可能影响 UDP GSO(如 VXLAN)、SCTP 等,需按依赖层级操作:
- 先关 TSO:
ethtool -K eth0 tso off - 再关 GSO:
ethtool -K eth0 gso off(注意不是generic-segmentation-offload这个显示名,命令里用的是gso) - 最后确认:
ethtool -k eth0 | grep -i "segmentation.*off"应全部显示off - 若需保留 UDP GSO(如隧道场景),可只关 TCP 相关:
ethtool -K eth0 tso off gso off,但保留ufo off(UDP 分片卸载)
回滚测试时容易忽略的 kernel 参数干扰
即使 ethtool 显示全关,/proc/sys/net/ipv4/tcp_tso_win_divisor 或 net.ipv4.tcp_slow_start_after_idle 等参数仍可能间接放大 GSO fallback 的副作用。特别是:tcp_tso_win_divisor 非零时,内核会在窗口缩小时主动触发 GSO 分段,哪怕 TSO 已关。
- 临时清空干扰:
echo 0 > /proc/sys/net/ipv4/tcp_tso_win_divisor - 检查是否启用了 BQL(Byte Queue Limits):
cat /sys/class/net/eth0/queues/tx-0/byte_queue_limits/limit_max,值非 0 时可能压制发送节奏,掩盖真实 GSO 行为 - 测试务必在相同 socket buffer 设置下对比:
ss -i确认skmem和wmem未被自动调优扰动
GSO 的 fallback 行为高度依赖 skb 数据长度、MSS、拥塞窗口和 socket 写队列状态,单靠 ethtool 输出无法反映运行时实际分段逻辑——得看 /proc/net/snmp 和 perf record -e skb:kfree_skb 的分段点分布。











