10. 特定分包层
所有分包层 (Packetization Layer) 协议都必须考虑第 6 节讨论的所有问题. 对许多协议而言, 处理这些问题是直接明了的. 本节讨论在若干协议中实现 PLPMTUD 的具体细节. 希望这里的描述足以作为示例, 使实现者能够将其适配到更多协议.
10.1. 使用 TCP 的探测方法
TCP 没有机制区分带内数据和填充. 因此, TCP 必须通过适当地分段数据来生成探测分组. 分段有两种方法: 重叠和非重叠.
非重叠方法
在非重叠方法中, 数据被分段为探测分组和任何后续段都不包含重叠数据. 如果探测分组丢失, "探测空洞" 将等于完整探测大小减去头部. 探测空洞中的数据需要用多个较小的段重新传输.
TCP sequence number
t <---->
i <--------> (probe)
m <---->
e
.
. (probe lost)
.
<----> (probe gap retransmitted)
<-->
重叠方法
另一种方法是发送与探测分组重叠的后续数据, 使探测空洞的长度等于当前 MSS. 在探测成功的情况下, 这种方法会产生额外开销, 因为它会把部分数据发送两次, 但在探测分组丢失后只需重传一个段. 当探测成功时, 由于发送了重复数据, 可能会产生一些重复确认. 重要的是, 这些重复确认不能触发快速重传 (Fast Retransmit). 因此, 使用这种方法的实现 应该 将探测大小限制为当前 MSS 的三倍 (最多导致 2 个重复确认), 或者对成功探测之后紧随的数据适当调整其重复确认阈值.
TCP sequence number
t <---->
i <--------> (probe)
m <---->
e <---->
.
. (probe lost)
.
<----> (probe gap retransmitted)
应根据给定 TCP 实现中哪种方法最简单,最高效来选择使用哪种分段方法.
10.2. 使用 SCTP 的探测方法
在流控制传输协议 (Stream Control Transmission Protocol, SCTP) [RFC2960] 中, 应用将消息写入 SCTP, SCTP 将数据划分为适合通过网络传输的较小 "块" (chunk). 每个块都会被分配一个传输序列号 (Transmission Sequence Number, TSN). 一旦某个 TSN 已经被传输, SCTP 就不能改变该块的大小. SCTP 多路径支持通常要求 SCTP 选择一种块大小, 使其消息适配所有路径中最小的 PMTU. 虽然并非必需, 实现可以将多个数据块捆绑在一起, 形成更大的 IP 分组, 用于在具有较大 PMTU 的路径上发送. 注意, SCTP 必须独立探测到对端的每条路径上的 PMTU.
生成探测分组的 推荐 方法是在 SCTP 消息中添加一个仅由填充组成的块. [RFC4820] 中定义的 PAD 块 应该 附加到一个最小长度的 HEARTBEAT (HB) 块上, 以构造探测分组. 这种方法与所有当前 SCTP 实现完全兼容.
SCTP 可以 也使用类似上文 TCP 所述的方法进行探测, 即使用内联数据. 这种方法的优点是成功的探测没有额外开销; 但是, 失败的探测将需要重传数据, 这可能影响流性能.
10.3. 用于 IP 分片的探测方法
有一些协议和应用通常发送大型数据报, 并依赖 IP 分片来传递它们. 长期以来人们已经知道, 这样做会带来一些不良后果 [Kent87]. 最近又逐渐清楚的是, 对当今 Internet 中的一般用途而言, IPv4 分片并不够健壮. 16 bit 的 IP 标识字段不够大, 无法防止频繁发生 IP 分片错误关联, 而 TCP 和 UDP 校验和也不足以防止由此产生的受损数据被传递到更高协议层 [frag-errors].
如第 8 节所述, 数据报协议 (例如 UDP) 可能依赖 IP 分片作为分包层. 但是, 使用 IP 分片来实现 PLPMTUD 存在问题, 因为在没有应用直接参与的情况下, IP 层没有机制确定这些分组最终是否被传递到远端节点.
为了在未修改的应用之下支持 IP 分片作为分包层, 实现 应该 依赖第 5.2 节描述的路径 MTU 共享, 再加上一个用于探测路径 MTU 的辅助协议. 有许多协议可用于此目的, 例如 ICMP ECHO 和 ECHO REPLY, 或者触发 ICMP 消息的 "traceroute" 风格 UDP 数据报. 使用 ICMP ECHO 和 ECHO REPLY 会同时探测正向路径和返回路径, 因此发送方只能利用两者中的较小值. 如果可用, 优先使用只探测正向路径的其它方法.
所有这些方法都有若干潜在的健壮性问题. 最可能发生的故障是与 MTU 无关的丢失 (例如, 节点丢弃某些协议类型). 这些与 MTU 无关的丢失会阻止 PLPMTUD 提高 MTU, 迫使 IP 分片使用小于必要值的 MTU. 由于这些故障不太可能导致互操作性问题, 它们相对温和.
不过, 还存在其它更严重的故障模式, 例如中间盒或上层路由器为不同协议类型或会话选择不同路径所导致的情况. 在这样的环境中, 辅助协议完全可能经历与主协议不同的路径 MTU. 如果辅助协议发现的 MTU 大于主协议的 MTU, PLPMTUD 可能会选择一个主协议不可用的 MTU. 虽然这是一个潜在的严重问题, 但这类情况很可能被大量观察者视为不正确, 因此会有强烈动机去修正它.
由于无连接协议可能不会保留足够的状态来有效诊断 MTU 黑洞, 在探测路径以测量 MTU 之前, 偏向使用过小的初始 MTU (例如 1 kByte 或更小) 会更健壮. 因此, 使用 IP 分片的实现 应该 使用按照第 7.2 节所述选择的初始 eff_pmtu, 但对无连接协议的默认初始 eff_mtu 使用单独的全局控制.
无连接协议还给路径信息缓存维护带来一个额外问题: 没有与连接建立和拆除相对应的事件可用于管理缓存本身. 一种自然的方法是为 "默认路径" 保留一个不可变缓存条目, 其 eff_pmtu 固定为无连接协议的初始值. 一旦发往某个特定目的地的分片数据报数量达到某个可配置阈值 (例如 5 个数据报), 就调用辅助路径 MTU 发现协议. 当辅助协议更新 eff_pmtu 时, 创建新的路径缓存条目, 并基于定时器或最近最少使用 (Least Recently Used) 缓存替换算法删除该条目.
10.4. 使用应用的探测方法
依赖 IP 分片和辅助协议来执行路径 MTU 发现的缺点, 可以通过在应用自身内部使用应用自己的协议实现路径 MTU 发现来克服. 应用必须具备某种合适的方法来生成探测分组, 并具备一种准确且及时的机制来判断探测分组是否丢失.
理想情况下, 应用协议包含一个用于确认消息交付的轻量级回显功能, 以及一种将消息填充到所需探测大小的机制, 且这些填充不会被回显. 这种组合 (类似于 SCTP HB 加 PAD) 是 推荐 的, 因为应用可以在具有非对称 MTU 的路径上分别测量每个方向的 MTU.
对于无法用 "echo plus pad" 实现 PLPMTUD 的协议, 通常也有其它生成探测分组的方法. 例如, 协议可能具有可变长度回显, 从而有效测量正向路径和返回路径的最小 MTU; 或者可能有办法向承载真实应用数据的常规消息添加填充. 也可能存在其它分段应用数据以生成探测分组的方法; 或者作为最后手段, 可以扩展协议, 加入专门用于支持 MTU 发现的新消息类型.
注意, 如果有必要添加新消息类型来支持 PLPMTUD, 最通用的方法是添加 ECHO 和 PAD 消息, 这使得特定于应用的 PLPMTUD 实现在与同一端系统上的其它应用和协议交互时具有最大可能的灵活性.
所有应用探测技术都要求具备发送大于第 9 节所述当前 eff_pmtu 的消息的能力.