Skip to main content

7. Address Resolution and Neighbor Unreachability Detection (地址解析和邻居不可达检测)

本节描述地址解析和邻居不可达检测。地址解析 (Address resolution) 是节点在仅给定其IP地址的情况下确定邻居的链路层地址的过程。邻居不可达检测 (Neighbor Unreachability Detection, NUD) 是跟踪到邻居的路径的可达性状态的过程。

7.1. Address Resolution (地址解析)

地址解析仅对确定为链路内的地址执行。它永远不会对组播地址执行。

当节点有IPv6数据包要发送时,它首先检查目的地缓存以确定目的地的下一跳地址。如果目的地缓存不包含目的地的条目,节点使用下一跳确定算法(参见第5.2节)来确定下一跳地址。

一旦知道下一跳IP地址,发送者检查邻居缓存以获取有关下一跳的链路层信息。如果不存在条目,发送者创建一个条目,将其状态设置为INCOMPLETE,启动地址解析,并将数据包排队等待地址解析完成。

对于组播数据包,下一跳始终是(组播)目的地址,并且被认为是链路内的。确定与组播IP地址对应的链路层地址的过程在涵盖在特定链路类型上运行IP的单独文档中描述(例如,[IPv6-ETHER])。

对于单播数据包,地址解析执行如下。发送者为下一跳地址创建邻居缓存条目(如果尚不存在),将其状态设置为INCOMPLETE,并通过向与目标地址对应的请求节点组播地址发送邻居请求消息来启动地址解析。请求从发送请求的接口分配的地址发送。

邻居请求的目标地址设置为下一跳地址。如果发送者在发送邻居请求的接口上分配了地址,则应该 (SHOULD) 包含源链路层地址选项。如果发送者在发送请求的接口上没有分配地址(例如,在初始化期间),发送者绝对不能 (MUST NOT) 包含源链路层地址选项。

在等待地址解析完成时,发送者必须 (MUST) 为每个邻居保留一个等待地址解析完成的数据包小队列。队列必须 (MUST) 至少保存一个数据包,并且可以 (MAY) 包含更多。但是,每个邻居的排队数据包数量应该 (SHOULD) 限制为某个小数字。一旦地址解析完成,节点传输任何排队的数据包。

在等待地址解析完成时,发送者继续发送邻居请求。用于地址解析的邻居请求每RetransTimer毫秒发送一次,直到接收到邻居通告或直到已发送最大数量的邻居请求 (MAX_MULTICAST_SOLICIT)。如果在MAX_MULTICAST_SOLICIT个请求后没有接收到邻居通告,则地址解析失败。发送者必须 (MUST) 释放数据包的任何缓存副本,并且应该 (SHOULD) 为等待地址解析的每个排队数据包返回代码为3(地址不可达)的ICMP目的地不可达指示。

7.2. Neighbor Unreachability Detection (邻居不可达检测)

7.2.1. Reachability Confirmation (可达性确认)

如果节点最近收到确认最近发送到邻居的数据包被其IP层接收的确认,则认为邻居是可达的。积极确认可以通过两种方式收集:来自上层协议的提示,表明连接正在"向前进展 (forward progress)",或者接收到作为对邻居请求消息的响应的邻居通告消息。

如果从远程对等方接收到的数据包只有在最近发送到该对等方的数据包实际到达它时才能到达,则连接正在"向前进展"。例如,在TCP中,接收到(新的)确认表示先前发送的数据到达了对等方。同样,新(非重复)数据的到达表示较早的确认正在到达远程对等方。如果数据包正在到达对等方,它们也必须到达对等方的IP层,这是邻居不可达检测的要求。

对于链路外目的地,向前进展意味着第一跳路由器是可达的。当存在这样的确认时,实现可以 (MAY) 更新第一跳路由器的邻居缓存条目并将其可达性状态设置为REACHABLE。如果实现不跟踪向前进展,当继续从远程对等方接收数据包时,它应该 (SHOULD) 假设正在取得向前进展。

邻居不可达检测与正在发送数据包的应用程序并行运行。向邻居发送数据包不确认其可达性;接收相应的确认才确认。实现绝对不能 (MUST NOT) 仅因为邻居正在被主动使用就得出它是可达的结论。

当节点需要对相邻地址执行地址解析但已经有该地址处于STALE状态的邻居缓存条目时,节点将状态更新为DELAY而不是INCOMPLETE,并发送邻居请求以确认可达性。然后节点等待DELAY_FIRST_PROBE_TIME秒。如果在该时间内没有收到可达性确认,则条目的状态更改为PROBE,并开始邻居不可达检测。

7.2.2. Neighbor Cache Entry States (邻居缓存条目状态)

正在向其发送流量的邻居的邻居缓存条目可以处于五种可能状态之一:

INCOMPLETE (不完整) - 当前正在对条目执行地址解析。具体来说,邻居请求已发送到目标的请求节点组播地址,但尚未接收到相应的邻居通告。

REACHABLE (可达) - 在最后ReachableTime毫秒内收到积极确认,表明到邻居的前向路径正常运行。在REACHABLE时,当发送数据包时不执行特殊操作。

STALE (陈旧) - 自收到前向路径正常运行的最后积极确认以来,已经过去了ReachableTime毫秒以上。在陈旧时,在发送数据包之前不执行任何操作。

STALE状态是在接收到更新缓存的链路层地址的未请求邻居发现消息时进入的。接收这样的消息不确认可达性,进入STALE状态确保快速检测到路径故障。但是,在使用条目之前不会实际验证可达性。

DELAY (延迟) - 自收到前向路径正常运行的最后积极确认以来,已经过去了ReachableTime毫秒以上,并且在最后DELAY_FIRST_PROBE_TIME秒内发送了数据包。如果在进入DELAY状态的DELAY_FIRST_PROBE_TIME秒内没有收到可达性确认,则发送单播邻居请求并将状态更改为PROBE。

DELAY状态是一种优化,它为上层协议提供额外的时间来提供可达性确认,在由于缺乏最近流量而自最后一次确认以来已经过了ReachableTime毫秒的情况下。如果没有这种优化,在流量间歇后打开TCP连接将启动探测,即使随后的三次握手几乎立即提供可达性确认。

PROBE (探测) - 通过每RetransTimer毫秒重传单播邻居请求来主动寻求可达性确认,直到接收到可达性确认或直到已发送最大数量的探测 (MAX_UNICAST_SOLICIT)。如果在发送MAX_UNICAST_SOLICIT个请求后没有接收到响应,则停止重传,应该 (SHOULD) 删除该条目。到该邻居的后续流量将重新创建条目并再次执行地址解析。

请注意,所有邻居请求都是基于每个邻居的速率限制。节点绝对不能 (MUST NOT) 向同一目标发送邻居请求的频率超过每RetransTimer毫秒一次。

7.2.3. Node Behavior (节点行为)

邻居不可达检测算法根据条目是否用于转发数据包而有不同的操作。

当接收到可达性确认(通过上层建议或请求的邻居通告)时,条目的状态更改为REACHABLE。一个例外是上层建议对INCOMPLETE状态的条目没有影响(例如,尚未缓存链路层地址)。

当节点向其条目为STALE的邻居发送数据包时,节点将条目的状态更新为DELAY并设置计时器在DELAY_FIRST_PROBE_TIME秒后过期。如果计时器过期时条目仍处于DELAY状态,则条目的状态更改为PROBE,并发送单播邻居请求。邻居请求使用缓存的链路层地址发送。后续请求(如果有)使用相同的缓存链路层地址发送。邻居请求每RetransTimer毫秒重传一次,直到接收到可达性确认或直到已发送MAX_UNICAST_SOLICIT个请求。

如果响应单播邻居请求接收到邻居通告,并且邻居通告的请求标志被设置,则条目的状态更改为REACHABLE。如果未设置请求标志,则条目保持在PROBE状态。

如果在PROBE状态下接收到可达性确认,则条目的状态更改为REACHABLE。如果已发送最大数量的探测而没有接收到可达性确认,则应该 (SHOULD) 删除该条目,到该邻居的未来流量将需要再次执行地址解析。实现可以 (MAY) 随时垃圾收集陈旧条目。但是,INCOMPLETE状态的条目不应该 (SHOULD NOT) 被删除,直到地址解析失败(即,已发送MAX_MULTICAST_SOLICIT个邻居请求且没有接收到响应)。

7.3. Neighbor Unreachability Detection Protocol (邻居不可达检测协议)

本节提供邻居不可达检测算法如何运行的概述。

7.3.1. Reachability Confirmation Events (可达性确认事件)

以下事件导致缓存的链路层地址被重新确认为REACHABLE:

  1. 对于除INCOMPLETE外的任何状态的条目,接收到请求的邻居通告。

  2. 对于除INCOMPLETE外的任何状态的条目,接收到上层可达性确认(例如,积极的TCP确认)。

  3. 对于处于STALE、DELAY或PROBE状态的条目,发送邻居请求并接收到请求的邻居通告。

7.3.2. State Transitions (状态转换)

状态转换发生如下:

INCOMPLETE -> REACHABLE: 当接收到包含目标链路层地址选项的有效邻居通告时。

INCOMPLETE -> (deleted): 当地址解析失败(即,发送了MAX_MULTICAST_SOLICIT个邻居请求但没有响应)时。

REACHABLE -> STALE: 当ReachableTime毫秒过去而没有接收到可达性确认时。

STALE -> DELAY: 当向处于STALE状态的邻居发送数据包时。

STALE -> REACHABLE: 当接收到可达性确认时。

DELAY -> PROBE: 当DELAY_FIRST_PROBE_TIME秒过去而没有接收到可达性确认时。

DELAY -> REACHABLE: 当接收到可达性确认时。

PROBE -> REACHABLE: 当接收到可达性确认时。

PROBE -> (deleted): 当发送MAX_UNICAST_SOLICIT个探测而没有接收到可达性确认时。

7.3.3. Sending Neighbor Solicitations (发送邻居请求)

为邻居不可达检测目的发送邻居请求消息时,适用以下规则:

  • 邻居请求的目标地址必须 (MUST) 设置为正在确认其可达性的邻居的IP地址。

  • 邻居请求必须 (MUST) 使用缓存的链路层地址作为单播数据包发送。

  • 邻居请求的源地址必须 (MUST) 是分配给发送邻居请求的接口的地址。

  • 邻居请求应该 (SHOULD) 包含源链路层地址选项。

7.3.4. Receiving Neighbor Solicitations (接收邻居请求)

当接收到邻居请求时,接收者检查它是否是请求的目标。如果是,接收者应该 (SHOULD) 为发送者创建或更新邻居缓存条目。如果发送者已存在邻居缓存条目,接收者更新条目的链路层地址(如果不同)并按如下方式设置条目的状态:

  • 如果条目处于任何状态并且接收到的邻居通告中的覆盖标志被设置,则更新条目的链路层地址。

  • 如果条目处于INCOMPLETE状态,则将条目的链路层地址设置为源链路层地址选项中的值(如果存在),并将状态设置为STALE。

  • 如果条目处于除INCOMPLETE外的任何状态,并且接收到的源链路层地址与缓存的链路层地址不同,并且覆盖标志被设置,则将缓存的链路层地址替换为接收到的地址,并且条目的状态保持不变。

7.4. Sending Neighbor Advertisements (发送邻居通告)

节点响应邻居请求发送邻居通告,并且当其链路层地址更改时也发送未请求的邻居通告。

7.4.1. Responding to Neighbor Solicitations (响应邻居请求)

当接收到邻居请求时,目标节点应该 (SHOULD) 响应邻居通告。如果邻居请求的源地址不是未指定地址,则邻居通告发送到邻居请求的源地址;否则,邻居通告发送到全节点组播地址。

邻居通告的目标地址从邻居请求的目标地址复制。如果邻居通告是响应邻居请求而发送的,则请求标志设置为1;否则,设置为零。

如果邻居请求中包含目标链路层地址选项,并且链路层地址与接收节点的链路层地址不同,则覆盖标志设置为1;否则,根据情况设置。

7.4.2. Unsolicited Neighbor Advertisements (未请求的邻居通告)

节点可以发送未请求的邻居通告以宣布其链路层地址的更改。当节点检测到其链路层地址已更改(例如,在热交换以太网接口后)时,它应该 (SHOULD) 向全节点组播地址组播几个邻居通告,以快速更新邻居的邻居缓存条目。

对于未请求的邻居通告,覆盖标志应该 (SHOULD) 设置为1,以确保邻居更新其缓存的链路层地址。在未请求的邻居通告中,请求标志必须 (MUST) 设置为零。