WSL2环境下启用MTU 9000巨帧后,符合MTU的大报文ping目标设备异常丢包
遇到这种情况确实挺闹心的——明明两边都确认支持巨帧,小包能通、超MTU的包报错也符合预期,但卡在MTU范围内的大包却全丢,完全摸不着头绪对吧?结合你给出的测试细节,我来帮你梳理几个可能的排查方向:
先确认WSL2虚拟交换机的MTU是否同步
WSL2是通过Hyper-V虚拟交换机和宿主机物理网卡通信的,很多人容易忽略这一层的MTU配置:你虽然在Windows物理网卡和WSL内部网卡都设了9000,但虚拟交换机可能还是默认的1500,这就会导致大报文在转发时被丢包。
你可以在Windows Powershell里执行以下命令检查:
Get-VMSwitch | Select-Object Name, MTU
找到对应WSL的虚拟交换机(通常名称是WSL),如果它的MTU不是9000,就用这条命令修改:
Set-VMSwitch -Name "WSL" -MTU 9000
修改完成后记得重启WSL(wsl --shutdown再重新打开Ubuntu),再测试ping。
检查分片禁用参数的影响
你用了-M do参数强制禁止分片,虽然你计算的8900字节+ICMP头部28字节=8928字节,确实小于9000MTU,但WSL2的虚拟网络栈在转发时可能会额外添加虚拟头部(比如Hyper-V的封装头部),导致实际报文大小超过了MTU。这时候因为禁用了分片,报文直接被丢弃,而且不会返回“message too long”错误(因为系统计算的是应用层大小,没算额外的虚拟头部)。
你可以先去掉-M do参数测试:
ping 10.0.0.10 -c 10 -s 8900
如果能通,说明问题就出在分片禁用上。这时候你可以适当减小发送的包大小(比如改成8872字节,8872+28=8900,留足虚拟头部的空间),或者确认虚拟交换机的MTU是否真的能承载9000字节的完整报文。
用TCP报文排除ICMP层面的问题
有时候目标设备的防火墙或者安全策略会拦截大的ICMP包,但允许TCP大报文通过。你可以用nc命令做个测试:
- 在目标设备上开启监听:
nc -l 1234 - 在WSL2里发送大报文:
dd if=/dev/zero bs=8900 count=1 | nc 10.0.0.10 1234
如果TCP能发送成功,说明巨帧本身是通的,问题出在ICMP的配置上(比如目标设备禁用了大ICMP包,或者你的ping参数还有其他限制)。
更新WSL到最新版本排除bug
有些旧版本的WSL2在巨帧支持上存在兼容性bug,建议你先更新到最新版本:
在Windows Powershell里执行:
wsl --update
更新完成后重启WSL,再测试ping,说不定就能解决问题。
备注:内容来源于stack exchange,提问作者C. Crt




