TI CC2530 CC2538 zigbee source routing机制的有效利用(加快单播指令的发送,解决单播丢包问题)

  • 很多人开始对于source routing是十分迷惑的,加之TI的FAE很多时候人力有限,所以会产生很多疑问,既然都有路由表了,怎么还会有个叫做source routing,这些东西不是凭空产生的,都是有产生的历史背景的。
  • 通过对Z-Stack 3.0 Developer’s Guide.pdf文档的阅读,我们发现,source routing作为zigbee PRO协议栈的一个新特性,是many-to-one路由机制的一部分,source routing的唯一作用就是协调器(在这里也可以称为concentrator,中文叫网关,或者英文名coordinator)能以最优路径发送数据给其他router或者end device。
  • 即使你按照swra427c.pdf(AN123)文档Z-Stack Knobs配置使能了many to one,但是默认也不会使用到source routing。
  • 一般情况下,coordinator和其他router一样,也有一张路由表,记录了到达多个router的路由信息,而且会AODV动态变化,协议栈自带的所有sample工程,都是在zcl.c里面调用zcl_SendCommand发送控制指令,最终都会调用AF_DataRequest发送控制指令给其他节点,但此时根本没有利用到source routing,不信可以用ubiqua分析一下数据包,就会发现Source Route Included是No,而不是Yes,这就解释了为什么很多人提到coordinator给多个节点单播发送控制指令的时候,虽然有间隔发送,但有时候也会出现莫名奇妙丢包的问题,因为协议栈此时可能没有路由路径,所以发了AODV,等路由路径建立了,此时控制指令也不会再次重发,自然就产生了丢包。
  • 一般网络建立之后物理位置就固定下来了,能否利用source routing来发送数据呢,这样就不存在路由表超时无效的问题,可以加快发送数据。即使在协调器上电不久,不需要重建路由表,都可以利用上层网关已存储的source route加快数据的发送。

下图可以看出,并没有利用source routing
没有用到source routing

对于many to one路由机制有两个点需要注意,无非就是:
1. coordinator发送数据给其他节点,类似于通过网关发送控制指令控制LED灯或者窗帘;
2. 其他节点发送数据给coordinator,类似于做为zigbee传感器数据采集节点。

  • 这就是所谓的many to one,多对一,或者说一对多,前提他们是如何知道到达彼此的路径的呢?
  • 首先,其他节点是如何知道到达coordinator的路径?不是一般意义上的大家都死命在那发送AODV路由请求,这样就会导致网络严重拥塞,严重丢包,最后谁也发现不了谁。为了解决这个问题,coordinator会定时发送route request(RREQ)广播,这个时间由CONCENTRATOR_DISCOVERY_TIME这个宏来控制,其他节点收到这个广播包后,就知道自己到达coordinator的路径了,当然也可以发送单播,只给某一个节点发送route request,请参考 5.4.2 Many-to-One Route Discovery 。例如下图,0x1234和0x5678节点收到route request之后就知道到达coordinator(0x0000)的路由路径了。
    many to one route discovery

  • 其次,coordinator是如何知道到达其他节点的路由路径呢? 肯定是让其他节点主动报告自己的位置,不能是人家coordinator主动问你在哪里,对吧。协议栈里面也是这么干的,我们接下来往下看,参考 5.4.3 Route Record Command

  • 其他节点会不定时的给coordinator发送route record(RREC)指令,这个指令里面就包含了自己到达coordinator的relay转发路径,这样,coordinator一旦收到route record之后,就知道自己到达这个节点的最优路径了。

  • 例如下图,0x9DF5节点给0x0000发送了一条route record指令,就包含了两个负责relay的节点,最终coordinator就知道这样的路由路径:0x9DF5->0x1828->0x5E89->0x0000
    route record

  • 很多人会以为协议栈会自己管理source routing,在你需要发送控制指令给某个节点的时候,协议栈会自动帮你加上relay列表,以实现最优路径发送给某个节点。

  • 遗憾的是,协议栈并不会这样做,这一点guide文档并没有提及。 coordinator自己收到了route record,也只是把短地址、路由列表relayList和路由数量relayCount解析出来,最后调用ZDO_SrcRtgIndCB函数把这三个参数丢给上层APP,自己就不管了( 具体传递参数请参考ZDO_SrcRtgIndCB的代码,这个函数在非公开的代码AllDevice.a库里面被调用 )。
  • 既然协议栈自己并不会管理source routing,那么只能上层APP自己管理收到的relayList,并在发送控制指令的时候根据目的节点的短地址,要不要给出relayList了,如果给出,那么就按照relayList的路径去发送,否则就按照协议栈自己的一般路由表去找目的节点。
  • AF_DataRequestSrcRtg这个函数就是负责在发送控制指令前,添加relayList的,该函数最终也会调用AF_DataRequest实现控制指令的发送,但是在这之前,它还有一个动作就是调用RTG_AddSrcRtgEntry_Guaranteed把relayList加入到source routing table里面,让协议栈按照这个relay路径去发送,指令就能很快到达目的节点,只有不能到达的时候才会AODV。
  • 我们自己在上层APP里面使用了数据库,一旦收到route record,则把短地址和对应的relayList以及relayCount都插入到数据库中,在需要单播发送控制指令的时候,再用短地址去数据库中查找是否有source routing,如果有则调用AF_DataRequestSrcRtg,否则调用AF_DataRequest进行发送。

结语

  • 测试On/Off:Off关灯指令,是否通过了source routing发送,我们看到,的确是通过了source routing提供的路径发送的,且没有提示source route failure,说明发送成功,中间经过了0x42B3、0x1828、0x5E89三个节点进行了转发,由于我们没有在0x42B3附近进行抓包,所以左边Traffic View里面的On/Off:Off只能显示了2行,否则一定显示的是3行转发信息。
    这里写图片描述

  • 通过使用source routing,协调器能够快速发送单播指令给其他节点,效率很高,再也不会出现单播控制指令有时候能控制成功,有时候总是控制失败的问题

注意事项

  • 需要注意的是,在收到route record以及发送单播的时候,要原封不动的给出relayList,不要做逆序。比如收到0x8836发来的route record的时候,relayList方向是这样的:0x42B3->0x1828->0x5E89,那么发送单播控制指令的时候,也要同样给出0x42B3->0x1828->0x5E89,而不是0x5E89->0x1828->0x42B3,否则就会提示source route failure错误。
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页