关于MTU (Maximum transmission unit)

* MTU工作在链路层,是网卡传输(发送/接受)的数据桢最大长度。
* Ethernet(乙太网)最大MTU是1500,通常也是大部分设备默认值
* 网卡收到的数据桢长度超过该网卡的MTU时:如果数据桢里的IP或ICMP数据包header没有DF标志(Don’t Fragment flag),将数据分桢(fragmentation),分桢后第二个及以后的桢中只含有一部分IP header,并且没有tcp和udp header;否则,丢弃这个数据桢,并且给src ip发送一个「ICMP fragmentation required「并附带自己的MTU值,src可以根据这个MTU值调整自己发送的数据桢长度。(Path MTU Discovery)。
* 向网卡发送数据时,如果IP数据包长度(header + payload)超过了网卡的MTU,也会进行相同处理。
* TCP协议连接时会协商MSS(maximum segment size ), 本机的MSS是MTU减去ip header减去tcp header长度,最大为1460。取连接双方MSS的较小值。

IPv4 header长度最小为20
IPV6 header长度最小为40
ICMPv4 header长度为20+8
ICMPV6 header长度为40+8
TCP header长度为20
UDP header长度为8
IP(V4 & V6) payload(数据部分)长度最大为65535,因为header中表示长度部分是两位元组。

测试链路MTU

# 1472是ethernet最大值,因为ICMP header长度28
ping -s 1472 -M do 8.8.8.8

#超出长度会从最后通过的路由器(这里就是本机网卡地址)返回ICMP错误(如果该路由器防火墙禁止ICMP则没有返回,直接超时无响应)
ping -s 1473 -M do 8.8.8.8
From A.B.C.D icmp_seq=1 Frag needed and DF set (mtu = 1500)
...

然后有个在景德镇非常流行的奇葩:PPPoE,工作在链路层,header占用8位元组。所以它封装的Ethernet桢最大就不能超过1492。超过的桢在进入pppoe时就要被分桢。因为TCP协议中MSS协商的存在,理论上,如果你使用pppoe上网(即使是用路由器拨号),将所有电脑的网卡MTU设为1492(默认是1500)可以提高性能,不过实际上没什么用。

对于有nf_conntrack模块的iptables,MTU以及fragmentation是透明的,分桢的数据包会在进入INPUT或OUTPUT链前defragmentation重新组装完整。

查看以及修改MTU:

ip link list

ip link set eth0 mtu 1500