IPv6重复地址检测期间的MLD消息

网络工程 ipv6 协议理论 多播 射频卡 icmpv6
2021-07-13 01:10:33

我想知道是否有人可以阐明在 IPv6 重复地址检测期间应该何时发送多播侦听器发现 (MLD) 消息。RFC4862 5.4.2节详细描述了执行DAD的IPv6主机应该加入哪些组播组,即全节点组播地址和请求节点组播地址。它还提到了 MLD 的使用,但是我似乎无法解释 Windows 和 Linux 的观察行为,我将在下面解释。

根据 RFC4863,我的理解是节点不应宣布其对全节点多播地址的兴趣(因为 MLD 侦听交换机无论如何都会处理全节点多播流量),但建议为被请求节点发送 MLD 消息多播地址(因为 MLD 侦听交换机不可能知道它应该侦听和转发的所有请求节点多播地址)。

到目前为止一切顺利,但是当我查看 Windows、Linux 和 FreeBSD 如何在 DAD 期间实现 MLD 消息发送时,我不明白为什么请求节点多播地址的 MLD 消息被发送两次。下面是三个跟踪显示分别在启动 Linux、Windows 和 FreeBSD 机器的以太网接口时链路本地地址的 DAD。

一些看似奇怪的行为:

  1. Linux、Windows 和 FreeBSD 都发送了两次 MLD 消息。Linux 和 Windows 将它们间隔大约 300 毫秒,在 FreeBSD 中这是大约 2200 毫秒。为什么发送第二条消息,看看它是如何精确复制第一条消息的?这是某种形式的重传吗?
  2. Linux 将邻居请求消息 (SOL) 延迟到第二个 MLD 消息之后,而 windows 和 freebsd 立即发送 SOL 消息。
  3. Windows 和 freebsd 在邻居请求消息之后发送 MLD 消息。授予它在 SOL 消息之后立即发送第一个 MLD 消息。此外,当windows发送SOL消息时,它很可能已经加入了多播组;只有公告本身被延迟,而不是实际加入该组。尽管如此,首先发送 MLD 消息难道不会减少错过来自 MLD 侦听交换机后面的主机的邻居广告的机会吗?
  4. (请注意,windows 实际上主动通告它已在消息 #4 中分配了 fe80::c14b:8228:ee4:d4aa,但这与 MLD 无关)

到目前为止,我得出的初步结论是,没有关于 MLD 消息计时的标准化做法。有一些指导方针限制发送 MLD 消息以防止拥塞,例如在 RFC 4862 中。任何人都可以参考有关何时在 IPv6 DAD 期间发送 MLD 消息的更多材料,从而解释上述跟踪中的观察结果吗?我假设每个操作系统都在 DAD 期间选择何时发送 MLD 消息,而 Linux 和 Windows/FreeBSD 做出了不同的选择,但是为什么所有三个操作系统都选择为请求节点多播地址发送两次 MLD 消息(间隔 300/300 /2200 毫秒)?

请注意,我知道在大多数情况下 DAD 不需要 MLD 消息传递,并且 DAD 在阻止 MLD 消息时通常可以正常工作(除非某处有 MLD 侦听开关)。然而,我们的一些学生对 MLD 消息传递的不稳定行为感到困惑,我无法向他们解释观察到的行为。

1个回答

回答您的问题的关键是做出一个非常重要的区分:重复地址检测 (DAD) 和多播侦听器发现 (MLD) 是完全独立的协议。

现在,也就是说,我认为RFC2710 的这一段解释了“重复”传输:

当节点开始侦听接口上的多播地址时,它应该立即在该接口上传输该地址的主动报告,以防它是链路上的第一个侦听器。为了覆盖初始报告丢失或损坏的可能性,建议在短暂延迟后重复一次或两次[主动报告间隔]。(完成此操作的一种简单方法是发送初始报告,然后就好像收到了针对该地址的多播地址特定查询一样,并适当设置了计时器)。

RFC3810取代了 RFC2710,但仍同意上述内容。(感谢@logion 指出这一点!)我将引用 RFC2710 的内容留在原处,因为我认为它有助于在没有额外上下文的情况下更容易理解。特别是,RFC 3810 中确认行为的部分在这里:

为了覆盖一个或多个多播路由器丢失状态更改报告的可能性,[稳健性变量] - 通过重传计时器安排 1 次重传,间隔从范围中随机选择(0,[非请求报告间隔]) .

这让我们不得不讨论 DAD,特别是为什么 DAD 完全独立于 MLD。

在 IPv6 节点打算使用 IP 地址之前,它必须首先检查该地址是否在使用中。该检查是通过向目标 IP 地址的请求节点组播 (SNM) 地址发送邻居请求 (NS) 消息来完成的。SNM 是一个多播地址,拥有目标 IP 地址的任何人都会监听该地址。

Neighbor Solicitation 数据包的目标 IP 是FF02::1:FFyy:yyyy(其中yy:yyyy是目标 IPv6 地址的最后 24 位)。源 IP 是::“未指定的”IPv6 地址。它必须使用未指定地址,以防止使用目标地址本身,因为它可能会触发重复。此时,初始主机不知道地址是否唯一。

如果网络上的另一台主机已经拥有目标 IPv6 地址,它们将收到上述邻居请求消息,并通过发送指示 IP 已在使用中的邻居广告 (NA) 来响应。

这里是关键:由于初始 NS 是从未指定的地址 ( ::)发送的,拥有目标 IPv6 地址的其他主机将无法知道将响应的 NA 发送给谁。因此,它必须将结果发送到FF02::1“所有节点”多播地址。

如果您阻止所有 MLD 消息,这就是 DAD 仍然可以执行的方式。因为加入 All Nodes 多播组不需要 MLD 事务,所以所有理解 IPv6 的交换机都会自动将“All Nodes”目的地帧转发到相应 VLAN 中的所有端口。DAD,不需要侦听特定的多播组来接收已在使用的地址的通知。

如果没有人声明 IPv6 地址,则 DAD 会确定 IPv6 地址是唯一的,并允许发起主机开始使用该地址本身。这就是提示加入目标地址的相关 SNM 组的原因,其中一些 MLD 消息发送到 的 MLD 多播地址FF02::16(并且根据上面的 RFC,此消息打算发送两次)。

Windows 捕获似乎在发送声称网络上的 IP 的邻居广告之前使用源 IP,这在 DAD 结束时发生。我不禁觉得这有点过头了,因为 NA 标志着 DAD 过程的结束,并且确认地址在网络上确实是唯一的。

linux捕获在DAD NS之前发送了MLD消息,但是这些是从未指定的地址发送的,因此不会导致IP冲突。如果网络上的任何 MLD 嗅探开关只需要将 MAC 地址与加入的 MLD 组相关联,那么这将工作得很好(免责声明:我对 MLD 嗅探的复杂性并不十分熟悉,并且不能声称这是否正是怎么运行的)

BSD 捕获不包括 NA,但两个 MLD 消息在 DAD NS 发出后 0.15 秒发生。对我来说,这似乎有点太短了,因为在考虑唯一地址之前,DAD 过程需要等待不到一秒钟的时间(根据我所做的捕获和测试)。