3.协议综述
本节目的是本着[RFC4101]的精神描述RPL。协议细节可以后面章节找到。
3.1 拓扑结构
本节介绍可形成的基本RPL拓扑结构,及构造这些拓扑结构的规则,例如,指导DODAG形成的规则。
3.1.1 构造拓扑结构
LLNs,如无线网络,通常不会象点对点导线那样强制形成拓扑结构,所以RPL不得不发现链路并有节制地选择对端。
很多情况下,由于第2层仅有部分范围重叠,RPL形成了非传递/非广播多路访问(NBMA)网络拓扑结构,并在它的基础上计算路由。
RPL路由优化与一个或多个根之间的流量发送和接收,这些根作为拓扑结构的汇聚点。因此,RPL组织如下拓扑结构:一个被划分为数个DODAG的DAG,每个DODAG对应一个汇聚点。如果DAG有多个根,可以预期,这些根会象中继链路那样通过公共主干网联合。
3.1.2 RPL标识符
RPL使用四个值来标识和维护一个拓扑结构:
- 第一个是RPLInstanceID。RPLInstanceID标识了一组由单个或多个DODAG组成的DAG。一个网络可能拥有多个RPLInstanceID,它们中的每一个都定义了独立的一组DODAG,它们可针对不同的目标函数(OF)和/或应用进行优化。由一个RPLInstanceID标识的一组DODAG被称为RPL实例。同一RPL实例中的所有DODAG使用相同的OF。
- 第二个是DODAGID。DODAGID的使用范围仅限于RPL实例内。网络中联合使用RPLInstanceID和 DODAGID可唯一标识一个DODAG。一个RPL实例可拥有多个DODAG,它们中的每一个拥有唯一的DODAGID。
- 第三个是DODAGVersionNumber。DODAGVersionNumber的使用范围仅限于DODAG内。 DODAG有时通过DODAG根进行重构,并递增其DODAGVersionNumber。联合使用RPLInstanceID、DODAGID和 DODAGVersionNumber可以唯一标识一个DODAG版本。
- 第四个是Rank。Rank的使用范围仅限于DODAG版本内。Rank在DODAG版本基础上建立一个偏序,定义单个节点相对DODAG根的位置。
3.1.3 实例,DODAGs和DODAG版本
一个RPL实例包含一个或多个DODAG根。一个RPL实例可为给定的目的地前缀提供路由,通过DODAG根或DODAG内的替代路径到达目的地。这些根可独立运行,也可在网络上协同工作,无需像LLN那样受到限制。
RPL实例由如下东西组成:
- 仅有一个根的单个DODAG。
例如,在智能家居应用中,为使延迟最小化,DODAG将集中照明控制器作为唯一的根。
- 多个拥有独立根(不同的DODAGID)的相互间不协调的DODAG
例如,在城市数据采集应用中的多个数据采集点间,由于没有合适的连接而无法协调一致,或者以多DODAG结构为手段来动态、自主地分割网络。
- 携带虚拟根的单个DODAG在主干网络中协调LLN汇聚点(使用相同的DODAGID)。
例如,运行于可靠的传输链路上的多个边界路由 。在一个支持IPv6低功耗无线个域网(6LoWPAN)的应用中,它们有能力作为相同DODAG汇聚点的逻辑等价接口。
- 上述组合可适用于某些应用场景
每个RPL包都与一个特定RPLInstanceID关联(见11.2节),也就是与RPL实例(见第5节)关联。RPLInstanceID和应用流量类型或服务之间映射的提供和自动发现不在本文讨论范围内(将来会在配套文档中定义)。
图1展示了一个RPL实例,它包含三个DODAG,根分别为R1、R2、R3。每个DODAG根公告相同的RPLInstanceID。图中线段表示双亲和孩子间的连接。
图2展示了DODAGVersionNumber的递增是如何导致新DODAG版本产生的。此图说明了DODAVersionNumber值增加的结果是一个不同的DODAG拓扑。注意,新的DODAG版本并不一定会带来不同的DODAG拓扑。某些特定的拓扑改变才需要新的DODAG版本,本规范稍后会对此进行讨论。
需要注意,此例中的树型结构非常简单,然而当连接支持时,DODAG结构是允许每个节点拥有多个双亲的。
3.2 上行路由和DODAG构造
RPL提供向上到DODAG根的路由时,会根据目标函数(OF)优化DODAG形成。RPL节点通过DODAG信息对象(DIO)来构造和维护这些DODAG。
3.2.1 目标函数(OF)
OF定义了在RPL实例中RPL节点是如何选择和优化路由的。OF在DIO配置选项中通过Objective Code Point(OCP)来进行标识。OF定义了节点是如何转化为一个或多个度量和约束的([RFC6551]中定义),转化成的值叫Rank,它表示节点到DODAG根的大概距离。OF还定义了节点是如何选择双亲的。列详细的描述可参考14节或[RFC6551]、[RFC6552]规范文档以及关相配套文档。
3.2.2 DODAG修复
DODAG根通过递增DODAGVersionNumer来发起一个全局修复操作,从而产生一个新的DODAG版本。在新DODAG版本中,那些不受旧版本Rank的限制节点可以选择新的位置。
RPL还支持可用于DODAG版本内的本地修复机制。当通过DODAG根策略进行配置和控制时,DIO消息会指定必要的参数。
3.2.3 安全
RPL支持信息的保密和完整。当链路层机制可用且适合,则使用它,否则RPL使用自己的机制。RPL拥有三种基础安全模式。
第一种叫“unsecured”(无保障)模式,RPL控制消息在发送时不附带任何安全机制。无保障模式并不意味着RPL网络是不安全的,它可能使用了现有的安全原语(如链路层安全)来满足应用的安全需求。
第二种叫“preinstalled”(预设)模式,节点在加入RPL实例时,拥有预设的密钥以使得它可以处理和产生安全的RPL消息。
第三种叫“authentiated”(认证)模式,在认证模式下,节点和预设模式一样拥有预设密钥,但预设密钥仅能在以叶子节点形式加入RPL实例时使用。以路由的形式加入认证模式的RPL实例需要获取一个来自认证机构的密钥。获取密钥的过程超出本规范的范围。注意,本规范仅仅没有对RPL实现是如何安全运行于认证模式下提供足够详细的描述。关于这一点,有必要在将来的配套规范中对于节点如何获取和申请认证材料(如密钥、证书)和从哪获取那些材料进行详述(请参阅10.3节)。
3.2.4 接地和浮动的DODAG
DODAG可以是接地的或浮动的:DODAG根公告是哪一种情况呢?一个接地的DODAG为那些满足应用定义目标需求的主机提供连接。一个浮动的DODAG没有预期要满足目标,在大多数情况下,它仅提供DODAG内到节点的路由。例如,浮动的DODAG可用于在修复期间保持互连。
3.2.5 本地DODAG
在LLN中,当目的地为DODAG根时,RPL节点可以通过构建本地DODAG来优化到此根的路由。不同于全局DAG,可能是由多个DODAG组成的,本地DAG有且仅有一个DODAG,因此只有一个DODAG根。本地DODAG可以在需要时再构造。
3.2.6 管理偏好
实现/布署可以通过管理偏好来决定哪些DODAG根应当优先于其它根使用。管理偏好提供了控制流量和设计DODAG构成的途径,从而更好地支持应用条件和需求。
3.2.7 数据通路验证和回路探测
LLNs的低功耗和有损性质促使RPL的按需回路探测必须使用额外数据包。因为数据流量的偶发性,维护路由拓扑时时随物理拓扑而变化会导致能量的浪费。在物理连接中,LLNs通常呈现瞬间且无碍流量的变化,但从控制平面密切跟踪这些变化代价高昂。连接的瞬间及偶发变化无需RPL处理,直到有数据被发送。RPL在这方面的设计借鉴了现存高频使用的LLN协议以及大量证明其功效的实验和布署。
RPL分组信息是跟数据包一起传送的,它包含了发送者的Rank信息。数据包的路由决策(上行或下行)和两节点的Rank关系的不一致预示着有可能出现回路。如果收到这样的数据所,节点会发起本地修复操作。
例如,如果节点收到一个标示为上行的数据包,但包中记录的发送者比接收者的Rank更低,此时接收者可以终止数据包的继续上行,此时的DODAG是不一致的。
3.2.8 分布式算法操作
以下是有关DODAG构造的分布式算法的高层级概述:
- 某些节点通过相关的DODAG配置,被设定为DODAG根。
- 节点通过发送链路本地多播DIO信息给所有RPL节点以公告它们的存在、与DODAG的隶属关系、路由开销以及相关度量。
- 节点监听DIO并通过它们的信息以加入一个新的DODAG(进而选择DODAG双亲),或按照指定OF和邻居的Rank保持当前DODAG。
- 节点通过DODAG版本中的双亲,为DIO消息所指定的目的地提供路由表条目。节点决定加入某个 DODAG,为默认路由以及数个与实例关联的其它外部路由提供一个或多个DODAG双亲作为下一跳。
3.3 下行路由和目的地公告
RPL使用目的地公告对象(DAO)消息来建立下行路由。DIO消息对应用来说是一个可选项,它需要点对多点(P2MP)或点对点(P2P)通信的支持。RPL支持两种下行流量模式:存储式(完全状态)或非存储式(完全源路由)(见第9节)。任何给定的RPL实例不是存储式就是非存储式。在这两种情况下,P2P数据包都是先上传至DODAG根,然后下行至最终目的地(除非目的地在上行路由中)。在非存储模式下,数据包在下行前将遍访到根的所有路径。而在存储模式下,数据包在到达DODAG根之前可通过源和目的地的公共祖先直接下行至目的地。
截止撰写本规范为止,还没有应用同时支持运行存储和非存储模式。大多应用只是希望要么支持无下行路由的非存储模式,要么支持存储模式。其它操作模式,如hybrid的混合了存储和非存储模式超出了本规范的范围,也许会在其它配套文档中描述。
本规范描述在P2P通信支持下的基础操作模式。注意,更多优化的P2P解决方案将在配套文档中描述。
3.4 本地DODAG路由发现
作为可选项,一个RPL网络可支持LLN中到指定目的地DODAG的按需发现。此类本地DODAG的行为和全局DODAG稍有不同:它们通过联合使用DODAGID和RPLInstanceID来唯一定义,RPLInstanceID指示了一个DODAG是否为本地DODAG。
3.5 Rank特性
Rank是一个DODAG版本内某节点位置的标量表示。Rank用于避免和探测回路,因而必定展现出某些特性。Rank的精确计算留目标函数(OF)完成。即便OF已经完成某些特定计算,Rand还得自己实现通用属性。
尤其,当DODAG版本靠近DODAG目的地时,节点的Rank必须单调减少。这种情况下,可将Rank当成位置的标量表现或DODAG版本内节点的半径。
OF如何计算Rank的细节超出本规范范围,尽管这种计算依赖于如双亲、链路度量、节点度量和节点配置和策略等。请参考14节获取更多信息。
虽然Rank值源于路径度量并受它影响,但Rank并非路径开销。Rank拥有自己的不属于上述所有度量的特性:
Type(类型):Rank是一个抽象的数值。
Fuction(功能):Rank是DODAG版本中,节点与邻居相对位置的表达式,它不一定是到根的距离或路径开销的完美表示或正确表达式。
Stability(稳定性):Rank的稳定性决定了路由拓扑的稳定性。推荐使用一些抑制或过滤措施以保持拓扑的稳定,因此Rank没有必要象链路或节点度量那样快速改变。一个新的DODAG版本应成为调和差异的好机会,这些差异可能是在DODAG版本内的度量和Rank之间,随着时间的推移而形成的。
Properties(特性):Rank以严格单调的方式递增,它可用于校验靠近或离开根的行进。度量像带宽或抖动一样,不一定会呈现这些特性。
Abstrace(抽象):Rank没有物理单位,而是每跳一定范围的增量,每个增量的分配由OF来决定。
3.5.1 Rank比较(DAGRank())
Rank可被当成定点值,整数部分和小数部分之间的小数点位置由MinHopRankIncrease决定。MinHopRankIncrease是一个节点和它任意双亲间的最小Rank增量。MinHopRankIncrease由DODAG提供。MinHopRankIncrease在跳数开销精确度和网络支持的最大跳数间进行权衡。例如,一个非常大的MinHopRankIncrease可以精确描述给定跳数对Rank的影响,但它无法支持太多的跳数。
当目标函数(OF)计算Rank时,OF将使用整个Rank值(也就是16bit)进行运算。当Rank用于对比,例如用于决定决定与双亲间的关系或回路探测时,将使用Rank的整数部分。Rank的整数部分使用下面的DAGRank()宏计算得出,其中floor(x)函数求解小于等于x的最大整数:
DAGRank(rank) = floor(rank/MinHopRankIncrease)
举例来说,如果16bit的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的计算由LLN任意两相邻节点M和N的以下属性得出:
DAGRank(M) < DAGRank(N):
这种情况下,M的位置比N离DODAG根更近。此时节点M可安全地作为节点N的双亲,不会有任何回路的风险。进而,节点N的双亲集中的所有双亲的Rank值必须小于DAGRank(N)。也就是说节点N所呈现的Rank必须大于它的双亲所呈现出的Rank。
DAGRank(M) = DAGRank(N):
这种情况说明DODAG中,M和N相对于根的位置相近或完全相等。路由通过具有相同Rank的节点有可能导致路由回路(即,那个节点在选择路由的过程中通过了一个具有相同Rank值的节点)。
DAGRank(M) > DAGRank(N):
这种情况下,M的位置比N离DODAG根更远。进而节点M可能位于节点N的子DODAG内。如果节点N选择节点M作为双亲,会存在回路的风险。
例如,当OF极力减小的度量是EXT或延迟时,可通过密切跟踪EXT的方式业计算Rank。或采用适合DODAG内正在使用的OF的更复杂的方法计算Rank。
3.6 RPL使用的路由度量和约束
路由协议通过路由度量计算最短路径。诸如IS-IS(
[RFC5120])和OSPF(
[RFC4915])等内部网关协议(IGPs)使用的是静态链路度量。这些链路度量可以简单反映代宽,也可按照定义不同链路特征的几种度量的多项式函数计算而来。一些路由协议支持多种度量:在决大多数情况下,每种(子)拓扑使用一种度量。少数情况下,第二度量可在多重等价路径(Equal Cost Multiple Path:ECMP)中用于最高仲裁。多重度量的最优化被称作NP完全问题(NP-complete problem),被一些集中式路径计算引擎所支持。
(这里解释一下Equal Cost Multiple Path:到达同一目的地可以有多条等价路径存在,我们称之为ECMP,但对于一个目的地只能寻找一条路径。当存在多条满足基本条件的路径时,寻找出其中的一条路径就叫“最高仲裁”)
相比之下,LLNs需要同时支持静态和动态度量。与此同时,链路度量和节点度量都需要。就RPL而言,只定义一种度量乃至一种复合度量都是不够的,它需要满足所有使用情形。
此外,RPL支持基础约束的路由,此种约束适用于链路和节点。如果链路或节点并不满足所需的约束,它将从候选邻居集中被去除,从而产生受约束的最短路径。
一个目标函数(OF)指定了用于计算(约束)路径的目标。进而,可通过配置节点以支持一系列度量和约束并依照DIO消息公告里的度量和约束信息在DODAG中选择它们的双亲。上行和下行数据流度量的单独还是合并公告取决于OF和度量。当它们单独公告时,可能会出现DIO双亲集与DAO双亲集不一样的情况(单播DAO消息的发送目标是DAO的双亲节点)。然而,它们都是跟Rank计算规则有关的双亲。
OF还被RPL用于从路由度量和约束中解耦。鉴于OF制定DODAG双亲选择、负载均衡等规则,使用度量和/或约束集合。因此DIO消息中的DAG约束选项所携带的信息些决定了首选路径。
支持链路/节点的约束和度量集在
[RFC6551]中有详述。
例1:最短路径:路径提供端到端的最短延时。
例2:最短约束路径:路径不通过电池供电节点且路径可靠性最优化。
3.7 回路避免
当拓扑发生改变时,RPL努力避免形成回路。当回路形成时,RPL会使用基于Rank的数据路径校检机制来进行探测(评见第11节)。实践中,这表示RPL既不保证路径选择的无回路,也不保证严格的延迟收敛时间,但只要RPL被使用,就可以探测和修复回路。RPL使用这种回路探测机制以确保数据包在DODAG版本内前行,并在必要时触发修复。
3.7.1 贪婪和不稳定
在DODAG版本中,当节点试图向更深层移动(Rank变大)以增加双亲集尺寸或提高其它度量,此时节点是贪婪的。一旦节点已经加入DODAG版本,为防止DODAG版本的不稳定,RPL将禁止某些行为,包括贪婪。
设想某节点愿意从它自己的sub-DODAG中的一个节点(一般情况下,这个节点更深)那接收和处理DIO消息。这种情况下,当两个或更多节点持续尝试在DODAG版本内移动以相互优化,形成反馈回路的可能性是存在的。有时,这将导致不稳定,正是基于此原因,当节点处理来自更深层节点的DIO信息时,将被RPL限制在某种本地修复的形式。此方法创造了一个“视界线”,使得节点的行为无法越过此界限而受影响进入到不稳定状态,此种行为可能来自节点的sub-DODAG内。
event horizon:视界线,天文学术语。指黑洞的边界。在此边界以内的光无法逃离。
3.7.1.1 用例:贪婪的双亲选择和不稳定
上图描述了三个不同构造的DODAG。三个DODAG中,节点A到B和C间都存在可用链路。
- 在图3-1中,节点A是节点B和C的双亲。
- 在图3-2中,节点A是节点B和C的双亲,节点B也是节点C的双亲。
- 在图3-3中,节点A是节点B和C的双亲,节点C也是节点B的双亲。
如果一个RPL节点过于贪婪,除了最优先考虑的双亲外,它还会试图优化更多的其它双亲,从而导致不稳定。考虑图3-1所示的DODAG,节点B和C可能最喜欢A作为它们的双亲,但当它们运行于贪婪模式下,就会设法优化出两个双亲。
- 将图3-1设为初始状态
- 假设节点C首先离开DODAG,然后以更低的Rank重新加入,并将节点A和B作为其双亲(图3-2所示)。现在节点C比节点A和B更深,并满足于拥有两个双亲。
- 假设节点B在贪婪模式下,愿意接收和处理节点C的DIO消息(违反了RPL规则),于是节点B离开DODAG并以更低的Rank重新加入,并将节点A和C作为其双亲。现在节点B比节点A和C更深,并满足于拥有两个双亲。
- 接下来,节点C也是贪婪的,它将离开并重新加入成为更深节点,以再次获得两个双亲并拥有比它们列低的Rank。
- 然后,节点B再一次离开、加入以变得更深,并获得两个双亲。
- 再一次,节点C离开、加入、变得更深。
- 如此重复,DODAG将在图3-2和图3-3间来回震荡,直到节点计数变成无穷大并再次重启循环。
- 可通过RPL中的以下机制防止出现此种循环:
- 节点B和C保持Rank值不变,只要此Rank可以满足于依附它们最优双亲(A),且不再寻找任何更深的(错误的)替代双亲(节点不贪婪)。
- 节点B和C不处理来自更深节点的DIO消息(因为这样的节点可能在它自己的sub-DODAG内)。
此机制在8.2.2.4中会作进一步描述。
3.7.2 DODAG回路
当节点离开DODAG然后又附着到之前sub-DODAG内的设备时,可能会形成DODAG回路。这种情形在丢失DIO消息时特别容易发生。严格使用DODAGVersionNumber可排除此类回路,但此类回路在使用某些本地修复机制时会偶尔碰到。
例如,考虑以下情况,本地修复机制允许一个节点从DODAG分离,并公告值为INFINITE_RANK的Rank(为了毒化它的路由/通知它的sub-DODAG),然后再次附着回DODAG。在某些情况下,节点可能会附着到它之前的sub-DODAG内,导致了一个DODAG回路,因为INFINITE_RANK公告在LLN环境中丢失后会导致毒化失败。(这种情况下,基于Rank的数据路径校验机制会最终检测并触发回路的修复)
路由中毒/路由毒化(route poisoning): 做某种设置,来表示该网络不可达。
3.7.3 DAO回路
当双亲存在根据从孩子那接收和处理的DAO消息设置的路由, 而孩子随后清除了相关的DAO状态,此时可能会产生DAO回路。在No-Path(一种DAO消息,它会导致之前宣告的前缀无效,见6.4.3节)被遗漏,并一直持续到所有状态被清除时,会发生此种回路。RPL包含一种可选机制来确认DAO消息,它可以减少单个DAO消息被溃漏的几率。RPL带有回路探测机制,它减轻DAO回路所带来的影响并触发回路维修(见11.2.2.3节)。