tcpdump 显示 64 KB 数据包:卸载与抓包位置
主机抓包中的巨型数据包可能出现在分段之前或聚合之后。在断定隧道忽略了其 MTU 之前,先确定观测位置。
在主机上抓包,可能会在 MTU 为 1420 的接口上看到 64 KB 的数据包,显而易见的结论是隧道忽略了自己的大小限制。这个结论通常是错的。主机上的抓包点位于处理路径内部,此时分段、聚合和校验和计算可能尚未发生。在读数据包大小之前,先读观测点的位置。
抓包位置改变了你看到的东西
发送卸载让协议栈把一个很大的单元交给网卡,由网卡稍后切成线路大小的小块。接收聚合则在入向路径上做相反的事,在主机侧观测者看到之前就把分段合并起来。因此抓包记录的是该位置主机的内部视图,不一定是链路上的帧。两种机制都取决于设备和路径。
ethtool -k eth0 | grep -E 'tso|gso|gro'
在把大小当成故障之前,到第二个位置抓包,最好是独立的接收端或镜像口。如果大单元只出现在发送主机上,线路上可能从未承载过它。两个观测点比一个文件更有力,尤其是当问题在于究竟什么离开了这台机器时。
把内层和外层接口分开
隧道会新增自己的接口,而且外层与内层的视图在封装和处理上并不相同。在隧道设备上抓包看到的是内层数据包,在物理网卡上抓包看到的是外层数据包。两者之间的大小、地址和校验和状态可能不同,原因与故障毫无关系。
记录每个文件由哪个接口产生。在隧道设备上看到的大小描述的是内层数据包,而不是网卡最终发出的帧。把两者混在一次分析里,正是普通封装差异变成谜团的方式。
校验和警告同样取决于位置
发送侧的抓包可能在硬件填入校验和之前就显示该字段,从而产生任何接收端都不会看到的警告。这与远端主机拒收损坏数据包是不同的证据。方向和抓包位置决定了你手里是哪一种。
当实际传输失败时,比较接收端或路径上另一点处的观测。把方向、接口和封装层与记录一起保存,因为没有这些信息的截图事后无法解释。
只把关闭卸载当作受控测试
关闭卸载会改变性能和包处理方式,所以它不是面对奇怪大小显示的第一反应。如果要测试,只改一个设置,并先记录基线。同时改动 MTU、防火墙规则和客户端配置的运行,无法把结果归因于卸载。测试后恢复设置。
ethtool -K eth0 tso off gro off
ping -M do -s 1400 example.com
真正的大传输停滞是另一个问题,涉及路径 MTU 和应用得到的反馈。主机的聚合单元既不能证明也不能否定下游的大小限制,低 CPU 占用率也不能说明卸载就是原因。
有用的结果是解释清楚的抓包位置,加上可复现的应用层观测。把这两者分开之后,MTU 调整才能针对真正的约束,而不是针对内部缓冲区的形状。