8. Upward 路由 (Upward Routes)
本节描述 RPL 如何发现和维护 Upward 路由. 它描述 DODAG 信息对象 (DODAG Information Objects, DIOs) 的使用, 这些消息用于发现和维护这些路由. 本节规定 RPL 如何生成和响应 DIO. 它还描述 DODAG 信息请求 (DODAG Information Solicitation, DIS) 消息, 这些消息用于触发 DIO 传输.
如第 3.2.8 节所述, 决定加入 DODAG 的节点 MUST 至少配置一个 DODAG 父节点作为关联实例的默认路由. 该默认路由使分组能够向 Upward 转发, 直到最终到达某个共同祖先, 再从那里向 Downward 路由到目的地. 如果目的地不在 DODAG 中, 则 DODAG 根可能能够利用到 DODAG 外部的连通性转发该分组; 如果无法向外部转发该分组, 则 DODAG 根必须丢弃它.
DIO 消息也可以传输显式路由信息:
-
DODAGID: DODAGID 是根的全局或唯一本地 IPv6 地址. 加入 DODAG 的节点 SHOULD 经由 DODAG 父节点, 为根用作 DODAGID 的地址配置一条主机路由.
-
RIO Prefix: 根 MAY 在 DIO 消息中放置一个或多个 Route Information 选项. RIO 用于通告一条可经由根到达并与偏好关联的外部路由, 如第 6.7.5 节所述, 该节纳入了 [RFC4191] 中的 RIO. 它被解释为根的一种能力, 而不是路由通告, 并且 MUST NOT 被重新分发到另一个路由协议中; 但是当一个分组从附接到某个 RPL 路由器的节点注入 RPL 域时, 入口 RPL 路由器 SHOULD 使用它来选择 DODAG. Objective Function MAY 使用 RIO 中通告的路由或这些路由的偏好, 以便在同一实例中偏向某个 DODAG 而不是另一个 DODAG.
8.1. DIO 基本规则 (DIO Base Rules)
-
对于以下 DIO Base 字段, 非 DODAG 根节点 MUST 通告与其首选 DODAG 父节点 (第 8.2.1 节定义) 相同的值. 这样, 这些值将沿 DODAG 向 Down 传播且保持不变, 并由每个拥有到该 DODAG 根路由的节点通告. 这些字段如下:
- Grounded (G)
- Mode of Operation (MOP)
- DAGPreference (Prf)
- Version
- RPLInstanceID
- DODAGID
-
节点 MAY 在每一跳更新以下字段:
- Rank
- DTSN
-
每个根设置的 DODAGID 字段 MUST 在 RPL Instance 内唯一, 并且 MUST 是属于该根的可路由 IPv6 地址.
8.2. Upward 路由发现和维护 (Upward Route Discovery and Maintenance)
Upward 路由发现允许节点通过发现属于目标 DODAG 的邻居并识别父节点集合来加入该 DODAG. 选择邻居和父节点的确切策略依赖于实现, 并由 OF 驱动. 本节规定这些策略为实现互操作性必须遵循的规则集合.
8.2.1. DODAG Version 内的邻居和父节点 (Neighbors and Parents within a DODAG Version)
RPL 的 Upward 路由发现算法和处理以三类链路本地节点的逻辑集合来表述. 首先, 候选邻居集合是可通过链路本地组播到达的节点子集. 该集合的选择依赖于实现和 OF. 其次, 父节点集合是候选邻居集合的受限子集. 最后, 首选父节点是父节点集合中的成员, 也是 Upward 路由中的首选下一跳. 从概念上讲, 首选父节点是单个父节点; 但如果多个父节点同等受偏好且具有相同 Rank, 它也可以是一组父节点.
更准确地说:
-
DODAG 父节点集合 MUST 是候选邻居集合的子集.
-
DODAG 根 MUST 具有大小为零的 DODAG 父节点集合.
-
非 DODAG 根节点 MAY 维护大小大于或等于一的 DODAG 父节点集合.
-
节点的首选 DODAG 父节点 MUST 是其 DODAG 父节点集合的成员.
-
节点的 Rank MUST 大于其 DODAG 父节点集合中的所有元素.
-
当邻居不可达检测 (Neighbor Unreachability Detection, NUD) [RFC4861] 或等效机制确定某个邻居不再可达时, RPL 节点在计算和通告路由时 MUST NOT 将该节点纳入候选邻居集合, 直到它确定该节点再次可达. 经过不可达邻居的路由 MUST 从路由表中移除.
这些规则确保 DODAG 内节点之间存在一致的偏序关系. 只要节点 Rank 不变, 遵循上述规则即可确保每个节点到 DODAG 根的路由无环, 因为到根的每一跳 Rank 都会降低.
OF 可以指导候选邻居集合和父节点集合选择, 如 [RFC6552] 中所述.
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 给予一定偏好, 但如果没有其他选择, 则应跟随该父节点.
8.2.3. DIO 消息通信 (DIO Message Communication)
收到 DIO 消息时, 接收节点必须首先确定该 DIO 消息是否应被接受以进行进一步处理, 随后如果符合条件, 再提交该 DIO 消息进行进一步处理.
-
如果 DIO 消息格式错误, 则该 DIO 消息不符合进一步处理条件, 节点 MUST 静默丢弃它. (错误日志见第 18 节).
-
如果 DIO 消息的发送方是候选邻居集合的成员, 且该 DIO 消息格式正确, 则节点 MUST 处理该 DIO.
8.2.3.1. DIO 消息处理 (DIO Message Processing)
随着从候选邻居接收 DIO 消息, 按第 8.2 节所述的 DODAG 发现规则, 这些邻居可以被提升为 DODAG 父节点. 当节点将某个邻居放入 DODAG 父节点集合时, 该节点便通过新的 DODAG 父节点附接到 DODAG.
最受偏好的父节点应用于限制哪些其他节点可以成为 DODAG 父节点. DODAG 父节点集合中的某些节点可能具有小于或等于最受偏好的 DODAG 父节点的 Rank. (例如, 如果某个能量受限设备位于较小 Rank, 但根据优化目标应避免使用它, 从而导致更受偏好的父节点具有较大 Rank, 就可能出现这种情况.)
8.3. DIO 传输 (DIO Transmission)
RPL 节点使用 Trickle 计时器 [RFC6206] 传输 DIO. 如果来自 DAGRank 较小的发送方的 DIO 不会导致接收方的父节点集合, 首选父节点或 Rank 发生变化, 则相对于 Trickle 计时器而言, 该 DIO SHOULD 被视为一致.
以下分组和事件 MUST 被视为相对于 Trickle 计时器的不一致, 并导致 Trickle 计时器重置:
-
当节点在转发分组时检测到不一致, 如第 11.2 节详述.
-
当节点收到不带 Solicited Information 选项的组播 DIS 消息, 除非 DIS 标志限制此行为.
-
当节点收到带 Solicited Information 选项的组播 DIS, 且该节点匹配 Solicited Information 选项中的所有谓词, 除非 DIS 标志限制此行为.
-
当节点加入新的 DODAG Version (例如通过更新其 DODAGVersionNumber, 加入新的 RPL Instance 等).
注意, 此列表并非穷尽, 实现 MAY 将其他消息或事件视为不一致.
节点 SHOULD NOT 响应单播 DIS 消息而重置其 DIO Trickle 计时器. 当节点收到不带 Solicited Information 选项的单播 DIS 时, 它 MUST 以单播方式向发送方返回 DIO. 该 DIO MUST 包含 DODAG Configuration 选项. 当节点收到带 Solicited Information 选项的单播 DIS 消息, 并匹配该 Solicited Information 选项的谓词时, 它 MUST 以单播方式向发送方返回 DIO. 该单播 DIO MUST 包含 DODAG Configuration 选项. 因此, 节点 MAY 向潜在 DODAG 父节点传输单播 DIS 消息, 以探测 DODAG Configuration 和其他参数.
8.3.1. Trickle 参数 (Trickle Parameters)
Trickle 计时器的配置参数规定如下:
-
Imin: 从 DIO 消息中学习为 (2^DIOIntervalMin) ms. DIOIntervalMin 的默认值为 DEFAULT_DIO_INTERVAL_MIN.
-
Imax: 从 DIO 消息中学习为 DIOIntervalDoublings. DIOIntervalDoublings 的默认值为 DEFAULT_DIO_INTERVAL_DOUBLINGS.
-
k: 从 DIO 消息中学习为 DIORedundancyConstant. DIORedundancyConstant 的默认值为 DEFAULT_DIO_REDUNDANCY_CONSTANT. 在 RPL 中, 当 k 的值为 0x00 时, 它被视为 RPL 中的无限冗余常量, 即 Trickle 永不抑制消息.
8.4. DODAG 选择 (DODAG Selection)
DODAG 选择依赖于实现和 OF. 为限制不稳定移动, 在所有度量都相同的情况下, 节点 SHOULD 保持先前的选择. 此外, 至少在存在更稳定选择时, 节点 SHOULD 提供一种机制来过滤掉可用性被检测为波动的父节点.
当出于安全或其他原因无法连接到 grounded DODAG 或不宜连接到 grounded DODAG 时, 分散的 DODAG MAY 尽可能聚合为更大的 DODAG, 以允许 LLN 内的连通性.
节点在将候选邻居视为 DODAG 父节点之前, SHOULD 验证与该候选邻居之间存在双向连通性和足够的链路质量.
8.5. 作为叶节点运行 (Operation as a Leaf Node)
在某些情况下, RPL 节点可能只能作为叶节点附接到 DODAG. 这种情况的一个示例是节点不理解或不支持 (策略上不支持) RPL Instance 的 OF 或通告的度量/约束. 如第 18.6 节中关于策略函数所规定, 节点可以作为叶节点加入 DODAG, 也可以不加入 DODAG. 如第 18.5 节所述, 此时建议记录故障.
叶节点不会扩展 DODAG 连通性; 然而在某些情况下, 叶节点仍可能偶尔需要传输 DIO, 特别是当该叶节点并非一直作为叶节点运行且检测到不一致时.
作为叶节点运行的节点必须遵守以下规则:
-
它 MUST NOT 传输包含 DAG Metric Container 的 DIO.
-
它的 DIO MUST 通告 INFINITE_RANK 的 DAGRank.
-
它 MAY 抑制 DIO 传输, 除非 DIO 传输是由于转发分组时检测到不一致或响应单播 DIS 消息而触发; 在这些情况下, DIO 传输 MUST NOT 被抑制.
-
它 MAY 按第 9.2 节所述传输单播 DAO.
-
它 MAY 按第 9.10 节所述向 '1 hop' 邻域传输组播 DAO.
一种需要叶节点发送 DIO 的特殊情况是: 该叶节点曾经是另一个 DODAG 的成员, 而另一个节点基于旧拓扑假设转发消息, 从而触发不一致. 叶节点需要传输 DIO 来修复该不一致. 注意, 由于 LLN 的有损特性, 即使叶节点在成为叶节点之前曾通过在旧 DODAG 中通告 INFINITE_RANK 的 Rank 来乐观地毒化其路由, 该通告也可能已经丢失, 因此叶节点必须能够在稍后发送 DIO 以修复不一致.
在一般情况下, 叶节点 MUST NOT 将自身通告为路由器 (即发送 DIO).
8.6. 管理 Rank (Administrative Rank)
在某些情况下, 基于某些实现特定策略和节点属性, 将节点通告的 Rank 调整到 OF 计算值之外可能是有益的. 例如, 电池受限的节点除非别无选择, 否则应作为叶节点; 此时它可以增强 OF 规定的 Rank 计算, 以暴露一个被夸大的 Rank.