很多人可能遇到类似问题,CC2530/CC2538 ZNP工程,已经定义了宏TP2_LEGACY_ZC,用于协调器兼容旧zigbee设备(1.2协议)。复现步骤,网络内第一个ZR直接可以入网,第二个ZR通过中间ZR也可以入网,有Update Device之后ZC立马回复Tunnel Transport Key,可以入网,第三个设备通过中间ZR基本无法入网,中间ZR给ZC发送了Update Device,没有任何反应,导致入网失败,之后多次尝试,依旧失败。
ubiqua抓包分析后,大概能看到如下现象
解决方案
经过对bdb.c和ZDSecMgr.c代码的分析,发现了bug,修改如下位置
/****************************************************************************
* @fn bdb_TCProcessJoiningList
*
* @brief Process the timer to handle the joining devices if the TC link
* key is mandatory for all devices
*
* @param none
*
* @return none
*/voidbdb_TCProcessJoiningList(void){bdb_joiningDeviceList_t* tempJoiningDescNode;if(bdb_joiningDeviceList){
tempJoiningDescNode = bdb_joiningDeviceList;while(tempJoiningDescNode){if(tempJoiningDescNode->NodeJoinTimeout){
tempJoiningDescNode->NodeJoinTimeout--;}if(tempJoiningDescNode->NodeJoinTimeout ==0){//Check if the key exchange is requiredif(bdb_doTrustCenterRequireKeyExchange()){
AddrMgrEntry_t entry;
entry.user = ADDRMGR_USER_DEFAULT;osal_memcpy(entry.extAddr,tempJoiningDescNode->bdbJoiningNodeEui64, Z_EXTADDR_LEN);if(AddrMgrEntryLookupExt(&entry)){ZDSecMgrAPSRemove(entry.nwkAddr,entry.extAddr,tempJoiningDescNode->parentAddr);}//Expired device either is legacy device not using the TCLK entry or got//removed from the network because of timeout, eitherway it is not using//TCLK entry neither the Security user in the address manager, so free the entry//in both tables.
uint16 keyNvIndex;
uint16 index;
APSME_TCLKDevEntry_t TCLKDevEntry;
uint8 found;//Remove the entry in address managerZDSecMgrAddrClear(tempJoiningDescNode->bdbJoiningNodeEui64);//search for the entry in the TCLK table
keyNvIndex =APSME_SearchTCLinkKeyEntry(tempJoiningDescNode->bdbJoiningNodeEui64,&found,NULL);//If found, erase it.if(found == TRUE){osal_memset(&TCLKDevEntry,0,sizeof(APSME_TCLKDevEntry_t));
TCLKDevEntry.keyAttributes = ZG_DEFAULT_KEY;//Increase the shift by one. Validate the maximum shift of the seed which is 15
index = keyNvIndex - ZCD_NV_TCLK_TABLE_START;
TCLinkKeyFrmCntr[index].rxFrmCntr =0;
TCLinkKeyFrmCntr[index].txFrmCntr =0;//Update the entryosal_nv_write(keyNvIndex,0,sizeof(APSME_TCLKDevEntry_t),&TCLKDevEntry );}if(pfnTCLinkKeyExchangeProcessCB){bdb_TCLinkKeyExchProcess_t bdb_TCLinkKeyExchProcess;osal_memcpy(bdb_TCLinkKeyExchProcess.extAddr,tempJoiningDescNode->bdbJoiningNodeEui64, Z_EXTADDR_LEN);
bdb_TCLinkKeyExchProcess.status = BDB_TC_LK_EXCH_PROCESS_EXCH_FAIL;bdb_SendMsg(bdb_TaskID, BDB_TC_LINK_KEY_EXCHANGE_PROCESS, BDB_MSG_EVENT_SUCCESS,sizeof(bdb_TCLinkKeyExchProcess_t),(uint8*)&bdb_TCLinkKeyExchProcess);}}//Free the device from the listbdb_TCJoiningDeviceFree(tempJoiningDescNode);}
tempJoiningDescNode = tempJoiningDescNode->nextDev;}}//we are done with the listif(bdb_joiningDeviceList ==NULL){osal_stop_timerEx(bdb_TaskID,BDB_TC_JOIN_TIMEOUT);}}