8.2.2. 跨 DODAG Version 的邻居和父节点 (Neighbors and Parents across DODAG Versions)
上述规则管理单个 DODAG Version. 本节中的规则定义当存在多个 DODAG Version 时 RPL 如何运行.
8.2.2.1. DODAG Version
-
元组 (RPLInstanceID, DODAGID, DODAGVersionNumber) 唯一定义一个 DODAG Version. 节点 DODAG 父节点集合中的每个元素, 按从每个 DODAG 父节点最近听到的 DIO 消息所传达的信息, MUST 属于同一个 DODAG Version. 节点候选邻居集合中的元素 MAY 属于不同的 DODAG Version.
-
如果节点 DODAG 父节点集合中的每个元素都属于某个 DODAG Version, 或者该节点是对应 DODAG 的根, 则该节点是该 DODAG Version 的成员.
-
节点 MUST NOT 为自己不是成员的 DODAG Version 发送 DIO.
-
DODAG 根 MAY 递增其通告的 DODAGVersionNumber, 从而迁移到新的 DODAG Version. 当 DODAG 根递增其 DODAGVersionNumber 时, 它 MUST 遵循第 7 节所述的序列号算术 (Serial Number Arithmetic) 约定. 触发 DODAGVersionNumber 递增的事件在本节后文和第 18 节中描述.
-
在给定 DODAG 内, 非根节点 MUST NOT 通告高于它听到的最高 DODAGVersionNumber 的 DODAGVersionNumber. Higher 定义为第 7 节中的大于运算符.
-
一旦节点通过发送 DIO 通告了某个 DODAG Version, 它 MUST NOT 成为同一 DODAG 的先前 DODAG Version 的成员 (即具有相同 RPLInstanceID, 相同 DODAGID 和较低 DODAGVersionNumber). Lower 定义为第 7 节中的小于运算符.
当非根节点上的 DODAG 父节点集合变为空时 (即最后一个父节点已被移除, 导致该节点不再与该 DODAG 关联), 在实现特定的本地计时器到期之前不应抑制 DODAG 信息. 在抑制 "old" DODAG 状态之前的间隔内, 如果出现任何新父节点, 该节点将能够观察 DODAGVersionNumber 是否已递增. 这有助于防止某些可能的环路, 这些环路可能在该节点无意中重新加入其自身先前 sub-DODAG 中的旧 DODAG Version 时发生.
随着 DODAGVersionNumber 递增, 新的 DODAG Version 会从 DODAG 根向外扩散. 通告新 DODAGVersionNumber 的父节点不可能属于正在通告较旧 DODAGVersionNumber 的节点的 sub-DODAG. 因此, 节点可以安全地添加任意 Rank 且具有较新 DODAGVersionNumber 的父节点, 而不会形成环路.
例如, 假设某节点已离开 DODAGVersionNumber 为 N 的 DODAG. 又假设该节点曾有一个 sub-DODAG, 并曾尝试通过通告 INFINITE_RANK 的 Rank 来毒化该 sub-DODAG, 但这些通告可能已在 LLN 中丢失. 那么, 如果该节点观察到某个候选邻居正在以 DODAGVersionNumber N 通告其在原始 DODAG 中的位置, 该候选邻居可能位于该节点先前的 sub-DODAG 中, 因而存在一种可能情况: 将该候选邻居添加为父节点可能导致环路. 在这种情况下, 如果观察到该候选邻居通告 DODAGVersionNumber N+1, 则可以确定该候选邻居是安全的, 因为它必然不在原始节点的 sub-DODAG 中, 它是在原始节点分离期间通过听到 DODAG 根的信息才得以递增 DODAGVersionNumber 的. 因此, 分离节点记住原始 DODAG 信息是有用的, 包括 DODAGVersionNumber N.
DODAG 根究竟何时递增 DODAGVersionNumber 依赖于实现, 超出本规范范围. 示例包括周期性递增 DODAGVersionNumber, 根据管理干预递增, 或在应用层检测到连通性丢失或 DODAG 低效时递增.
节点转换到并通告新的 DODAG Version 后, 一旦它已承诺通告新的 DODAG Version, 上述规则就使它无法再通告先前的 DODAG Version (先前的 DODAGVersionNumber).
8.2.2.2. DODAG 根 (DODAG Roots)
-
无法满足应用定义目标的 DODAG 根 MUST NOT 设置 Grounded 位.
-
DODAG 根 MUST 通告 ROOT_RANK 的 Rank.
-
DODAG 父节点集合为空的节点 MAY 成为 floating DODAG 的 DODAG 根. 它 MAY 同时设置其 DAGPreference, 使其较不受偏好.
在使用非 LLN 链路联合多个 LLN 根的部署中, 可以在这些非 RPL 链路上运行 RPL, 并使用一个路由器作为 "backbone root". backbone root 是 DODAG 的虚拟根, 并在骨干上暴露 BASE_RANK 的 Rank. 所有以该 backbone root 为父节点的 LLN 根, 包括 backbone root 本身也作为 LLN 根服务的情况, 都向 LLN 暴露 ROOT_RANK 的 Rank. 这些虚拟根是同一 DODAG 的组成部分, 并通告相同的 DODAGID. 它们通过骨干与虚拟根协调 DODAGVersionNumber 和其他 DODAG 参数. 协调方法超出本规范范围 (将在未来配套规范中定义).
8.2.2.3. DODAG 选择 (DODAG Selection)
Objective Function 以及 DAG 通告的路由度量和约束集合决定节点如何选择其邻居集合, 父节点集合和首选父节点. 这种选择也隐式决定 DAG 内的 DODAG. 此类选择可以包括管理偏好 (Prf), 以及度量或其他考虑因素.
如果节点可以加入一个更受偏好的 DODAG, 同时仍然满足其他优化目标, 则该节点通常会尝试加入由 OF 确定的更受偏好的 DODAG. 在其他条件相同的情况下, 由实现决定哪个 DODAG 最受偏好 (因为需要提醒的是, 节点在每个 RPL Instance 中只能加入一个 DODAG).
8.2.2.4. DODAG Version 内的 Rank 和移动 (Rank and Movement within a DODAG Version)
-
节点 MUST NOT 通告小于或等于 DODAG Version 内其父节点集合中任何成员的 Rank.
-
节点 MAY 通告低于其在该 DODAG Version 内先前通告值的 Rank.
-
令 L 为给定节点在某个 DODAG Version 内曾通告的最低 Rank. 在同一 DODAG Version 内, 该节点 MUST NOT 通告高于 L + DAGMaxRankIncrease 的有效 Rank. INFINITE_RANK 是该规则的例外: 节点 MAY 在 DODAG Version 内不受限制地通告 INFINITE_RANK. 如果节点的 Rank 将高于 L + DAGMaxRankIncrease 所允许的值, 则当它通告 Rank 时, 它 MUST 将自己的 Rank 通告为 INFINITE_RANK.
-
节点 MAY 在任意时间选择加入 RPL Instance 内的另一个 DODAG. 此类加入没有 Rank 限制, 除非该不同 DODAG 是该节点先前曾经作为成员的 DODAG Version; 在这种情况下, 必须遵守上一条 (3) 的规则. 在节点发送 DIO 指示其新的 DODAG 成员身份之前, 它 MUST 沿先前的 DODAG 转发分组.
-
节点 MAY 在听到合适 DODAG 父节点通告的下一个 DODAGVersionNumber 后的任意时间, 选择迁移到该 DODAG 内的下一个 DODAG Version.
从概念上讲, 实现会在 DODAG Version 内维护一个 DODAG 父节点集合. 移动意味着 DODAG 父节点集合发生变化. 向 Up 移动不会带来产生环路的风险, 但向 Down 移动可能会, 因此该操作受到额外约束.
当节点迁移到下一个 DODAG Version 时, 需要为新 Version 重建 DODAG 父节点集合. 实现可以推迟迁移一段合理时间, 以观察是否有其他可能具有更好度量但 Rank 更高的邻居通告自身. 类似地, 当节点跳转到新的 DODAG 时, 需要为这个新的 DODAG 构造新的 DODAG 父节点集合.
如果节点需要在其所附接的 DODAG 内向 Down 移动并提高其 Rank, 则它 MAY 按第 8.2.2.5 节所述毒化其路由并在移动前延迟.
节点允许不受限制地加入任何它先前从未作为成员的 DODAG Version, 但如果该节点曾是该 DODAG Version 的先前成员, 则它必须继续遵守以下规则: 在该 DODAG Version 生命周期中的任何时刻, 它不得通告高于 L+DAGMaxRankIncrease 的 Rank. 必须遵守此规则, 以免产生一个漏洞, 允许节点实际上一路递增其 Rank 直到 INFINITE_RANK, 这可能影响其他节点并造成浪费资源的 count-to-infinity 场景.
8.2.2.5. 毒化 (Poisoning)
-
节点通过通告 INFINITE_RANK 的 Rank 来毒化路由.
-
节点的父节点集合中 MUST NOT 有任何 Rank 为 INFINITE_RANK 的节点.
尽管实现可以出于毒化目的通告 INFINITE_RANK, 但这样做并不等同于将 Rank 设置为 INFINITE_RANK. 例如, 节点可以继续发送数据分组, 其 RPL Packet Information 包含的 Rank 不是 INFINITE_RANK, 但仍在其 DIO 中通告 INFINITE_RANK.
当观察到某个 (先前的) 父节点通告 INFINITE_RANK 的 Rank 时, 该 (先前的) 父节点已经从 DODAG 分离, 不再能够充当父节点, 也不存在其他节点可被视为具有大于 INFINITE_RANK 的 Rank 的方式. 因此, 该 (先前的) 父节点不能再充当父节点, 并会从父节点集合中移除.
8.2.2.6. 分离 (Detaching)
- 在给定 DODAG Version 内无法保持连接到 DODAG 的节点, 即如果不违反本规范规则就无法保留非空父节点集合的节点, MAY 从该 DODAG Version 分离. 分离的节点成为其自身 floating DODAG 的根, 并且 SHOULD 立即在 DIO 中通告这一新情况, 作为毒化的替代方案.
8.2.2.7. 跟随父节点 (Following a Parent)
- 如果节点从其某个 DODAG 父节点收到 DIO, 指示该父节点已离开 DODAG, 则该节点 SHOULD 尽可能通过备用 DODAG 父节点留在当前 DODAG 中. 它 MAY 跟随正在离开的父节点.
DODAG 父节点可能已经移动, 迁移到下一个 DODAG Version, 或跳转到不同 DODAG. 如果可以通过备用父节点留在当前 DODAG, 节点应对留在当前 DODAG 给予一定偏好, 但如果没有其他选择, 则应跟随该父节点.