最大传输长度
扫描二维码
随时随地手机看文章
TCP提供的是一种面向连接的,可靠的字节流服务,TCP提供可靠性的一种重要的方式就是MSS。通过MSS,应用数据被分割成TCP认为最适合发送的数据块,由TCP传递给IP的信息单位称为报文段或段(segment)。代表一个TCP socket的结构体struct tcp_sock中有多个成员用于确定应用数据被分割成最大为多大的数据块较为合适(最大报文段长度MSS)。
我们不难联想到,跟最大报文段长度最为相关的一个参数是网络设备接口的MTU,以太网的MTU是1500,基本IP首部长度为20,TCP首部是20,所以MSS的值可达1460(MSS不包括协议首部,只包含应用数据)。
前面的TCP三次握手协议中我们看到,通讯的双方都通过TCP选项通告了自己期望接收的MSS值,该值直接来源于struct tcp_sock的成员advmss,而这个值直接取自于网络设备接口的MTU减去IP首部和TCP首部的长度。在本地以太网中可达1460(如果首部都不含选项的话)。而成员rx_opt是一个结构体struct tcp_options_received,它记录的是来自对端的TCP选项通告,其成员mss_clamp表示mss的上限值,其来源就是对端的MSS通告,而mss_user是用户设置的mss,其优先级最高,如果有user_mss,则使用user_mss,忽略其它。
从上面我们可以看到,MSS是可以通过SYN段进行协商的(MSS选项只能出现在SYN报文段中),但它并不是任何条件下都可以协商的,如果一方不接受来自另一方的MSS值,并且没有user_mss,则MSS就定为默认值536字节(加上首部,允许576字节的IP数据报)。实际上,struct tcp_sock->rx_opt->mss_clamp的初始值就定为536,等收到来自对端的MSS通告后,才进行修改。而结构体struct
tcp_sock的成员mss_cache用于缓存上次的有效的mss,其初始值也被定为536。
函数mytcp_sync_mss为一个tcp socket中的mss相关的成员进行数据同步,其基本的一个算法是:
1、当前的MSS正常情况下应该为mtu-IP首部-TCP首部(不包括选项)。
2、struct tcp_sock->rx_opt->mss_clamp中含有对端通告的能够接受的MSS值,如果该值小于第一步计算所得到的MSS,则以该值为准。
3、IP首部如果带有IP选项,则MSS中要减去选项长度。
4、如果MSS已经小于48了,则令其等于48。
5、减去TCP首部中选项的长度。
6、如果MSS当前已经大于滑动窗口大小的1/2,则取滑动窗口大小的1/2作为MSS值(但不能小于48)。
7、成员mss_cache用于缓存下刚刚计算所得的MSS。
所以,说本地以太网中MSS为1460的说法并不正确,它还会动态变化,如果IP首部和TCP首部中出现选项,则MSS要相应的减小,一般TCP首部中会有12字节的时间戳选项(外加两字节的填充选项),这时的MSS就等于1448。
MSS的主要作用是限制另一端主机发送的数据的长度,同时,主机本身也控制自己发送数据报的长度,这将使以较小MTU连接到一个网络上的主机避免分段。
struct tcp_sock有一个成员xmit_size_goal,用于记录该socket发送数据报时的segment的大小,一般情况下它的值就等于MSS(特殊情况有例外,以后再分析)。
最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)。最大传输单元这个参数通常与通信接口有关(网络接口卡、串口等)。
因特网协议允许IP分片,这样就可以将数据报分成足够小的片段以通过那些最大传输单元小于该数据报原始大小的链路了。这一分片过程发生在 IP 层(OSI模型的第三层,即网络层),它使用的是将分组发送到链路上的网络接口的最大传输单元的值。原始分组的分片都被加上了标记,这样目的主机的 IP 层就能将分组重组成原始的数据报了。
在因特网协议中,一条因特网传输路径的“路径最大传输单元”被定义为从源地址到目的地址所经过“路径”上的所有IP跳的最大传输单元的最小值。或者从另外一个角度来看,就是无需进一步分片就能穿过这条“路径”的最大传输单元的最大值。
RFC 1191 描述了“路径最大传输单元发现方法”,这是一种确定两个 IP 主机之间路径最大传输单元的技术,其目的是为了避免 IP 分片。在这项技术中,源地址将设置数据报的 DF(Don't Fragment,不要分片)标记位,再逐渐增大发送的数据报的大小——路径上任何需要将分组进行分片的设备都会将这种数据报丢弃并返回一个“数据报过大”的 ICMP 响应到源地址——这样,源主机就“获取”到了不用进行分片就能通过这条路径的最大的最大传输单元了。
不幸的是,越来越多的网络封杀了 ICMP 的传输(譬如说为了防范 DoS 攻击)——这使得路径最大传输单元发现方法不能正常工作,其常见表现就是一个连接在低数据流量的情况下可以正常工作,但一旦有大量数据同时发送,就会立即挂起(例如在使用 IRC 的时候,客户会发现在发送了一个禁止 IP 欺骗的 ping 之后就得不到任何响应了,这是因为该连接被大量的欢迎消息堵塞了)。而且,在一个使用因特网协议的网络中,从源地址到目的地址的“路径”常常会为了响应各种各样的事件(负载均衡、拥塞、断电等等)而被动态地修改——这可能导致路径最大传输单元在传输过程中发生改变——有时甚至是反复的改变。其结果是,在主机寻找新的可以安全工作的最大传输单元的同时,更多的分组被丢失掉了。
对于时下大多数使用以太网的局域网来说,最大传输单元的值是 1,500 字节。但是像 PPPoE 这样的系统会减小这个数值,通常是1492(= 1500 - 2(PPP)- 6(PPPoE)),这就使得在使用最大传输单元发现方法时可能会产生这样的结果:一些处于配置不当的防火墙之后的站点变得不可达了。对于这种情况,还是可能找到变通的方法的,但这取决于你控制的是网络的哪一部分。这些方法包括改变用来在防火墙一端建立 TCP 连接的第一个分组的 MSS(Maximum Segment Size,最大分段大小)。
对于一些支持老版本以太网协议的 IBM 系统(例如 XSeries),可能只有在把最大传输单元设为 1492 之后才能在当下常见的局域网上进行运作。
[编辑]普通媒体的MTU表
这里的MTU所指的是无需分段的情况下,可以传输的最大IP报文(包含IP头部,但不包含协议栈更下层的头部)。
超通道
65535
16Mb/s令牌环
17914
4Mb/s令牌环
4464
FDDI
4352
以太网
1500
IEEE 802.3/802.2
1492
X.25
576
点对点(低时延)
296
网络 | MTU |
---|