在由于该站点上其他问题而引发的讨论中,我意识到我对执行路径MTU发现(PMTUD)的时间并不了解。

我知道它的作用- -发现从客户端到服务器的路径上最低的MTU。
我知道它是如何做到的–将“ Do n't Fragment”位设置为逐渐发送更大的数据包,并查看可以发送多少数据包

我的问题是,主机何时才能执行PMTUD?

我正在寻找具体情况。不仅像“当主机要发现路径MTU时”这样的通用名称。如果您可以提供执行该操作的主机的数据包捕获,或者提供生成此数据包捕获的说明,则可以得到加分。

我还特别指的是IPv4。我知道在IPv6中,瞬态路由器不是造成碎片的原因,并且可以想象PMTUD发生得更为普遍。但是现在,我正在寻找IPv4中PMTUD的特定示例。 (尽管您可以将PMTUD放在一起的唯一数据包捕获是在IPv6中,但我还是很乐意看到它)

评论

PMTUD是从受支持的最低MTU到最高的MTU吗?还是执行PMTUD的设备先尝试最大的MTU,然后以较大的增量递减,直到数据包通过,然后以较小的增量递减,然后来回交替直到最终确定为止?
@cpt_fink,有一些策略。 ICMP碎片需要消息的现代实现在ICMP有效负载本身中包括需要碎片的链路的MTU。这很容易,因为启动主机会立即知道MTU的路径。较早的实现必须使用各种策略来“搜索”要使用的正确MTU。 RFC1191的第5部分中概述了这些策略。这些策略的范围从自动默认为IP Minimum(576),到使用“通用” MTU的表来更有效地搜索(请参阅RFC1191第7.1节)。

这是个有趣的问题。我在PMTUD上进行了一些挖掘,发现了这一点。即使它很旧,我还是决定回答,因为我有完全相同的问题,经过几个小时的研究,我可以得出一个相当不错的答案(我想)。如果可能的话,我将在明天尝试通过捕获数据包来更新和支持我的答案。

#1 楼

答案很简单:只要主人高兴即可。真。就是这么简单。

下面的说明假定仅使用IPv4,因为IPv6消除了路由器中的碎片(强制主机始终处理碎片和MTU发现)。 br />没有严格的规则可以控制主机何时(或什至)主机执行Path MTU Discovery。 PMTUD浮出水面的原因是,由于各种原因,碎片被认为是有害的。为了避免数据包碎片,PMTUD的概念作为一种变通方法而得以实现。当然,一个好的操作系统应该使用PMTUD来最大程度地减少碎片。因此,自然地,何时使用PMTUD的确切语义取决于发送方的操作系统,尤其是套接字实现。我只能说说Linux的特定情况,但是其他UNIX变体可能差别不大。

在Linux中,PMTUD由IP_MTU_DISCOVER套接字选项控制。通过指定级别getsockopt(2)IPPROTO_IP选项,可以使用IP_MTU_DISCOVER检索其当前状态。此选项仅对SOCK_STREAM套接字有效(SOCK_STREAM套接字是双向的,面向连接的可靠套接字;实际上,它是TCP套接字,尽管其他协议也是可能的),并且在设置后,Linux将完全按照定义执行PMTUD在RFC 1191中。

请注意,实际上,PMTUD是一个连续的过程。数据包是使用DF位置1发送的,包括3向握手数据包,您可以将其视为连接属性(尽管实现可能愿意在某一点接受一定程度的分段并停止使用DF发送数据包位设置)。因此,PMTUD只是该连接上的所有内容都通过DF发送的事实的结果。

如果不设置IP_MTU_DISCOVER怎么办?有一个默认值。默认情况下,在IP_MTU_DISCOVER套接字上启用了SOCK_STREAM。可以通过阅读/proc/sys/net/ipv4/ip_no_pmtu_disc来读取或更改。零值表示在新套接字中默认启用IP_MTU_DISCOVER;非零意味着相反。

无连接套接字呢?

这很棘手,因为无连接,不可靠的套接字不会重新传输丢失的段。将数据打包为MTU大小的块是用户的责任。同样,如果Message太大错误,则期望用户进行必要的重新传输。因此,基本上用户代码必须重新实现PMTUD。不过,如果您准备好迎接挑战,则可以通过将IP_PMTUDISC_DO标志传递给setsockopt(2)来强制DF位。

最重要的是何时(以及是否)使用PMTUD
当它使用PMTUD时,就像连接属性一样,它连续发生(但是在任何时候实现都可以停止这样做)
不同的操作系统使用不同的方法,但通常情况下,可靠的,面向连接的套接字默认情况下执行PMTUD,而不可靠的无连接套接字则不能执行


#2 楼

通常,每当主机认为数据包由于太大而被丢弃时,都会发生路径最大传输单位发现(PMTUD)。明确指示数据包已丢弃。在典型的实践中,所有IPv4数据包都设置有“不要分段”(DF)标志,因此,任何超出MTU的数据包都会引发这种响应。 IPv6根本不支持分段。

某些路由器或主机防火墙经常丢弃所有ICMP,因为天真的管理员认为ICMP存在安全风险。或者,某些链路聚合方案可能会中断ICMP传递。 RFC4821中提出了一种不依赖于ICMP的发现MTU的替代机制。这是来自局域网上具有9001 MTU的主机的示例,但该主机必须经过IPsec VPN才能到达10.33.32.157:

$ tracepath -n 10.33.32.157
 1?: [LOCALHOST]                                         pmtu 9001
 1:  10.1.22.1                                             0.122ms pmtu 1500
 1:  169.254.3.1                                           1.343ms pmtu 1422
 1:  10.255.254.61                                        23.790ms 
 2:  no reply
^C [this host won't return an ICMP port unreachable, so tracepath won't terminate]

使用tracepath

$ sudo tcpdump -p -ni eth0 'icmp and icmp[0] == 3 and icmp[1] == 4'
14:46:57.313690 IP 10.1.22.1 > 10.1.22.194: ICMP 10.33.32.157 unreachable - need to frag (mtu 1500), length 36
14:46:57.315080 IP 169.254.3.1 > 10.1.22.194: ICMP 10.33.32.157 unreachable - need to frag (mtu 1422), length 556


MTU发现被缓存。在Linux中,可以观察到并用tcpdump刷新(请注意Linux 3.6以来的更改):设定。每一端发送的SYN中都包含最大段大小(MSS)。 TCP标头(20字节,不包括选项)和IP标头(20字节)意味着MSS和MTU之间相差40字节。带有ip的大文件:

$ ip route get 10.33.32.157
10.33.32.157 via 10.1.22.1 dev eth0  src 10.1.22.194 
    cache  expires 591sec mtu 1422
$ sudo ip route flush cache
$ ip route get 10.33.32.157
10.33.32.157 via 10.1.22.1 dev eth0  src 10.1.22.194 
    cache


在第一个数据包中,本地主机建议的MSS为8961。这是配置的9001 MTU,减少40个字节。返回的SYN / ACK的MSS为1379,表示MTU为1419。我碰巧知道在该网络中,远程主机也发送了8961,但是该值已由路由器修改,因为它知道该路径包括Internet路径( MTU 1500)来自IPsec隧道的开销。该路由器还修改了我们发送的8961的MSS,使其在另一台主机上显示为1419。这称为MSS夹紧。

从某种意义上讲,PMTUD一直在发生。实际上,如果MSS钳制到位并且所有流量都通过TCP进行,或者没有一个路由器的MTU小于端点上配置的MTU,则可能永远不会发生。即使没有MSS限制,当缓存过期时,它也很少发生。

#3 楼

PMTUD用于计算TCP会话的最佳MSS。
一个示例是在Cisco或Juniper路由器上的BGP实现。

http://www.juniper.net/techpubs/zh_CN/junos12.1/topics/usage-guidelines/routing-configuring -mtu-discovery-for-bgp-sessions.html

谢谢。

评论


我相信他的意思是“何时触发?”。

–乔丹·海德
2014年12月4日20:22