标签:地址冲突
目前公司商用的协议栈程序是支持分节点地址可配置的,与zigbee2007pro有很大的不同,因此也产生了一些问题,特别严重的就是本篇所讲述的更换设备导致的现象。本篇将深入代码分析冲突检测及处理的流程,并给出修改方法。
测试使用两个设备模拟冲突场景,A设备先行入网,之后断电,B设备与A设备配置相同的短地址0x0140。当B设备上电后,便产生如下的冲突情景,会影响到正常通讯。
A设备的MAC地址为:E3909602004B1200
B设备的MAC地址为:CB909602004B1200
第102帧:B设备上电后发送的LinkStatus
第103帧:路由设备0x7DED检测到短地址冲突,发出了冲突包。
第104帧:路由设备0x2AFE检测到短地址冲突,发出了冲突包。
第105帧:路由设备0x206A检测到短地址冲突,发出了冲突包。
第106帧:B设备发出了地址声明包。(原生协议栈此时会发送随机地址)
第107帧:B设备转发路由设备0x7DED广播的冲突包。
第108帧:B设备发出了第二个地址声明包。(APS Counter=1)
第109帧:B设备发出了第三个地址声明包。(APS Counter=2)
第110帧:路由设备0x0141转发B设备发出的第一个冲突包,跳数减1。
第111帧:路由设备0x2AFE转发B设备发出的第一个冲突包,跳数减1。
第112帧:B设备发出了第五个地址声明包。(APS Counter=4)
这一小节是对第103帧到105帧的机制分析。
a.代码中有一处冲突检测,位于ZDO_ProcessDeviceAnnce中。
// If address conflict is detected, no need to update the address manager
if ( NLME_CheckNewAddrSet( Annce.nwkAddr, Annce.extAddr )== ZFailure )
{
return;
}
该函数说明中有如下明确说明:
* If ZFailure is returned, the stack already sent out an address conflict
* route error - already called NLME_ReportAddressConflict().
b.但是我在屏蔽掉该接口后,发现路由设备还是会发出冲突包,说明ZStack内部还有一些调用。从抓包来看,冲突包是在问题设备发了LinkStatus之后。网上找到如下资料,说LinkStatus与关联表存在对应关系。所以ZStack在解析LinkStatus时应该会更新关联表,可以推断,很有可能是在这时识别到地址冲突。
类型associated_devices_t中,有一个age域,当关联表的维护者收到一条来自该短地址的Link Status消息,就会重置该域。
全功能节点(路由器)默认为15秒发送一次Link Status,那么父节点就可以通过age域来判断它的全功能子节点是否还连接在网络中。
目前对于LinkStatus的解析,ZStack并未开放出对应的代码。
这一小节是对第106帧的分析。
该函数处理位于ZDApp_ProcessNetworkJoin函数的最底下。
// Assume from address conflict
if ( _NIB.nwkAddrAlloc == NWK_ADDRESSING_STOCHASTIC )
{
// Notify the network
ZDApp_AnnounceNewAddress();
// Notify apps
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
}
这是原生协议栈在接收冲突包后的处理。ZDAPP_AnnounceNewAddress会声明一个随机的地址,并且通知应用任务调用状态改变的事件。
我们为了保证配置的节点地址不被切到随机,此处将ZDAPP_AnnounceNewAddress替换成了自己的声明函数。
由于无数的声明包不断发出,致使网络异常拥堵,影响到了正常数据传输。
本次修改还是从根源下手,即第三点的1小节,其他路由设备检测冲突的处理要做一定的放行。从对该小节的代码分析,我们知道此处涉及两个地方,第一处地方由于未开放代码,目前暂无办法,只能对第二处地方ZDO_ProcessDeviceAnnce进行修改。
原生协议栈的做法是:先判断设备声明是否有冲突,有冲突直接丢弃该声明包,无冲突才会将该声明地址更新到地址管理数据库中。
这里的措施就是尽量让新的设备声明能够更新到各个路由设备的地址管理数据库中,保证一次声明过后就以这次的为准,以后不再产生冲突包。修改如下:
1.屏蔽NLME_CheckNewAddrSet这个return处理
2.删除旧的关联表项
分析了TI在该函数的详细流程,发现TI的ZIGBEE_STOCHASTIC_ADDRESSING是以短地址唯一为前提,他们处理的是同一个设备更换短地址的情况。与我们同一短地址但不同设备的方式有所不同,因此在函数中还需要针对性的修改。
if ( AddrMgrEntryLookupNwk( &addrEntry ) )
{
AssocRemove(addrEntry.extAddr);
ZDApp_NVUpdate();
AddrMgrExtAddrSet( addrEntry.extAddr, Annce.extAddr );
AddrMgrEntryUpdate( &addrEntry );
}
经过实际验证,发现路由设备更新了该修改之后,可以解决问题。
路由设备在接收一次新声明后便能更新关联表,看到关联表项对应的短地址只有一项,而原来会有两项具有相同的短地址。实际抓包发现不再一直狂发声明包。
标签:地址冲突
原文地址:http://blog.csdn.net/sadshen/article/details/44837297