通过 PPPoE(光猫等) 方式上网的用户,MTU 理论最大值为 1492,但是个别运营商会使用稍小的值,如果客户端还设置为 1492,可能会导致网速下降或者无法上网。

关于 MTU

MTU(maximum transmission unit) 其实属于 2 层的一个概念,它的目的是限定「MAC 帧中数据部分(payload)的大小」的值。

为什么要有 MTU?打个比方,网络传输数据时,数据包就像一袋大米,被工人从一个点搬到另一个点。一袋大米的重量是要限制的,太重了工人搬不动,或者半路袋子破了,那就要重新打包,降低了效率;太轻了也不行,力气都浪费在搬空袋子和路上了。MTU 就相当于一袋大米的重量限制,告诉设备数据包封装后最大不能超过多少,设备一般会使用最大值,以便获得最高效率。这个比方可能不是很准确,只是为了方便了解。

一个不可拆分的数据包,小于等于 MTU 会被正常传输,大于 MTU 则会被丢弃或拆分。明白了这个概念,那我们就可以不断加大数据包,直到数据包被丢弃,这样就可以获得 MTU 了。

怎么获得 MTU

ping 是个常见的命令,用于获得 MTU 简单高效。ping 使用的协议是 ICMP(4 层),网络结构中从高层到低层依次是,ICMP → IP → Ethernet(PPPoE)。ICMP 包头是 8 byte,IP 包头是 20 byte。简单来说:

1
ICMP 包大小 + ICMP 包头 + IP 包头 ≤ PPPoE MTU

也就是:ICMP 包最大值 + 28 = PPPoE MTU

PPPoE MTU 理论最大值为 1492(Ethernet MTU 1500 byte - PPPoE header 8 byte),减去 28 的 IP 头和 ICMP 头,得出 ICMP 包最大为 1464 byte。所以我们可以从 1464 开始递减,就可以快速拿到ICMP 包最大值。你也可以尝试增大数字。

ping 不通的说明数字过大,请尝试减小。常见的提示信息有「Message too long」、「packet needs to be fragmented but DF set」。

ICMP 包最大值 + 28就是最优 PPPoE MTU,下文用 {mtu} 表示。。

以下操作都是在 shell 中进行,Windows 请使用 cmd。

macOS MTU 设置

1
2
3
4
5
6
7
8
# 查看网卡接口名称
ifconfig
# 获取最优 mtu
ping -D -s 1464 119.29.29.29
# 查看 mtu(ifconfig 也可以),{iface} 表示网卡接口名称,例如 en0
networksetup -getMTU {iface} 
# 设置 mtu
networksetup -setMTU {iface} {mtu}

-D 表示 “Do not fragment/不要拆分”,-s 指定包大小。

Linux MTU 设置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 查看网卡接口及 mtu (ifconfig 命令)
ifconfig| grep mtu
# 查看网卡接口及 mtu (ip 命令)
ip addr | grep mtu
# 获取最优 mtu
ping -M do -s 1464 119.29.29.29 -4
# 设置 mtu
vim /etc/network/interfaces
添加一行`mtu {mtu}`
# 重启网络服务
/etc/init.d/networking restart

-M do 表示 “Do not fragment/不要拆分”,-s 指定包大小。ping 默认使用IPv6的,加 -4 强制使用 IPv4;不支持 -M 参数的,去掉 -M do;不同 Linux 发行版本,设置 mtu 的方法有差异,以上方法仅供参考。

Windows MTU 设置

1
2
3
4
5
6
# 获得网卡接口 id
netsh interface ipv4 show interfaces
# 获取最优 mtu
ping -f -l 1464 119.29.29.29
# 设置 mtu
netsh interface ipv4 set subinterface {id} mtu={mtu} store=persistent

-f 表示 “Do not fragment/不要拆分”,-l 指定包大小。

其它说明

  • ICMP 包最大值 + 28就是最优 PPPoE MTU。例如,ICMP 包最大值是 1464,则 PPPoE MTU 等于 1464+28= 1492,拨号设备的 MTU 设置为 1492 即可。
  • ping 使用的 IP 地址可以你常用的 dns 或 网站域名。