目录
1、MTU定义
MTU指一条链路上一个二层报文里面允许承载的二层以上报文的最大长度,单位为byte。
2、MTU设置位置
通常设置在路由器、交换机、电脑网络端口,MTU通常取值为1500。网络端口在接收或者发送报文时,报文的二层以上报文的长度和端口MTU值进行比较,判断是否接收或者分片或者丢弃该报文。
3、以太端口报文
如果是以太端口,报文组成:
4、Trunk端口报文
如果该以太端口为Trunk端口(802.1Q),报文组成:
5、IPv4报文
二层以上报文内容如果是IP格式,此时二层以上报文长度就是IP报文的长度。此时报文组成:
6、IP MTU
针对IP报文的MTU值。
这个值对非IP报文不生效。
7、MTU处理机制
MTU处理机制:
入端口:
路由器接收报文时,二层以上报文长度X和入端口MTU比较:
if 图中X > 入端口MTU:
丢弃该报文
else:
从入口接收该报文
出端口:
路由器需从出端口转发报文时,二层以上报文长度X和出端口MTU比较:
if 图中X > 出端口MTU:
if 出端口是三层端口:
对该报文分片处理(ip fragementation)
if 出口端口是二层端口:
丢弃该报文 (Fragmentation is done only at Layer 3)
else:
从出口转发该报文
8、巨包和小包
一般来说:
大于1500的报文,认为是巨包(a giant packet or a jumbo packet.)
小于64的报文,认为是小包(Runt),会被drop。
9、IP分片机制
只有在发出报文时,如果报文大于出口MTU,对该报文进行分片。具体是否分片,还需要看IPv4 Header的分片设置。
报文分片后,接收节点依靠报文ID把相同报文的不同分片重新组装为分片前的报文。
3个分片标志位:
- R目前保留未用;
- DF:设置为1时,不允许对报文进行分片;如果出端口判断某报文需要分片,但DF设置为不允许分片,则丢弃该报文。
- MF:如果报文没有分片,MF为0;如果报文分片,除最后一个分片,其他分片都设置为1;最后一个分片设置为0,同时offset不为零,从而和没有分片的报文区别开来了。
Fragement offset:主要用来计算分片中的data在原来报文中的位置。注意8个字节为1个偏移量。数值为0,表示从(tcp + data)部分的第0个字节开始。
举例:
某出端口mtu=1476,需转发IP报文长度为1500的报文(DF = 0):
由于1500 > 1476,需分片操作:
分片前报文:IPv4 header + tcp/data = 20 + 1480 ,
分片报文计算方法:
计算第一个报文分片:
由于mtu = 1476,减少分片报文的ipv4头部(20),可以放入tcp/data的最大字节数为:
1476-20 = 1456
以8个字节为1个偏移单位,计算1456有多少个单位的偏移量:
1456/8 = 182
正好被8整除,就是说第一个分片报文可以放入原报文tcp/data部分的1456字节;如果有余数,余数的字节放入下一个分片。
第一个分片报文结构为:
ip0(offset = 0,df = 0, mf = 1) + 1456(tcp/data) = 20 + 1456 = 1476 = mtu
计算第二个报文分片:
还剩下1480-1456 = 24 bytes的tcp/data,放入第二个报文分片,原报文全部数据(1480)分两个分片即可。
第二个分片报文结构为:
ip1(offset=182,df=0,mf=1)+ 24(tcp/data) = 20 + 24 = 44
10、分片带来的问题
会带来一些问题,比如cpu/内存开销,把报文拆成分片,到接收端重组,都有一定开销;分片丢失,如果1个分片在传输过程中丢失,所以分片都要重传;防火墙问题,如果分片不是顺序到达,非首包可能过不了防火墙,因为没有相关会话信息(TCP包头在第一个分片中)。
所以,原则上尽量不要分片。
如何避免,需了解TCP MSS和PMTUD工作机制。TCP MSS可以避免在发送时分片;PMTUD可以避免在整条路径上出现分片操作。
11、TCP MSS工作机制
原来的工作机制
TCP位于第四层。按照协议封装顺序,TCP内容(包括TCP头部),封装到第三层(即增加IPv4头部)。
建立TCP会话的两方,假设一方为A,另一方为B。
TCP Maximum Segment Size (MSS),用来在TCP会话建立时,彼此通告自己一次能接收的TCP层的报文最大值,对方在发送TCP层的报文时,TCP层的报文大小会控制在小于或等于该MSS值。
A会通过发给B的TCP SYN的MSS字段,告知B自己希望一次接收的最大的数据量(TCP层的数据),即MSS-A,假定为16k,B收到后,设置Send MSS = MSS-A=16k;
B会通过发给A的TCP SYN的MSS字段,告知A字节希望一次接收的最大的数据量,即MSS-B,假定为8k,A收到后,设置Send MSS = MSS-B = 8k。
所以TCP MSS不是协商一致机制,而是告知机制,要求对方按照自己提供的MSS发送数据。
假定A的MTU = 1500,如果A按照MSS-B=8k的大小从tcp层发送数据时,交付到IPv4层的时候,显然大于1500,此时就在A(发送端)进行分片操作。
假定B的MTU=4466,B在tcp层按照16k大小发送数据给A时,交付到IPv4层的时候,显然大于4466,B也要进行分片操作。
避免分片的MSS工作机制
为了避免分片,修改了MSS的设置规则,MSS需要和MTU进行比较。
修改后的工作机制:
A的MSS = 16K,MTU=1500,在TCP层的MTU为1500-20-20 = 1460。A会比较这两个值,选择小的作为MSS发送个B,B设置sent mss时,会把这个值和自己的MTU进行比较(B的MTU=4466, TCP层MTU为4466-40=4426),选择较小的为最终send mss = 1460。
B的MSS=8K,MTU=4466,在TCP层的MTU为4466-20-20=4426,B会比较这两个值,选择小的作为MSS发送给A,A设置send mss时,会把这个值和自己的MTU进行比较(A的MTU= 1500,TCP层MTU为1500-20-20=1460),选择较小的为最终的send mss=1460。
A、B在TCP层都按照1460进行分段,交付到ipv4层,都不会大于mtu,这样,A、B在发送数据时,不会出现IP分片操作。
12、PMTUD工作机制
TCP MSS只能避免TCP会话的两端在发送数据时不进行分片,但不能保证整体路径上不出现分片。如果中间路径的mtu小于发送报文的长度,还是需要进行分片。
为了避免整条路径出现分片,需要用到PMTUD,探测路径上的MTU最小值,从而在发送端调整发送报文的大小,避免出现分片。
PMTUD只支持TCP/UDP。
在主机端激活PMTUD时,发出的IP报文DF设置为1,即路径上的节点不允许进行分片操作。
中间路由器如果检测到出口MTU小于IP报文长度时,由于IP报文DF=1,不允许分片,会丢弃该报文,同时向该报文源主机发送ICMP Type 3 Code 4信息,该信息包含可以包含出口MTU值。
发送主机收到ICMP Type 3 Code 4信息后,会调整发送的报文大小,最终按照路径上的最小MTU发送报文,不会出现分片。
同时在发送主机,在路由表里,会保存去往该目的地址需要设置的MTU一段时间。
参考
1、《Resolve IPv4 Fragmentation, MTU, MSS, and PMTUD Issues with GRE and IPsec》
2、《Troubleshoot MTU on Catalyst 9000 Series Switches》