CC2530/CC2538 TI zigbee协调器只有Update Device入网困难bug

  • 目前zigbee领域最稳定的方案仍然是TI的CC25xx方案,没有之一。
  • 很多人可能遇到类似问题,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
*/
void bdb_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 required
        if(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 manager
          ZDSecMgrAddrClear(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 entry
            osal_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 list
        bdb_TCJoiningDeviceFree(tempJoiningDescNode);
      }
      tempJoiningDescNode = tempJoiningDescNode->nextDev;
    }
  }

  //we are done with the list
  if(bdb_joiningDeviceList == NULL)
  {
    osal_stop_timerEx(bdb_TaskID,BDB_TC_JOIN_TIMEOUT);
  }
}

技术分析

  • 在ZDSecMgrDeviceJoinDirect和ZDSecMgrUpdateDeviceInd回调函数里面都调用了bdb_TCAddJoiningDevice函数,前者是处理直接入网,就是设备没有经过中间ZR直接加入ZC,后者是处理间接入网,也就是当ZC收到中间ZR发来的Update Device后进行的处理。
  • 结合bdb_TCAddJoiningDevice函数的注释,注释意思是该函数用于跟踪入网设备是否有请求key(也就是根据ZC返回的Node Descriptor Response里面的Stack Compliance Revision标志,zigbee 3.0设备入网必须主动发送Request Key,这里请求的key类型是TCLK,对应的key类型是宏KEY_TYPE_TC_LINK),zigbee 3.0设备正常情况下,入网都会发送Request Key,但zigbee 1.2设备加入zigbee 3.0的ZC,肯定不会有Request Key步骤,ZC为了兼容zigbee 1.2设备,既然在编译阶段已经定义了宏TP2_LEGACY_ZC,就不需要严格判断是否有请求key了,那就在tempJoiningDescNode->NodeJoinTimeout超时后,根据bdb_doTrustCenterRequireKeyExchange函数返回值判断是否需要key交换来决定是否删除both tables表,如果兼容zigbee 1.2协议或者zigbee 3.0设备入网阶段某些原因没有发送Request Key,那就不用处理,只有没定义TP2_LEGACY_ZC,超时以后就必须Leave掉已入网的设备。
  • 那有人就说,既然不需要检查是否发送Request Key了,那zigbee 3.0和1.2设备都可以自由入网了,为什么还要判断呢,干脆去掉检查Request Key这一步好了,原因就是3.0为了安全性,不能没有请求TCLK就入网,为了兼容1.2设备,肯定一定程度降低了安全性,但也是没有办法的事情。
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页