IP分片的影响有多严重?

3

我知道在发送ip报文时,网络路径上的每个跳跃都会检查下一个跳跃的MTU是否大于我发送的数据包的大小。如果是,则数据包将被分段,并且两个分段的数据包将分别发送到下一个跳跃处,然后在目标地址(或者在某些情况下,在遇到的第一个NAT路由器处)重新组装。

据我所知,这种情况可能相当糟糕,但我真的不明白为什么。

  • 我知道如果连接经常丢失数据包,那么丢失单个分段就意味着我必须重新发送整个数据包(这实际上是我自己想出来的唯一一件事)
  • 是否有可能我的数据包不会被分段,而是被丢弃?
  • 如何识别分段的数据包?我能否100%确定它们将被正确地重新组装?例如,如果我同时向同一目的地发送两个几乎长度相同的ip数据包,那么这两个数据包的分段交换的可能性有多大,比如AAA,BBB会重新组装成ABA,BAB吗?

原则上,如果数据包没有丢失并且分段正确地重新组装,实际上使用分段似乎是节省本地带宽以避免发送更多标题而不是只发送一个大数据包的好方法。

谢谢

2个回答

8

IP分片可能会导致几个问题:

1) 应用层丢包率增加

正如您所提到的,如果单个分片丢失,则整个第4层数据包将丢失。因此,在一个随机丢包率较小的网络中,每个第4层数据包的应用层丢包率将增加约等于分片数的因子。

2) 不是所有网络都处理分片的数据包

一些系统,例如Google的计算引擎,不会重新组装分片的数据包。

3) 分片可能会导致重新排序

当路由器将流量拆分到并行路径时,它们可能会尝试将同一流量的数据包保持在单个路径上。由于只有第一个分片具有UDP/TCP端口号等第4层信息,后续分片可能会被路由到不同的路径,延迟第4层数据包的组装并导致重新排序。

4) 分片可能会导致令人困惑且难以调试的行为

例如,如果您从一个源发送两个UDP流A和B到运行Linux的目标,则目标可能会丢弃其中一个流的数据包。这是因为默认情况下,如果从同一源接收到超过64个其他片段,则Linux会“超时”片段队列。如果流A的数据速率比流B高得多,则在流B的片段之间可能会收到来自流A的64个片段,导致B片段被丢弃。
因此,虽然IP分片可以通过最小化用户头减少开销,但它可能会带来更多麻烦。

1
那个链接并没有说Google Compute Engine不会重新组装分段数据包,只是它的MTU是1460,而不是通常假定的更高数字(1500或1492)。是否有其他关于这方面信息的参考资料? - TBBle
1
你说得对,我的链接没有显示出来。我在2015年初使用GCE时发现了这一点。看起来它已经被报告并部分修复了。 https://code.google.com/p/google-compute-engine/issues/detail?id=87#c22 - Hugh White
我更新了我的链接。这里有更多关于分片的讨论:https://news.ycombinator.com/item?id=10578122 - Hugh White

5
据我所知,除非数据包本来就会被丢弃,否则唯一不会被分割而是被丢弃的情况是标记为“不分段”的数据包。 这些数据包应该被丢弃而不是被分段。
分段的数据包在其标头中具有标识符、片段偏移和更多片段字段,当组合在一起时,可以使目标主机在接收到所有片段后可靠地重新组装数据包。 第一个片段的偏移量为零,而最后一个片段将“更多片段”标志设置为零。 如果两个数据包的标头发生变异,它们的片段偏移量交换但仍然有效,则仍然有可能(尽管极少)重新组合出一个不正确的数据包。发生这种情况的概率基本为零。请注意,IP不提供任何机制来确保数据负载的完整性,只提供了头部中控制信息的完整性。
数据包分段必然会浪费带宽,因为每个片段都有[大部分]原始数据报的标头的副本。 数据包可以分成只有8个字节的片段,因此我们可以将最大大小的数据包分成60 * 8192 + 65536字节的60 + 65536字节,导致最坏情况下负载增加约750%。 我唯一能想到的一个例子是,如果通过某种频分复用方案并使用其他空闲信道,将数据包分段以并行发送其片段,则会受益。但此时,检测到这种情况并将数据包分割需要比直接发送更多的工作。
有关IP数据包分段机制的所有基本细节都可以在 IETF RFC 791 中找到,如果你想了解更多信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接