Skip to main content

5. 主机的概念模型

虽然不要求实现符合主机的特定概念模型, 但本节描述了主机可以用来帮助理解邻居发现的概念模型。主机在概念上维护许多数据结构:

邻居缓存 (Neighbor Cache) - 关于最近发送流量的各个邻居的条目集。条目以邻居的链路内单播IP地址为键, 并包含诸如其链路层地址、指示邻居是路由器还是主机的标志 (在本文档中称为IsRouter)、指向等待地址解析完成的任何排队数据包的指针等信息。邻居缓存条目还包含邻居不可达检测算法使用的信息, 包括可达性状态、未应答探测的数量以及计划进行下一次邻居不可达检测事件的时间。

目的地缓存 (Destination Cache) - 关于最近发送流量的目的地的条目集。目的地缓存包括链路内和链路外目的地, 并提供到邻居缓存的间接级别; 目的地缓存将目的地IP地址映射到下一跳邻居的IP地址。与邻居缓存不同, 目的地缓存包含链路内和链路外目的地的条目。将目的地缓存与邻居缓存分开维护有多个目的。首先, 目的地缓存可以包含链路上不相邻的目的地的条目。其次, 目的地缓存可以包含受路径MTU发现、重定向消息等影响的条目。

前缀列表 (Prefix List) - 定义链路内地址集的前缀列表。前缀列表条目是从路由器通告中接收的信息创建的。每个条目都有一个相关的失效计时器值 (从通告中提取), 用于使前缀过期。前缀列表条目还包含一个标志, 指示前缀是否可用于链路内确定和/或地址自动配置, 如 [ADDRCONF] 中所述。

默认路由器列表 (Default Router List) - 可以向其发送数据包的路由器列表。默认路由器列表条目指向邻居缓存中的条目; 选择默认路由器的算法偏好已知可达的路由器而不是可达性可疑的路由器。每个条目还有一个相关的失效计时器值 (从路由器通告中提取), 用于删除不再通告的条目。

上述概念数据结构在功能上是分开的; 实现可以自由地以最方便的方式组合部分或全部数据结构。通过在以下各节的伪代码中使用上述数据结构, 可以直接满足本协议的要求。但是, 只要实现的外部行为保持不变, 实现可以自由使用替代数据结构。

5.1. Conceptual Data Structures (概念数据结构)

虽然主机不需要维护下面描述的所有数据结构, 但本节描述了一组足以实现邻居发现的数据结构。

5.2. Conceptual Sending Algorithm (概念发送算法)

当节点有要发送的数据包时, 它首先检查目的地缓存。如果目的地不存在条目, 节点将创建一个条目并通过调用下一跳确定算法 (第5.2节) 初始化其下一跳地址。一旦创建了目的地缓存条目, 节点就会检查下一跳的邻居缓存条目的状态。

邻居缓存条目可以处于五种状态之一:

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

REACHABLE (可达) - 已知该条目最近 (在数十秒前) 可达。在最后ReachableTime毫秒内收到了正向路径到邻居正常运行的积极确认。在REACHABLE状态下, 发送数据包时不采取特殊操作。

STALE (陈旧) - 已知该条目最近可达, 但最近未收到确认。在STALE状态下, 在发送数据包之前不采取任何操作。发送数据包时, 节点根据实现将条目转换为DELAY或PROBE。

DELAY (延迟) - 已知该条目最近可达, 并且在最后DELAY_FIRST_PROBE_TIME秒内发送了数据包。如果在进入DELAY状态后DELAY_FIRST_PROBE_TIME秒内未收到可达性确认, 则发送邻居请求并将状态更改为PROBE。延迟探测的传输为上层协议提供可达性确认的机会。

PROBE (探测) - 通过每RetransTimer毫秒重传邻居请求来主动寻求可达性确认, 直到收到可达性确认。

邻居缓存还保存运行邻居不可达检测算法所需的信息, 包括各种计时器、计数器等。

向邻居发送数据包时, 节点使用邻居缓存条目中包含的状态信息来确定在向该邻居发送流量之前需要做什么 (如果有的话)。以下伪代码说明了发送算法:

if (目的地缓存条目存在) {
next hop = 目的地缓存 next_hop;
} else {
next hop = 下一跳确定 (第5.2节);
创建目的地缓存条目;
}

if (下一跳的邻居缓存条目存在) {
if (邻居缓存条目状态 == INCOMPLETE) {
将数据包排队到邻居缓存条目;
/* 地址解析已在进行中 */
}
if (邻居缓存条目状态 == REACHABLE) {
发送数据包;
}
if (邻居缓存条目状态 == STALE) {
发送数据包;
将邻居缓存条目状态设置为DELAY;
将邻居缓存条目计时器设置为DELAY_FIRST_PROBE_TIME;
}
if (邻居缓存条目状态 == DELAY) {
发送数据包;
/* 计时器已设置 */
}
if (邻居缓存条目状态 == PROBE) {
发送数据包;
/* 邻居不可达检测正在进行 */
}
} else {
创建邻居缓存条目;
将邻居缓存条目状态设置为INCOMPLETE;
if (链路层地址可轻易获得) {
设置链路层地址;
将邻居缓存条目状态设置为STALE;
发送数据包;
} else {
将数据包排队到邻居缓存条目;
开始地址解析;
}
}

5.3. Garbage Collection and Timeout Requirements (垃圾回收和超时要求)

邻居缓存、目的地缓存和前缀列表必须进行垃圾回收和超时。但是, 特定的超时期限故意未指定。必须选择超时期限以在维护陈旧信息和更新该信息的成本之间提供合理的平衡。通常, 超时期限应足够慷慨以防止缓存内容的抖动, 但足够短以防止长期陈旧。

概念实现可能使用以下规则:

  • 邻居缓存条目应在转换到STALE状态后至少保留ReachableTime指定的时间。但是, 如果实现使用某种形式的垃圾回收算法来回收条目, 它们可以保留更长时间。INCOMPLETE状态下的条目不需要保留这么长时间。

  • 目的地缓存条目应尽可能长时间 (即无限期) 保留在缓存中。但是, 特定的时间段取决于实现。如果收到指定到目的地的更好路由的重定向消息, 实现应该 (SHOULD) 使目的地缓存条目无效。

  • 前缀列表中的条目根据路由器通告中指定的生命周期超时。当新的路由器通告到达时, 条目的生命周期会更新。

  • 默认路由器列表中的条目根据路由器通告中指定的路由器生命周期超时。收到路由器生命周期为零的路由器通告表明应立即从默认路由器列表中删除该路由器。