乐于分享
好东西不私藏

TSO/GRO网卡卸载技术详解!附Linux配置调整命令(建议收藏)

TSO/GRO网卡卸载技术详解!附Linux配置调整命令(建议收藏)

抓包看到超大报文别慌,那是网卡在帮你“作弊”

前两天有个读者私信留言发了一张tcpdump截图,一脸困惑:“我的网卡明明协商的MSS是1460,怎么抓包抓到2800多字节的TCP载荷?是不是网卡坏了?”

这不是网卡坏了,而是网卡太“聪明”了。今天我们就来聊聊TSO和GRO这两个让网卡帮CPU“作弊”的技术。

一、先讲个故事:CPU的“分拣员”困境

想象一下,你是一个快递中转站的经理(CPU),每天要处理几万件快递(网络数据包)。每个快递都要你亲手拆开、分拣、打包、贴单……忙得满头大汗。

后来你招了个实习生(网卡),跟他说:“小卡,以后大包裹你帮我拆成标准小件再发出去(TSO);送来的小件你帮我拼成大包裹再拿给我(GRO)。”

这就是Offload技术的本质:把CPU的“脏活累活”卸载给网卡硬件,让专业的人做专业的事。

ps:可苦了“网卡”小兄弟了...,实习生不容易呀,找工作不容易呀。

1.1 TSO:发送端的大包拆分助手

TSO全称TCP Segmentation Offload,是发送方向的卸载技术。传统模式下,内核协议栈要把数据切成一个个MSS大小的小段,再交给网卡发送。开启TSO后:

  • • 内核:把几KB甚至几十KB的大块数据直接扔给网卡
  • • 网卡:按照MSS自动切分成小报文,加上TCP头部,再发到网络

好比你要寄一箱书,快递站小哥(CPU)本来要一本一本打包,现在你直接把整箱书扔给自动分拣机(网卡),机器自己拆成标准包裹。

1.2 GRO:接收端的拼包神器

GRO是Generic Receive Offload,接收方向的“反向操作”。网络上传来的是一个个小报文,开启GRO后:

  • • 网卡:把多个连续的小报文拼接成一个大段
  • • 内核:一次处理一大块数据,而不是被几百个小包“轰炸”

还是快递的例子:快递站把一堆小包裹自动捆成一个大箱子再送到你手上,你开箱一次就能取出所有东西,不用拆100次小包裹。

1.3 抓包看到“超规”报文?别慌

很多刚接触TSO/GRO的朋友会犯晕:用tcpdump抓包,明明协商的MSS是1460,怎么看到本机发出的包TCP length有2800?

原因很简单:tcpdump的抓包点在“内核与网卡之间”。开启TSO后,内核交给网卡的大包还没被拆分,tcpdump先“偷看”到了。同理,开启GRO后,网卡合并后的大包被内核接收前,tcpdump也看到了“合并成果”。

# 抓包看到的现象示例
# 本机发出的包,TCP length = 2800 > 1460

12:34:56.789012 IP 10.0.0.1.12345 > 10.0.0.2.80: Flags [P.], seq 1:2801, ack 1, ...

这不是网卡坏了,是网卡帮你“作弊”成功了。

二、IP分片?生产环境请远离它

聊到TSO,顺便提一下IP分片。很多人搞混“TCP分段”和“IP分片”。TCP分段由TSO/网卡完成,而IP分片是网络层的“下下策”。

IP分片有个致命缺陷:只有第一个分片携带TCP头部,后续分片没有四层信息。防火墙看到后续分片,不知道是TCP还是UDP,直接当非法报文丢弃。

所以生产环境,内核协议栈默认尽量避免IP分片——要么靠路径MTU发现,要么靠TSO在发送端就切好。

三、Linux上手实操:ethtool三板斧(建议收藏噢)

说了这么多理论,咱们直接上命令。TSO/GRO是网卡驱动级别的特性,Linux下用ethtool管理。

3.1 第一步:找到你的网卡

# 推荐方法
ip link
# 或者

ifconfig -a

常见网卡名:eth0、ens192、bond0等。

3.2 第二步:查看当前状态

ethtool -k eth0 | grep -E "tcp-segmentation|generic-receive"

输出示例:

tcp-segmentation-offload: on
generic-receive-offload: on

3.3 第三步:开启或关闭

# 开启(需要sudo)
sudo
 ethtool -K eth0 tso on gro on

# 关闭

sudo
 ethtool -K eth0 tso off gro off

# 单独操作

sudo
 ethtool -K eth0 tso on
sudo
 ethtool -K eth0 gro on

3.4 第四步:验证是否生效

# 再次查看状态
ethtool -k eth0 | grep -E "tcp-segmentation|generic-receive"
# 或者用抓包实测

tcpdump -i eth0 -c 10 -n -v

四、避坑指南:这几个点必须知道

⚠️ 坑1:重启就失效

ethtool配置是临时生效的,服务器重启、网卡重启(比如ifdown/ifup)后会恢复默认。要永久生效,有两种方法:

方法一:写开机自启脚本

# /etc/rc.local 或 systemd service
/sbin/ethtool -K eth0 tso on gro on

方法二:修改网络配置文件(以CentOS/RHEL为例)

# 在 /etc/sysconfig/network-scripts/ifcfg-eth0 中添加
ETHTOOL_OPTS="-K eth0 tso on gro on"

⚠️ 坑2:老网卡或虚拟网卡不支持

部分老旧网卡、低版本虚拟化网卡(如virtio早期版本)可能不支持。执行命令会提示:

Cannot set device feature settings: Operation not supported

遇到这种情况,要么升级驱动/虚拟化环境,要么认命——关掉它。

⚠️ 坑3:抓包排障时记得关掉

如果你用tcpdump分析问题,比如怀疑对方发的包超过了MSS,记得临时关闭TSO/GRO,否则抓包数据是“作弊后”的,可能误导排查。

# 排障时临时关闭
sudo
 ethtool -K eth0 tso off gro off
# 排障完再开启

sudo
 ethtool -K eth0 tso on gro on

⚠️ 坑4:生产环境改前先测试

虽然TSO/GRO默认大多开启,但某些业务(比如DPDK、某些深度包检测设备)可能要求关闭。一定先在测试环境验证,别直接上生产。

五、性能实测:能省多少CPU?

我在一台10Gbps网卡的服务器上做过对比测试(大文件传输,约10GB):

配置
CPU使用率(内核态)
吞吐量
TSO/GRO关闭
35-40%
9.2 Gbps
TSO/GRO开启
12-15%
9.4 Gbps

CPU占用降低了约60%,吞吐量还略有提升。这就是硬件卸载的魅力。

六、一张图总结TSO/GRO

发送端                                    接收端
应用层数据(大块)                      应用层数据(大块)
     ↓                                         ↑
内核协议栈(几乎不做事)                 内核协议栈(一次处理大块)
     ↓ (大包)                                 ↑ (大包)
【抓包点】tcpdump看到大包 ←→ 【抓包点】tcpdump看到大包
     ↓                                         ↑
网卡硬件(TSO切分)                      网卡硬件(GRO合并)
     ↓ (小包)                                 ↑ (小包)
网络线缆  -------------------------------→

写在最后

TSO和GRO是现代数据中心网络里默默无闻的“幕后英雄”。它们不像DPDK那样炫酷,但几乎每台Linux服务器都在默默享受它们带来的性能提升。

下次你再抓包看到“超大TCP报文”,别大惊小怪,那是你的网卡在帮你干活。


你在配置网卡Offload特性时遇到过什么坑?有没有因为TSO/GRO导致抓包问题排查了半天?欢迎留言区一起聊聊!

如果觉得文章对你有帮助,欢迎点赞、在看、转发给身边被网络问题困扰的朋友~