3. 协议概述 (Protocol Overview)
本节的目标是按照 [RFC4101] 的精神描述 RPL. 协议细节见后续章节.
3.1. 拓扑 (Topologies)
本节描述可能形成的基本 RPL 拓扑, 以及构造这些拓扑的规则, 即约束 DODAG 形成的规则.
3.1.1. 构造拓扑 (Constructing Topologies)
LLN, 例如无线网络 (Radio Networks), 通常没有预定义拓扑, 例如由点到点线缆强加的拓扑. 因此, RPL 必须先发现链路, 然后谨慎选择对等节点.
在许多情况下, 由于第 2 层覆盖范围只部分重叠, RPL 会形成非传递 / 非广播多路访问 (Non-Broadcast Multi-Access, NBMA) 网络拓扑, 并在这些拓扑之上计算路由.
RPL 路由针对进出一个或多个根节点的流量进行优化, 这些根节点充当拓扑的汇聚点 (sinks). 因此, RPL 将拓扑组织为有向无环图 (Directed Acyclic Graph, DAG), 并将其划分为一个或多个面向目的地的 DAG (Destination Oriented DAGs, DODAGs), 每个汇聚点对应一个 DODAG. 如果 DAG 有多个根, 则预期这些根通过公共骨干联合在一起, 例如通过传输链路联合.
3.1.2. RPL 标识符 (RPL Identifiers)
RPL 使用四个值来标识和维护拓扑:
-
第一个是 RPLInstanceID. RPLInstanceID 标识一组由一个或多个面向目的地的 DAG (Destination Oriented DAGs, DODAGs) 组成的集合. 一个网络可以有多个 RPLInstanceID, 每个 RPLInstanceID 定义一组独立的 DODAG, 这些 DODAG 可以针对不同目标函数 (Objective Functions, OFs) 和/或应用进行优化. 由某个 RPLInstanceID 标识的 DODAG 集合称为 RPL 实例 (RPL Instance). 同一 RPL 实例中的所有 DODAG 使用相同的 OF.
-
第二个是 DODAGID. DODAGID 的作用域是 RPL 实例. RPLInstanceID 和 DODAGID 的组合唯一标识网络中的单个 DODAG. 一个 RPL 实例可以有多个 DODAG, 每个 DODAG 都有唯一的 DODAGID.
-
第三个是 DODAGVersionNumber. DODAGVersionNumber 的作用域是 DODAG. 有时, DODAG 根会通过递增 DODAGVersionNumber 来重建 DODAG. RPLInstanceID, DODAGID 和 DODAGVersionNumber 的组合唯一标识一个 DODAG 版本.
-
第四个是 Rank. Rank 的作用域是 DODAG 版本. Rank 在 DODAG 版本上建立偏序关系, 定义各个节点相对于 DODAG 根的位置.
3.1.3. 实例, DODAG 和 DODAG 版本 (Instances, DODAGs, and DODAG Versions)
一个 RPL 实例包含一个或多个 DODAG 根. RPL 实例可以为某些目的地前缀提供路由, 这些前缀可通过 DODAG 根或 DODAG 内的备用路径到达. 这些根可以独立运行, 也可以在一个不一定像 LLN 那样受限的网络上进行协调.
RPL 实例可以包括:
-
具有单个根的单个 DODAG
- 例如, 在家庭自动化应用中, 一个以单个集中式照明控制器为根, 并针对最小时延进行优化的 DODAG.
-
具有独立根且彼此不协调的多个 DODAG (具有不同 DODAGID)
- 例如, 城市数据采集应用中的多个数据采集点, 它们没有合适的连通性来相互协调, 或者通过形成多个 DODAG 的方式来动态且自主地划分网络.
-
具有虚拟根的单个 DODAG, 该虚拟根通过骨干网络协调 LLN 汇聚点 (具有相同 DODAGID).
- 例如, 多个通过可靠传输链路运行的边界路由器, 如为了支持 IPv6 低功耗无线个人区域网络 (IPv6 Low-Power Wireless Personal Area Network, 6LoWPAN) 应用而运行的边界路由器, 它们能够作为同一 DODAG 汇聚点的逻辑等价接口.
-
适合某些应用场景的上述组合.
每个 RPL 分组都与特定 RPLInstanceID (见第 11.2 节) 相关联, 因而也与特定 RPL 实例 (第 5 节) 相关联. RPLInstanceID 与应用流量类型或服务之间映射关系的配置或自动发现超出本规范范围, 将在未来配套规范中定义.
图 1 描绘了一个 RPL 实例示例, 该实例包含三个 DODAG, 其 DODAG 根分别为 R1, R2 和 R3. 这些 DODAG 根都通告相同的 RPLInstanceID. 图中的线表示父节点与子节点之间的连通性.
图 2 描绘了 DODAGVersionNumber 递增如何产生新的 DODAG 版本. 该图展示了 DODAGVersionNumber 递增导致不同 DODAG 拓扑的情况. 注意, 新的 DODAG 版本并不总是意味着不同的 DODAG 拓扑. 如本规范后文所述, 为适应某些拓扑变化, 需要新的 DODAG 版本.
在以下示例中请注意, 为简化起见, 图中使用类似树的结构表示. 但在连通性支持的情况下, DODAG 结构允许每个节点有多个父节点.
+----------------------------------------------------------------+
| |
| +--------------+ |
| | | |
| | (R1) | (R2) (R3) |
| | / \ | /| \ / | \ |
| | / \ | / | \ / | \ |
| | (A) (B) | (C) | (D) ... (F) (G) (H) |
| | /|\ |\ | / | / |\ |\ | | |
| | : : : : : | : (E) : : : `: : |
| | | / \ |
| +--------------+ : : |
| DODAG |
| |
+----------------------------------------------------------------+
RPL Instance
图 1: RPL 实例
+----------------+ +----------------+
| | | |
| (R1) | | (R1) |
| / \ | | / |
| / \ | | / |
| (A) (B) | \ | (A) |
| /|\ / |\ | ------\ | /|\ |
| : : (C) : : | \ | : : (C) |
| | / | \ |
| | ------/ | \ |
| | / | (B) |
| | | |\ |
| | | : : |
| | | |
+----------------+ +----------------+
Version N Version N+1
图 2: DODAG 版本
3.2. 向上路由和 DODAG 构造 (Upward Routes and DODAG Construction)
RPL 配置朝向 DODAG 根的 Up 路由, 形成根据目标函数 (Objective Function, OF) 优化的 DODAG. RPL 节点通过 DODAG 信息对象 (DODAG Information Object, DIO) 消息构造并维护这些 DODAG.
3.2.1. 目标函数 (Objective Function, OF)
目标函数 (Objective Function, OF) 定义 RPL 节点如何在 RPL 实例内选择并优化路由. OF 由 DIO Configuration 选项中的目标代码点 (Objective Code Point, OCP) 标识. OF 定义节点如何将一个或多个度量和约束转换为称为 Rank 的值, 这些度量和约束本身在 [RFC6551] 中定义, Rank 则近似表示节点到 DODAG 根的距离. OF 还定义节点如何选择父节点. 更多细节见第 14 节, [RFC6551], [RFC6552] 以及相关配套规范.
3.2.2. DODAG 修复 (DODAG Repair)
DODAG 根通过递增 DODAGVersionNumber 来发起全局修复操作. 这会启动新的 DODAG 版本. 新 DODAG 版本中的节点可以选择新的位置, 其 Rank 不受旧 DODAG 版本中 Rank 的约束.
RPL 还支持可在 DODAG 版本内用于本地修复的机制. DIO 消息指定必要参数, 这些参数由 DODAG 根上的策略配置和控制.
3.2.3. 安全 (Security)
RPL 支持消息机密性和完整性. 它的设计允许在链路层机制可用且适当时使用这些机制. 但在没有链路层机制时, RPL 可以使用自身机制. RPL 有三种基本安全模式.
第一种称为 "unsecured", 在该模式下, RPL 控制消息在不使用任何额外安全机制的情况下发送. 非安全模式并不意味着 RPL 网络是不安全的: 它可以使用其他已有安全原语, 例如链路层安全, 来满足应用安全需求.
第二种称为 "preinstalled", 加入 RPL 实例的节点具有预安装密钥, 这些密钥使节点能够处理和生成受保护的 RPL 消息.
第三种模式称为 "authenticated". 在 authenticated 模式下, 节点像 preinstalled 模式一样具有预安装密钥, 但该预安装密钥只能用于以叶节点身份加入 RPL 实例. 以路由器身份加入 authenticated RPL 实例需要从认证机构获取密钥. 获取该密钥的过程超出本规范范围. 注意, 仅凭本规范并不足以为 RPL 实现在 authenticated 模式下安全运行提供充分细节. 要使 RPL 实现在 authenticated 模式下安全运行, 未来的配套规范必须详细说明节点获取/请求认证材料 (例如密钥, 证书) 的机制, 并确定应从何处获得这些材料. 另见第 10.3 节.
3.2.4. Grounded 和 Floating DODAG (Grounded and Floating DODAGs)
DODAG 可以是 grounded, 也可以是 floating: DODAG 根会通告其所属状态. grounded DODAG 为满足应用定义目标所需的主机提供连通性. floating DODAG 不预期满足该目标. 在多数情况下, 它只为 DODAG 内的节点提供路由. 例如, floating DODAG 可用于在修复期间保持互连性.
3.2.5. 本地 DODAG (Local DODAGs)
RPL 节点可以通过形成本地 DODAG (Local DODAG) 来优化到 LLN 内某个目的地的路由, 该本地 DODAG 的 DODAG 根就是所需目的地. 与可以由多个 DODAG 组成的全局 DAG 不同, 本地 DAG 只有且仅有一个 DODAG, 因而也只有一个 DODAG 根. 本地 DODAG 可以按需构造.
3.2.6. 管理偏好 (Administrative Preference)
实现或部署可以通过管理偏好指定某些 DODAG 根优先于其他根使用. 管理偏好提供了一种控制流量并设计 DODAG 形成过程的方式, 以便更好地支持应用需求.
3.2.7. 数据路径验证和环路检测 (Data-Path Validation and Loop Detection)
LLN 的低功耗和有损特性促使 RPL 使用基于数据分组的按需环路检测. 由于数据流量可能并不频繁, 持续维护一个与物理拓扑保持最新的路由拓扑可能会浪费能量. 典型 LLN 中的物理连通性变化可能是暂时的, 且对流量无害, 但若从控制平面对其进行严密跟踪, 成本会很高. 对于暂时且不频繁的连通性变化, 在有数据需要发送之前, RPL 不必处理. RPL 设计的这一方面借鉴了现有且广泛使用的 LLN 协议, 也有大量实验和部署证据证明其有效性.
随数据分组传输的 RPL 分组信息包括发送方的 Rank. 分组的路由决策 (Upward 或 Downward) 与两个节点之间的 Rank 关系不一致时, 表示可能存在环路. 收到此类分组后, 节点会发起本地修复操作.
例如, 如果某个节点收到一个标记为沿 Upward 方向移动的分组, 且该分组记录发送方的 Rank 低于接收节点, 则接收节点可以判定该分组并未沿 Upward 方向前进, 且 DODAG 存在不一致.
3.2.8. 分布式算法运行 (Distributed Algorithm Operation)
构造 DODAG 的分布式算法可以从高层概括如下:
-
某些节点被配置为 DODAG 根, 并带有关联的 DODAG 配置.
-
节点通过向 all-RPL-nodes 发送链路本地组播 DIO 消息, 通告自身存在, 所属 DODAG, 路由成本以及相关度量.
-
节点监听 DIO, 并根据指定目标函数以及邻居的 Rank, 使用其中的信息加入新的 DODAG (从而选择 DODAG 父节点), 或维护现有 DODAG.
-
对于 DIO 消息指定的目的地, 节点通过其在 DODAG 版本中的 DODAG 父节点配置路由表项. 决定加入 DODAG 的节点可以将一个或多个 DODAG 父节点配置为默认路由以及关联实例若干其他外部路由的下一跳.
3.3. 向下路由和目的地通告 (Downward Routes and Destination Advertisement)
RPL 使用目的地通告对象 (Destination Advertisement Object, DAO) 消息建立 Downward 路由. 对于需要点到多点 (point-to-multipoint, P2MP) 或点到点 (point-to-point, P2P) 流量的应用, DAO 消息是一项可选特性. RPL 支持两种 Downward 流量模式: 存储模式 (Storing, 完全有状态) 或非存储模式 (Non-Storing, 完全源路由). 见第 9 节. 任意给定 RPL 实例要么是 storing, 要么是 non-storing. 在这两种情况下, P2P 分组都会先沿 Up 方向前往 DODAG 根, 再沿 Down 方向到达最终目的地 (除非目的地位于 Upward 路由上). 在 Non-Storing 情况下, 分组会一路到达 DODAG 根, 然后再沿 Down 方向传送. 在 Storing 情况下, 分组在到达 DODAG 根之前, 可能由源和目的地的共同祖先引导沿 Down 方向转发到目的地.
在编写本规范时, 不预期任何实现同时支持 Storing 和 Non-Storing 两种运行模式. 多数实现预期支持以下三种之一: 不支持 Downward 路由, 仅支持 Non-Storing 模式, 或仅支持 Storing 模式. 其他运行模式, 例如 Storing 与 Non-Storing 模式的混合方式, 超出本规范范围, 可由其他配套规范描述.
本规范描述一种支持 P2P 流量的基本运行模式. 注意, 更优化的 P2P 解决方案可以在配套规范中描述.
3.4. 本地 DODAG 路由发现 (Local DODAGs Route Discovery)
可选地, RPL 网络可以支持按需发现通向 LLN 内特定目的地的 DODAG. 这类本地 DODAG 的行为与全局 DODAG 略有不同: 它们由 DODAGID 和 RPLInstanceID 的组合唯一确定. RPLInstanceID 表示某个 DODAG 是否为本地 DODAG.
3.5. Rank 属性 (Rank Properties)
节点的 Rank 是该节点在某个 DODAG 版本中位置的标量表示. Rank 用于避免和检测环路, 因此必须展现某些属性. Rank 的精确计算留给目标函数处理. 即使 Rank 的具体计算由目标函数决定, Rank 也必须实现与目标函数无关的通用属性.
特别是, 沿着 DODAG 版本朝向 DODAG 目的地前进时, 节点的 Rank 必须单调递减. 从这个角度看, Rank 可以视为节点在某个 DODAG 版本中的位置或半径的标量表示.
目标函数如何计算 Rank 的细节超出本规范范围, 尽管该计算可能依赖于父节点, 链路度量, 节点度量, 以及节点配置和策略等因素. 更多信息见第 14 节.
Rank 不是路径成本, 尽管它的值可以从路径度量派生并受其影响. Rank 具有自身属性, 这些属性不一定适用于所有度量:
Type: : Rank 是一个抽象数值.
Function: : Rank 表达某个节点在 DODAG 版本中相对于邻居的相对位置, 不一定能很好地指示或适当地表达到根的距离或路径成本.
Stability: : Rank 的稳定性决定路由拓扑的稳定性. RECOMMENDED 使用某种抑制或过滤机制来保持拓扑稳定. 因此, Rank 不一定像某些链路或节点度量那样快速变化. 新的 DODAG 版本是一个很好的机会, 可用于协调 DODAG 版本内随时间形成的度量与 Rank 之间的差异.
Properties: : Rank 以严格单调方式递增, 可用于验证从根出发或朝向根的前进过程. 带宽或抖动等度量不一定表现出这种属性.
Abstract: : Rank 没有物理单位, 而是每跳增量的一个范围, 其中每个增量的分配由目标函数决定.
根据 RPL 环路避免策略, Rank 值会用于 DODAG 父节点选择. 一旦添加了父节点, 并且节点在 DODAG 内的 Rank 值已经被通告, 为了避免环路, 该节点后续在 DODAG 父节点选择以及在 DODAG 内移动方面的选择会受到限制.
3.5.1. Rank 比较 (DAGRank())
Rank 可以视为一个定点数, 其中整数部分与小数部分之间基点的位置由 MinHopRankIncrease 决定. MinHopRankIncrease 是某个节点与其任一 DODAG 父节点之间 Rank 的最小增量. DODAG 根配置 MinHopRankIncrease. MinHopRankIncrease 在跳成本精度与网络可支持的最大跳数之间形成折衷. 例如, 非常大的 MinHopRankIncrease 可以精确刻画给定一跳对 Rank 的影响, 但无法支持很多跳.
当目标函数计算 Rank 时, 目标函数作用于整个 Rank 数量, 即 16 位 Rank. 当比较 Rank 时, 例如用于确定父子关系或进行环路检测时, 应使用 Rank 的整数部分. Rank 的整数部分由 DAGRank() 宏按如下方式计算, 其中 floor(x) 是求不大于 x 的最大整数的函数:
DAGRank(rank) = floor(rank/MinHopRankIncrease)
例如, 如果 16 位 Rank 数量为十进制 27, MinHopRankIncrease 为十进制 16, 则 DAGRank(27) = floor(1.6875) = 1. Rank 的整数部分为 1, 小数部分为 11/16.
按照本文档的约定, 使用宏 DAGRank(node) 可以解释为 DAGRank(node.rank), 其中 node.rank 是节点维护的 Rank 值.
如果 DAGRank(A) 小于 DAGRank(B), 则节点 A 的 Rank 小于节点 B 的 Rank.
如果 DAGRank(A) 等于 DAGRank(B), 则节点 A 的 Rank 等于节点 B 的 Rank.
如果 DAGRank(A) 大于 DAGRank(B), 则节点 A 的 Rank 大于节点 B 的 Rank.
3.5.2. Rank 关系 (Rank Relationships)
对于 LLN 中作为邻居的任意节点 M 和 N, Rank 计算保持以下属性:
DAGRank(M) is less than DAGRank(N):
: 在这种情况下, M 的位置比 N 的位置更接近 DODAG 根. 节点 M 可以安全地作为节点 N 的 DODAG 父节点, 而不会产生环路风险. 此外, 对于节点 N, DODAG 父节点集合中的所有父节点都必须具有小于 DAGRank(N) 的 Rank. 换言之, 节点 N 呈现的 Rank MUST 大于其任一父节点呈现的 Rank.
DAGRank(M) equals DAGRank(N):
: 在这种情况下, M 和 N 在 DODAG 内以及相对于 DODAG 根的位置相似或相同. 通过具有相同 Rank 的节点进行路由可能导致路由环路, 例如当该节点也选择通过具有相同 Rank 的节点进行路由时.
DAGRank(M) is greater than DAGRank(N):
: 在这种情况下, M 的位置比 N 的位置更远离 DODAG 根. 此外, 节点 M 实际上可能位于节点 N 的子 DODAG 中. 如果节点 N 选择节点 M 作为 DODAG 父节点, 就存在产生环路的风险.
例如, 当目标函数最小化的度量是 ETX, 时延, 或其他更复杂的度量时, 可以用一种紧密跟踪 ETX 的方式计算 Rank. ETX 即期望传输次数 (expected transmission count), 是 LLN 中相当常见的路由度量, 定义于 [RFC6551]. 具体计算方式可根据 DODAG 内使用的目标函数而定.
3.6. RPL 使用的路由度量和约束 (Routing Metrics and Constraints Used by RPL)
路由协议使用路由度量来计算最短路径. 内部网关协议 (Interior Gateway Protocols, IGPs), 例如 IS-IS ([RFC5120]) 和 OSPF ([RFC4915]), 使用静态链路度量. 这类链路度量可以简单反映带宽, 也可以根据定义不同链路特征的若干度量的多项式函数计算. 有些路由协议支持多个度量: 在绝大多数情况下, 每个子拓扑使用一个度量. 较少情况下, 在存在等价多路径 (Equal Cost Multiple Paths, ECMPs) 时, 第二个度量可用作决胜条件. 多度量优化是已知的 NP-complete 问题, 有时由某些集中式路径计算引擎支持.
相比之下, LLN 确实需要同时支持静态度量和动态度量. 此外, 还需要同时支持链路度量和节点度量. 对 RPL 而言, 实际上不可能定义一个度量, 甚至一个复合度量, 来满足所有用例.
此外, RPL 支持基于约束的路由, 其中约束可应用于链路和节点. 如果某条链路或某个节点不满足所需约束, 它会从候选邻居集合中被 "修剪", 从而得到受约束的最短路径.
目标函数指定用于计算受约束路径的目标. 此外, 节点被配置为支持一组度量和约束, 并根据 DIO 消息中通告的度量和约束在 DODAG 中选择父节点. 根据 OF 和度量的不同, Upstream 和 Downstream 度量可以合并, 也可以分别通告. 当它们分别通告时, DIO 父节点集合可能不同于 DAO 父节点集合. DAO 父节点是接收单播 DAO 消息的节点. 但是, 就 Rank 计算规则而言, 它们都是 DODAG 父节点.
目标函数与 RPL 使用的路由度量和约束解耦. OF 规定 DODAG 父节点选择, 负载均衡等规则, 而使用的度量和/或约束集合, 也就是决定首选路径的那些因素, 则基于 DIO 消息中 DAG container 选项携带的信息.
支持的链路/节点约束和度量集合在 [RFC6551] 中规定.
示例 1: 最短路径: 提供最短端到端时延的路径.
示例 2: 最短受约束路径: 不经过任何电池供电节点, 并优化路径可靠性的路径.
3.7. 环路避免 (Loop Avoidance)
RPL 在拓扑变化期间会尽量避免产生环路, 并包含基于 Rank 的数据路径验证机制, 用于在环路确实发生时检测环路. 更多细节见第 11 节. 在实践中, 这意味着 RPL 既不保证无环路径选择, 也不保证严格的时延收敛时间, 但它可以在环路一被使用时检测并修复该环路. RPL 使用这种环路检测来确保分组在 DODAG 版本内向前推进, 并在必要时触发修复.
3.7.1. 贪婪性和不稳定性 (Greediness and Instability)
如果某个节点为了扩大父节点集合或改进其他度量, 试图在 DODAG 版本中移动得更深 (增加 Rank), 则该节点是贪婪的. 一旦节点加入 DODAG 版本, RPL 就会禁止某些行为, 包括贪婪行为, 以防止 DODAG 版本中由此产生的不稳定性.
假设某个节点愿意接收并处理来自其自身子 DODAG 中节点的 DIO 消息, 通常也就是来自比它自身更深的节点的 DIO 消息. 在这种情况下, 可能会形成反馈环路, 其中两个或更多节点在尝试相互优化的同时, 持续尝试在 DODAG 版本中移动. 在某些情况下, 这会导致不稳定. 因此, RPL 将节点可处理来自更深节点的 DIO 消息的情况限制为某种形式的本地修复. 这种方法创建了一个 "event horizon", 使得某个节点不会因自身子 DODAG 中节点的行为而在超过某个限制后受到影响并进入不稳定状态.
3.7.1.1. 示例: 贪婪父节点选择和不稳定性 (Greedy Parent Selection and Instability)
(A) (A) (A)
|\ |\ |\
| `-----. | `-----. | `-----.
| \ | \ | \
(B) (C) (B) \ | (C)
\ | | /
`-----. | | .-----'
\| |/
(C) (B)
-1- -2- -3-
图 3: 贪婪 DODAG 父节点选择
图 3 描绘了一个 DODAG 的三种不同配置. 在所有三种配置中, (B) 和 (C) 之间都存在可用链路. 在图 3-1 中, 节点 (A) 是节点 (B) 和 (C) 的 DODAG 父节点. 在图 3-2 中, 节点 (A) 是节点 (B) 和 (C) 的 DODAG 父节点, 节点 (B) 也是节点 (C) 的 DODAG 父节点. 在图 3-3 中, 节点 (A) 是节点 (B) 和 (C) 的 DODAG 父节点, 节点 (C) 也是节点 (B) 的 DODAG 父节点.
如果 RPL 节点过于贪婪, 也就是试图在其最优选父节点之外再优化出更多父节点, 就可能导致不稳定. 考虑图 3-1 所示的 DODAG. 在此示例中, 节点 (B) 和 (C) 可能最偏好节点 (A) 作为 DODAG 父节点, 但我们考虑它们在贪婪条件下运行并试图优化出两个父节点的情况.
-
令图 3-1 为初始条件.
-
假设节点 (C) 首先能够离开 DODAG, 并以更低的 Rank 重新加入, 同时将节点 (A) 和 (B) 作为 DODAG 父节点, 如图 3-2 所示. 此时节点 (C) 比节点 (A) 和 (B) 都更深, 且节点 (C) 满足于拥有两个 DODAG 父节点.
-
假设节点 (B) 出于贪婪, 愿意接收并处理来自节点 (C) 的 DIO 消息 (这违反 RPL 规则), 然后节点 (B) 离开 DODAG, 并以更低的 Rank 重新加入, 同时将节点 (A) 和 (C) 作为 DODAG 父节点. 此时节点 (B) 比节点 (A) 和 (C) 都更深, 并满足于拥有两个 DAG 父节点.
-
随后, 节点 (C) 由于同样贪婪, 会离开并在更深位置重新加入, 以再次获得两个父节点, 并具有比这两个父节点更低的 Rank.
-
接下来, 节点 (B) 会再次离开并在更深位置重新加入, 以再次获得两个父节点.
-
然后, 节点 (C) 再次离开并在更深位置重新加入.
-
该过程会重复, DODAG 会在图 3-2 和图 3-3 之间振荡, 直到节点计数至无穷并再次重新开始该循环.
-
可以通过 RPL 中的机制避免该循环:
-
节点 (B) 和 (C) 保持在足以附着到其最优选父节点 (A) 的 Rank, 而不追求任何更深 (更差) 的备用父节点 (节点不贪婪).
-
节点 (B) 和 (C) 不处理来自比自身更深节点的 DIO 消息 (因为这些节点可能位于其自身的子 DODAG 中).
-
这些机制在第 8.2.2.4 节中进一步描述.
3.7.2. DODAG 环路 (DODAG Loops)
当某个节点从 DODAG 脱离并重新附着到其先前子 DODAG 中的设备时, 可能会发生 DODAG 环路. 特别是, 当 DIO 消息丢失时, 可能发生这种情况. 严格使用 DODAGVersionNumber 可以消除此类环路, 但在使用某些本地修复机制时仍可能遇到此类环路.
例如, 考虑一种本地修复机制: 它允许节点从 DODAG 脱离, 通告 Rank 为 INFINITE_RANK (以毒化其路由 / 通知其子 DODAG), 然后重新附着到 DODAG. 在其中某些情况下, 节点可能会重新附着到其自身先前的子 DODAG, 从而导致 DODAG 环路. 这是因为如果 INFINITE_RANK 通告在 LLN 环境中丢失, 毒化可能失败. 在这种情况下, 基于 Rank 的数据路径验证机制最终会检测到该环路并触发修正.
3.7.3. DAO 环路 (DAO Loops)
当父节点在接收并处理来自子节点的 DAO 消息后安装了路由, 但该子节点随后清理了相关 DAO 状态时, 可能会发生 DAO 环路. 当 No-Path 丢失时会发生这种环路, 并会一直持续到所有状态都被清理. No-Path 是一种使先前通告的前缀失效的 DAO 消息, 见第 6.4.3 节. RPL 包含一种用于确认 DAO 消息的可选机制, 该机制可以缓解单个 DAO 消息丢失造成的影响. RPL 包含环路检测机制, 可缓解 DAO 环路的影响并触发其修复. 见第 11.2.2.3 节.