TinyOS LEEP详解

转自:http://qy.nwpu.info/?cat=11
LEEP详解

厚颜称本文为“LEEP详解”。话说古有《TCP/IP详解》,今有《CTP/LE详解》。

简介

LEEP协议主要用于估计节点间的单跳双向链路质量,以供路由协议计算路由。
TinyOS 2.x中实现的LEEP协议结合了广播LEEP帧的收发成功率和单播数据包的
发送成功率来计算单跳双向链路质量。

基本概念

入站链路质量:有节点对(A,B),以B作为参考结点,A向B发送的总包数为
total_in,其中B成功接收到的包数为success_in,从而有:

入站链路质量 = total_in / success_in

total_in的值即节点B成功收到的LEEP帧数。success_in的值可以通过A节点
广播的LEEP帧中的顺序号间接计算而得。LEEP帧中设有顺序号字段,节点A每
广播一次LEEP帧,它会将该字段加1,从而B节点只需要计算连续收到的LEEP帧
顺序号的差值就可以得到丢失的LEEP帧数。

入站链路质量也可以通过其它途径得到,比如LQI或RSSI之类的链路质量指示
器,不过这需要无线模块支持这类功能才行。

出站链路质量:节结点对(A,B),以B作为参考点,B向A发送包数为total_out,
其中A成功接收到包数为success_out,从而有:
出站链路质量 = total_out / success_out

由于LEEP帧是通过广播方式发送的,节点B无法得知节点A是否收到,从而
无法计算success_out。但B到A的出站链路质量即A到B的入站链路质量,要解决
该问题只有让A把它与B间的入站链路质量回馈给B,这其实就是LEEP帧的主要
功能之一。

TinyOS 2.x中用8位无符号整数表示出/入站链路质量。为了减少精度损失和
充分利用8位的空间,TinysOS在实际存储该值时对它扩大255倍。

双向链路质量
对于有向节点对(A,B),双向链路质量定义如下:
双向链路质量 = 入站链路质量 * 出站链路质量

因为本地干扰或噪声可以引起(A,B)和(B,A)链路质量不同,定义双向链路质量
就是为了将这种情况考虑在内。
EETX值
TinyOS 2.x中使用EETX(Extra Expected number of Transmission)值表示双向链路质量估计值。
在LEEP协议中使用的有两种EETX值:窗口EETX和累积EETX。窗口EETX是接收到的LEEP帧数或发送
的数据包数达到一个固定的窗口大小时,根据窗口中的收发成功率计算出的EETX。而累积EETX则
是本次窗口EETX和上次累积EETX加权相加的。根据指数移动平均的原理并让旧值的权重逐渐减少,
以适应链路质量的变化,是比较符合实际的统计方法。

LEEP协议对数据链路层的要求

有单跳源地址
提供广播地址
提供LEEP帧长度

其中,有单跳源地址的要求是为了让收到广播LEEP帧的节点确定更新邻居表中哪一项
的出站链路质量。现有节点的数据链路层一般都可以满足这3个要求。

LEEP帧结构

根据以上分析可以得知LEEP帧至少应具备一个顺序号和与若于邻居间结点的入站链路质量。
TinyOS 2.x中实现的LEEP帧结构如下:

     ----------------------------------------------------------
    | LEEP   | Payload | LI Entry | LI Entry | ... | LI Entry  |
    | Header |         |    1     |      2   |     |     n     |
     ----------------------------------------------------------

其中LEEP头部结构如下:

                    1
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |nentry | rsrvd |     seqno     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

各字段定义:
• nentry:尾部的LI项个数
• seqno:LEEP帧顺序号
• rsrvd:保留字段必须设为0

链路信息项
链路信息项格式如下:

                    1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |            node addr          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | link quality  |
    +-+-+-+-+-+-+-+-+

各字段定义:
node addr:邻居节点的链路层地址
• link quality:从与node id对应的节点到本节点的入站链路质量

实现

TinyOS 2.x中LEEP协议的实现在tos/lib/net/le目录下:

  1. LinkEstimator.h 头文件,包含了邻居表大小、邻居表项结构、LEEP帧头尾结构 以及LEEP协议中用到的常数的定义。

  2. LinkEstimator.nc 接口定义。包含了其它组件可以从LinkEstimator中调用的方法。 主要分为两类,一类用于获取链路质量,一类用于操作邻居表。

  3. LinkEstimatorC.nc 配置文件。它只说明LinkEstimator提供LinkEstimator接口。

  4. LinkEstimatorP.nc LEEP协议具体实现。

下面根据LinkEstimator.nc接口中定义的方法结合LinkEstimatorP.nc实现接口的源代码
来分析LEEP的工作原理。

估计链路质量的策略:

LEEP协议的目的是为了得到本节点到邻居节点的双向链路质量。实现中使用两种策略
综合来计算估计值。
根据信标帧的估计(B估计):
通过LEEP帧的信息来作EETX值的估计。
信标帧的发送:Send.send()方法,调用addLinkEstHeaderAndFooter()函数加LEEP
头尾。尾部存放的是本结节到邻居节点的链路质量表,如果LEEP帧中一次放不下
这个表,则在下次发LEEP帧时从第一个上次放不下的表项放起,以保证每个表项都有
被发送的机会是平等的。每发一个包都将帧中的顺序号字段加1。
发送的时机由LinkEstimator的使用者决定,如CTP。
信标帧的接收:SubReceive.receive(),处理LEEP头尾,更新邻居表。这些操作在函数
processReceiveMessage()中处理,该函数找到这个LEEP帧发送者对应的邻居表项,调用
updateNeighborEntryIdx()函数更新收到包数记数值和丢包数记数值。其中的丢包数就
是本次与上次LEEP帧中顺序号字段的差值。当收到的包数达到一个固定窗口的大小时,
调用updateNeighborTableEst()函数计算B估计值。
B估计值的计算:B估计值为

newEst = 255 * 接收到LEEP帧数 / 总帧数

根据动态移动平均原理更新入站链路质量:

inquality = (ALPHA*inquality + (10 - ALPHA)*newEst) / 10

TinyOS 2.x中设ALPHA值为9,因此每次更新时,旧值占9/10的权重,而新
值占1/10的权重。
计算双向链路质量:

窗口EETX = (255^2/(q_1*q_2) - 1) * 10  //这个看了源码才知道是inquality和outquality

更新累积EETX值:

累积EETX = (ALPHA*原eetx + (10-ALPHA)*newEst)/10

根据数据包的估计(D估计):
通过发送数据包的成功率来作EETX值的估计。
LinkEstimator并不能得知上层的数据包是否发送成功。因此它提供两个命令txAck()和txNoAck()
让上层组件调用。txAck()用于告知LinkEstimator数据包发送成功,它将对应通信邻居的成功传输
数据包计数值和总传输包计数值加1。当总传输包数达到一个固定窗口的大小时,调用updateDEETX()
函数计算窗口EETX值:

窗口EETX值 = (总包数 / 成功包数 - 1) * 10

更新累积EETX值:

累积EETX = (ALPHA*原eetx + (10-ALPHA)*newEst)/10

其它实现:

4bitle

参考
TEP124

你可能感兴趣的:(TinyOS,TinyOS)