MTU是Maximum Transmission Unit的缩写,意为最大传输单元,通俗的理解就是在网络上传送的最大数据包,单位是字节。
以太网对数据帧的长度都有一个限制,其最大值为1500,这个特性被称作MTU,不同类型的网络大多数都有一个上限。如果IP层有一个IP包要传,而且数据的长度比链路层上的MTU值还要大,那么就需要对这个数据包进行分片处理,而且要求被分片的每个数据包都要等于或小于这个MTU值,一般是最后一个数据包小于这个值。例如,一个大小为5000字节的数据包在穿越网络时,如果遇到一条MTU大小为1500字节的数据链路,即数据帧对多能容纳大小为1500字节的数据包。需要在数据成帧之前将数据包分片成多个小的数据包。被分片后,每片数据包的标示字段上打上相同的标记,以便接收者可以识别出属于同一个数据包的分片。如果不分片,该数据包就会被丢弃,从而造成数据包丢失。但是,如果因为MTU值设定得太小,以致于一个不是很大的数据包被分成许多片进行传输,这样就会产生很多数据包碎片,增加了设备负担,降低了网络使用率。
EthernetII帧的结构DMAC+SMAC+Type+Data+CRC。由于以太网传输电气方面的限制,每个以太网帧都有最小的大小64bytes,最大不能超过1518bytes,对于小于或者大于这个限制的以太网帧我们都可以视之为错误的数据帧,一般的以太网转发设备会丢弃这些数据帧。 小于64Bytes的数据帧一般是由于以太网冲突产生的“碎片”或者线路干扰或者坏的以太网接口产生的,对于这些小于64Bytes的“碎片”,MAC子层就会在数据字段的后面填充以满足整个数据帧长不小于64字节,以便传输。
为什么以太网规定会规定数据帧长度不小于64字节?
以太网是不可靠的,这就意味着发送者并不知道自己发出的数据对端是否收到,但如果它发出的数据包出现错误,则会进行重传。什么时候会发生错误,发生错误是指什么呢,以太网是如何检测到错误的?
以太网的错误主要是发生碰撞,碰撞是指两台机器同时监听到网络是空闲的,同时发送数据,就会发生碰撞,碰撞对于以太网来说是正常的。非常有名的CSMA/CD就是用来检测冲突的。假设A检测到网络是空闲的,开始发数据包,尽力传输,当数据包还没有到达B时,B也监测到网络是空闲的,开始发数据包,这时就会发生碰撞,B发现发生碰撞,开始发送碰撞信号,所谓碰撞信号,就是连续的01010101或者10101010,十六进制就是55或AA。这个碰撞信号会返回到A,如果碰撞信号到达A时,A还没有发完这个数据包,A就知道这个数据包发生了错误,就会重传这个数据包。但如果碰撞信号会返回到A时,数据包已经发完(在数据包比较短的情况下),则A不会重传这个数据包。
以太网为什么要设计这样的重传机制。首先,以太网不想采用连接机制,因为会降低效率,但他又想有一定的重传机制,因为以太网的重传是微秒级,而传输层的重传,如TCP的重传达到毫秒级,应用层的重传更达到秒级,我们可以看到越底层的重传,速度越快,所以对于以太网错误,以太网必须有重传机制。要保证以太网的重传,必须保证A收到碰撞信号的时候,数据包没有传完,要实现这一要求,A和B之间的距离很关键,也就是说信号在A和B之间传输的来回时间必须控制在一定范围之内。IEEE定义了这个标准,一个碰撞域内,最远的两台机器之间的round-trip time 要小于512bit time.(来回时间小于512位时,所谓位时就是传输一个比特需要的时间)。这也是我们常说的一个碰撞域的直径。512个位时,也就是64字节的传输时间,如果以太网数据包大于或等于64个字节,就能保证碰撞信号到达A的时候,数据包还没有传完。
512bit time是如何得来的?
先看一下一个比较古老但流行一时的标准:10BASE5,一种以太网标准,该标准用于使用粗同轴电缆、速度为10Mbps的基带局域网络,在总线型网络中,最远传输距离为500米。网络节点装有收发器,该收发器插在网卡上的15针连接单元接口(Attachment Unit Interface)中,并接到电缆上。也作thick Ethernet,ThickNet,ThickWare。另见coaxial cable,Ethernet,指的是使用标准的(粗)50Ω基带同轴电缆的10Mbit/s的基带以太网规范。它是IEEE802.3基带物理层规范的一部分,在每个网段上的距离限制是500m,整个网络最大跨度为2500m,每个网段最多终端数量为100台,每个工作站距离为2.5m的整数倍。上面提到的这个碰撞域的来回时间其实就是当时依据10M网络的标准来定义的,10BASE5允许最远的两个工作站间距离2.5公里 ,电子信号在2.5公里來回时间约为51.2us。根据CSMA/CD,最小封包以51.2us计算和10Mbps计算:51.2us * 10Mbps = 512 bit = 64 byte。这就是为什么以太网要最小64个字节的历史原因了,一个是基于CSMA/CD的需要,另外一个就是依据了当时10M网络的标准进行了计算和定义。
以太网帧最大不能超过1518bytes,这也是一个规定,但没有上述的这些限制,之所以规定为1518,主要是考虑到传输效率正确率。由于以太网EthernetII最大的数据帧是1518Bytes,这样,除去以太网帧的帧头(DMAC目的MAC地址48bit=6Bytes+SMAC源MAC地址48bit=6Bytes+Type域2bytes)14Bytes和帧尾CRC(FCS)校验部分4Bytes。那么剩下承载上层协议的地方也就是Data域最大就只能有1500Bytes这个值我们就把它称之为MTU。这个就是网络层协议非常关心的地方,因为网络层协议比如IP协议会根据这个值来决定是否把上层传下来的数据进行分片。就好比一个盒子没法装下一大块面包,我们需要把面包切成片,装在多个盒子里面一样的道理。
PPPOE环境下的MTU值设定
为什么在PPPOE拨号连接的情况下,将MTU设置大于1492时会出现ping大包不通的情况呢?先要弄清楚,MTU包含了那些东西,值是怎样算出来的?在上述网络环境下,路由器拨号接口下的MTU值设置为1500,主机ping www.qq.com –l 1470测试时抓包查看。此时是不能ping的。命令ping www.qq.com –l 1470中的1470表示的是这个ICMP包的净载荷数据长度为1470字节。结合上图,抓取的ICMP报文中包含:Ethernet Header、IP Header、ICMP - Internet Control Messages Protocol及FCS - Frame Check Sequence等内容。其各项所占字节长度如下表:
项目 | 内容 | 长度(字节) | 备注 |
Packet Length |
| 1516 | 数据包总长度 |
Ethernet Header | Destination | 6 | 目的MAC及源MAC分别为48Bit,分别占6字节 |
Source: | 6 | ||
Protocol Type: | 2 | ||
IP Header | Header Length: | 20 | IP报头 |
ICMP | ICMP Type | 8 | ICMP报头 |
ICMP Data Area: | 1470 | ICMP净载荷长度 | |
FCS | 4 | 帧校验序列号 |
在这个ping包截图中,MTU值计算时包含了IP报头、ICMP报头及ICMP净荷载长度即20+8+1470=1498。按通常理解1498明显小于拨号接口下的MTU值1500,这时候不需要分片,该ICMP包应该是被正常发送出去的。但为什么不能ping通呢?那是在以太网链路上的情况。那么在通过PPPOE拨号上网时,MTU又包含哪些东西呢?所谓PPPoE就是在以太网上面跑PPP协议, PPP协议和Ethernet不都是链路层协议吗?怎么一个链路层跑到另外一个链路层上面去了,难道升级成网络层协议了不成。其实这是个误区:就是某层协议只能承载更上一层协议。PPPOE协议栈如下:
IP |
PPP |
PPPoE |
Ethernet |
为什么会产生这种奇怪的需求呢?这是因为随着宽带接入(这种宽带接入一般为Cable Modem或者xDSL或者以太网的接入)由于以太网缺乏认证计费机制而传统运营商是通过PPP协议来对拨号等接入服务进行认证计费的,所以就出现了PPPoE。
再看PPPOE的数据报文格式:
版本 | 类型 | 代码 | 会话ID |
长度 | 净载荷 |
pppoe是通过以太网传输的,其含有PPPOE协议头有6个字节和以太网帧类型2字节。这个8字节的PPPOE封装字段会在数据从拨号接口发送出去时被添加到数据报文中。因此,该数据报文从拨号接口出去时的真实长度是1498+8=1506大于物理以太网接口F0/1的MTU值1500,因此,该数据包将会被丢弃,从而出现在主机上用ping www.qq.com –l 1470不通的情况。PPPoE带来了好处,也带来了一些坏处,比如:二次封装耗费资源,降低了传输效能等等,最大的坏处就是PPPoE导致MTU变小了,以太网的MTU是1500,再减去PPP的包头包尾的开销(8Bytes),就变成1492。通过上面的分析,在PPPOE环境下,设置接口MTU时需要将8个字节的PPPOE封装字段考虑进去,MTU=1500-8=1492,这样,当IP报头(20)+ICMP报头(8)+ICMP净荷载长度+PPPOE头(8)<=物理接口1500(即ICMP净载荷<=1500-28=1472)时,该数据包不会因为数据包长度超过接口MTU值被丢弃,而且还可以在不需要分片的情况下最大限度的发送数据包,提高传输效率。
MTU分片
当以个数据包的长度比链路层上的MTU值还要大,那么IP层就需要对这个数据包进行分片处理,而且要求被分片的每个数据包都要小于这个MTU值。下面仍然通过实验抓包的方式来分析数据包是如何分片的。在PC上执行ping www.qq.com –l 1600,1600为ICMP净载荷数据长度。
跟数据包分片有关的几个字段:
Identifier(标示符):该字段长度为16,通常与标记字段和偏移字段一起用于数据包分片。
Fragmentation Flags(分片标记):长度为3,其中第1位没有使用,第2位是不分片(DF),当DF位被设置为1时,表示路由器不能对数据包进行分片处理(对于一些上层TCP应用程序,因为某些原因,要求不能对该应用的数据包进行分片,这时候就需要将DF为设置为1)。如果数据包因为不能分片而未能被转发,路由器则会丢弃该数据包,并向源点发送错误消息,这一功能可以用工作在网络上测试MTU值。
第3位表示还有更多的分片(MF)位,当路由器对数据包进行分片时,除了最后一个分片的MF位设置为0外,其他所有分段的MF位都设置为1,以便接受者直到收到MF位为0的分段为止。
数据包被分片后每个分片的大小是否一样,分片大小是随机还是有规律可循?数据包在被分片时,是依照最大净载荷字节长度尽力让每个分片包大小都达到MTU允许的上限值,这样可以提高数据传输的速率。比如,主机A向主机B发送了4个大小为3000的数据包,每一个数据包都被分片为3个分片包,第一个分片包大小与第二、三个分片包的大小是怎样的呢?根据PPPOE下最大MTU为1492的规定以及分片标记的工作原理,每个数据数据包的最大净载荷为1472字节,所以该大小为3000字节的大包会被分片为净载荷分别为1472字节、1472字节及48字节的数据包。因此主机A发往B的4个3000字节的大包被分片的情况是完全一样的。
Fragment Offset:(分段偏移):字段长度为13位,以8个8位组为单位,用于指明分段起始点相对于报头起始点的偏移量。由于分段到达时可能错序,所以分片偏移字段可以使将接收者按照正确的顺序重组数据包。
综上所述,当主机向目的服务器地址222.73.78.203发送一个长度为1600字节的ping包时,这个ping包被发送到主机网卡(主机网卡MTU值默认为1500),网卡将这个数据包分片成2个包,第一个包总长度为1500(1472+20+8)字节,第二个包总长度为148(128+20)字节。第一个分片包经由交换机转发(交换机接口MTU为1500,且不进行分片处理)给路由器,路由器的内网口F0/0也不做分片处理,这个长度为1500的分片包被转发路由器的虚拟接口时,再次被进行分片处理(因为该虚拟接口的MTU值为1492),被分片的数据包在出虚拟接口时被加上8个字节的PPPOE头,由于被分片后的数据包长度小于外网口F0/1的MTU值1500,因此从物理口F0/1转发出去。被分片的数据包不会在数据链路的另一端被重组,而是一直保持分片状态,直到到达最终目的地时才会根据分片标记字段中的标记被重组。
TCP-MSS是Maximum Segment Size 最大分段大小的缩写,意为TCP数据包每次能够传输的最大数据分段,是TCP协议里面的一个概念 ,default value is 536。
MSS值所表示的是TCP报文的净载荷数据大小。通过设置其大小可以达到与设置MTU值一样的效果,都是为了避免主机发送的数据包大小超过网络链路MTU值而造成数据包被丢弃的情况。但是在实际情况中,该MSS值在TCP协议中实现的时候往往被MTU所代替。其实现原理是:一些TCP实现只有当目的主机在一个非直接连接网络上才发送MSS选项,pc上网或者别的一些tcp连接,PC会与目的地的IP地址,协商一次mss参数,作为自己发送数据包的参考。mss参数就是告诉对端本端最大支持不分片的数据包大小,只含净荷。
MSS是TCP数据包每次能够传输的最大净载荷数据分段。TCP MSS 被定义为相关的IP数据报尺寸减去TCP报头(20)和IP报头(20)即为40,而最大IP数据报尺寸的默认值是576,这就导致TCP MSS的默认值是536字节。在以太网链路上允许传输的最大IP数据包长度即MTU为1500,这也就导致MSS的最大值为1500-20-20=1640,而在PPPOE拨号的环境下,还需要减去8个字节的PPPOE封装头,因此PPPOE下的拨号接口的MSS最大值为1500-20-20-8=1452。
TCP报文中MSS的位置就在选项的位置,选项中内容有很多种,MSS是其中的一种。MSS在TCP报文中是可选项不是必选项,换句话说MSS是可协商的,而且在协商过后该选项内容可以改变也可以没有,在协商MSS时一般是建立TCP连接的两端发送[Syn]标志报文时互相通报然后选取最小MSS作为双方的约定,如果双方都不通报或有一方不通报一般选择MSS的默认值536。在这里不禁要问,TCP不是属于应用层的吗,MSS是TCP的属性选项,为什么会由IP来处理呢?这是因为通常TCP层不可能有适当地信息来作出这种决定,所有它更愿意把决定因特网路径合适的MTU的工作留给IP层来完成。
在PC访问网站服务器时,会在TCP连接阶段协商MSS值和其他的一些参数。然后PC使用默认的1460字节MSS向网站服务器发送TCP连接请求。因此,在使用PPPOE方式上网时,PC与网站服务器之间通过协商好的1460字节发送数据包,这个数据包经过封装加上TCP头和IP头后,到达路由器虚拟接口时,路由器会检查其接口的MTU值,发现这个数据包大于其设定好的MTU值1492,就会将该数据包分片成2个数据包进行发送。但网站认为,我们之间已经协商好了MSS值,就只接受MSS定义好长度的报文,任何大于或小于该MSS长度的报文都是无效,我会将它丢弃,这就会造成有些应用或某些网站无法打开的情况。当在路由器上设置了ip nat mss 1452命令后,当PC按照1460字节的MSS向网站发送TCP连接请求时,路由器接收到该请求,发现1460的设置加上报文头后会超过了最大的1492的限制,就会将该MSS值减8,即为1452,然后将修改后的连接请求发送给需要转发的网站。这样该网站如果同意路由器转发的该连接请求,TCP连接就可以建立成功。这样以后PC访问该网站时,最大就只会发送1492字节的IP报文。
在文章的概述部分,已经对什么是TCP-MSS,其作用是什么做了描述,现在仍然用实验抓包的方式来对其分析。
在PC访问www.qq.com网站时,PC与服务器之间会建立TCP协商,PC与服务器之间会相互通报自己本端的MSS值,然后选取最小的MSS值作为双方的约定。这一点通过深入的分析一下TCP协商时的数据报文就能得出结论,我们对比以下PC1访问网站的第一个数据报文和网站返回的第一个数据报文的具体情况。