您现在的位置是:首页 >技术杂谈 >Linux 检测通信路径上的PMTU(路径最大传输单元)网站首页技术杂谈

Linux 检测通信路径上的PMTU(路径最大传输单元)

bitcsljl 2024-06-24 18:01:02
简介Linux 检测通信路径上的PMTU(路径最大传输单元)

问题描述

终端设备向云端POST数据,数据量较小的没有问题,数据量大的必然出现丢包。网络很通畅,延迟较低。

分析

后来发现,终端到云端的通信路径上某个路由器节点的MTU小于终端的MTU,当终端发出的IP数据包长度大于该路由器节点的MTU时,IP数据包被丢弃。

处理方法

降低终端(Linux系统)的MTU。这里包含两个问题:

  1. 如何设置MTU?
  2. MTU设置为多少?

如何设置MTU?

什么是MTU?

MTU: MTU( Maximum Transmission Unit),最大传输单元,单位是字节。

大部分的网络设备的mtu默认值是1500。如果本机的mtu值大于网关的mtu值,大的数据包就会被拆开来传送,这样会产生数据包的碎片,增加丢包率,降低网络速度。把mtu设置比网关小或者相同,可以减少丢包。设置合适的mtu值,可以减少部分网站打不开,上网速度慢等问题。一般情况,可以把路由器、交换机和服务器的mtu值统一设置。

查看服务器的mtu值

cat /sys/class/net/网口名称/mtu

或者

# ifconfig
ens18: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1200

临时修改mtu值:(重启服务器后失效)

ifconfig  <网口名称> mtu 1200

永久生效

在NetworkManager的连接配置文件里配置mtu,在[ethernet]选项添加一行 mtu=1280:
在这里插入图片描述

MTU设置为多少?

MTU设置为多少比较合理?可以设置为PMTU的值。

PMTU是什么?

PMTU是Path MTU(Maximum Transmission Unit)的缩写,指的是在网络通信中,从源主机到目的主机所经过的所有网络设备中,能够通过的最大数据包大小。PMTU的原理是通过不断发送大小不同的数据包,直到发现一个最大的数据包能够成功传输,从而确定PMTU的大小。

PMTU的应用主要是在TCP/IP协议中,用于避免IP分片。当一个数据包的大小超过了某个网络设备的MTU时,该设备会将数据包分片,然后再将分片后的数据包发送出去。这样会增加网络传输的负担,降低网络传输的效率。因此,TCP/IP协议中的PMTU发现机制可以帮助避免IP分片,提高网络传输的效率。

怎么检测PMTU?

可以使用ping命令来检测。

PMTU最初是为IPv4路由器设计的。可以使用ICMP协议中的type和code字段发送MTU=XXX的消息,当这个ICMP消息到达IP包的源主机时,源主机将设置正确的MTU。

可以使用ping命令来检测PMTU,例如:

ping -c 4 -M do -s 1472 <IPv4 Address>

其中,-c 指定ping的次数。

-M <pmtud opt>     define mtu discovery, can be one of <do|dont|want>

Select Path MTU Discovery strategy. pmtudisc_option may be
either
do (prohibit fragmentation, even local one),
want (do PMTU discovery, fragment locally when packet size is large),
or
dont (do not set DF flag).

-M do 表示在传输过程中,IP数据包禁止分包,如果路由器收到长度比自身设置的MTU大的IP数据包,则不能拆分,只能丢弃,并在ICMP回复报文中设置MTU大小。

-s 1472 表示设置ICMP的PDU(有效载荷)为1472字节。ping 使用的是ICMP协议,ICMP的下层协议是IP协议,ICMP首部(header)共8字节,IP首部(header)共20字节,ICMP的IP数据包 = IP首部 + ICMP首部 + ICMP的PDU,所以 -s 1472 表示 整个IP数据包的长度等于20+8+1472 = 1500 字节。

如果源主机到目的主机的通信路径中有节点的MTU小于1500,则会返回ICMP消息“message too long”到达IP包的源主机:

# ping -c 4 -M do -s 1472 x.x.x.x
PING x.x.x.x (x.x.x.x) 1472(1500) bytes of data.
ping: local error: message too long, mtu=1492
ping: local error: message too long, mtu=1492
ping: local error: message too long, mtu=1492
ping: local error: message too long, mtu=1492

--- 123.103.127.118 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3051ms

推荐的MTU值是1492,去掉ICMP首部(header)的8字节和IP首部(header)的20字节,1492 - 28 = 1464,-s 的值修改为1464试试:

# ping -c 4 -M do -s 1464 x.x.x.x
PING x.x.x.x (x.x.x.x) 1464(1492) bytes of data.
1472 bytes from x.x.x.x: icmp_seq=1 ttl=49 time=20.2 ms
1472 bytes from x.x.x.x: icmp_seq=2 ttl=49 time=20.4 ms
1472 bytes from x.x.x.x: icmp_seq=3 ttl=49 time=20.6 ms
1472 bytes from x.x.x.x: icmp_seq=4 ttl=49 time=20.4 ms

--- 123.103.127.118 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 20.241/20.402/20.563/0.114 ms

将源主机的MTU值修改为1492后,问题解决。

如果仍返回“message too long”,可以逐步降低-s 的值,直至ping返回成功。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。