概念
MTU:maximum transmission unit, 二层协议里面的最大传输单元
MSS:maximum segment size
MTU - (TCP header + IP header) = MSS
MTU - (20 + 20) = MSS
MTU
MTU 受限于物理传输介质
常见的为以太网,MTU 一般为 1500bytes,实际在链路上传输的大小为 MTU + Ethernet header + FCS = 1500 + 14 + 4 = 1518 bytes
MTU 的大小意味着什么
MTU 越大,整个传输的效率就越高
原因:MTU 大时,以太网桢的头尾占比较小,实际传输的数据相对更多,所以效率高
注意:受限于物理因素,效率无法无限增加 - MTU 过大时丢失/损坏概率也大,会导致需要重传,效率反而降低
MTU 越小,整个传输的延迟越低
链路上同时只能传输一个包,如果一个包过大,其他包可能来不及传输,造成整体延迟增大
超过 MTU 限制会发生什么
绝大多数的系统和物理设计都是丢失
注:部分设备的实际触发 drop 的 MTU 和声明的最大 MTU 不同(留有一定的缓冲区间)
jumbo frame
Jumbo Frame 可以最大支持 9000 bytes,提高传输的速率。不过现实中基本上见不到、互联网上更见不到
因为 Ethernet 是 2 层协议,负责点对点的传输,如果因特网上如果一个 Jombo Frame 要能从用户传到另一个用户或服务,这需要所有点对点设备都要支持才行
而现实的世界里,基本上网络上所有的路由,交换设备,端设备,路由器,设置的 MTU 都是 1500
MSS
如何修改 MSS
iptables: iptables -I OUTPUT -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 48
ip route: ip route change 192.168.11.0/24 dev ens33 proto kernel scope link src 192.168.11.111 metric 100 advmss 48
程序想办法自己往 TCP option 里写 MSS
MSS Calmping
包可能不是直接传输的,中间可能经过了隧道,而隧道自己也有一些元数据需要控制
因此隧道传输时,可能修改包信息降低告知对端的 MSS
MSS 过大会造成什么?
IPv4
如果 MSS > MTU - headers(对于以太网,即大于 1460bytes),那么会导致 IP 分片
IP 分片在实际生产中是避免的 —— 因为若干弊端,都会尽量避免 IP 分片
只能整体重传
如果一个包因为 IP 分片变成了 3 个 fragment,包丢失必须 3 个 fragment 一起重传
处理延迟
对端会等所有的 fragment 到达才会交给上层处理
某些系统是不支持(或特意禁用了)IP Fragment
IPv6
IPv6 是禁止 IP 分片的(IPv4 可以通过指定 DF bit 来禁止分片)
当 MTU 过大时,会直接丢弃包然后回复一个 ICMP 包(Type = 3,Code = 4)
引申:当 ICMP 包被禁用 / 错误路由,会导致黑洞连接
TSO
TCP Segment Offload
在机器上抓包时可能发现「发送的数据大于 MSS」,这是因为如果网卡支持 TSO,那么内核会将 TCP 拆包的工作转移给网卡进行
同理,接收时,开启 TSO 的情况下网卡也可能直接完整 TCP 组包
可以通过 ethtool -K eth0 tx off 关闭 TSO
参考
https://en.wikipedia.org/wiki/Maximum_transmission_unit
https://www.kawabangga.com/posts/4983