Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrectly neighbor parse on ZDOCmd.Mgmt_Lqi_req (Z-Stack bug ?) #65

Open
HiFiPhile opened this issue Feb 8, 2021 · 9 comments
Open
Labels
bug Something isn't working wontfix This will not be worked on

Comments

@HiFiPhile
Copy link

  • Coordinator : LAUNCHXL-CC26xR1, FW CC2652R_coordinator_20210120.zip, IEEE: 00:12:4b:00:21:9f:c1:f9, NWK: 0
  • End device : Danfoss Ally, IEEE 84:2e:14:ff:fe:5e:50:10, NWK: 0x020C

I'm investigating this issue zigpy/zigpy#565 and found after a coordinator rset the neighbor table is wrong.

DEBUG:zigpy.util:Tries remaining: 3
DEBUG:zigpy_znp.zigbee.application:Intercepted a ZDO request: dst_addr=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=0, src_ep=0, cluster=ZDOCmd.Mgmt_Lqi_req, sequence=5, options=TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST, radius=30, data=b'\x05\x00'
DEBUG:zigpy_znp.zigbee.application:Intercepted AP ZDO request ZDOCmd.Mgmt_Lqi_req({'StartIndex': 0}) and replaced with ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Sending request: ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiReq.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiRsp.Callback(Src=0x0000, Status=<Status.SUCCESS: 0>, Neighbors=Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=75:2f:df:c4:34:62:d5:ae, ieee=14:ff:fe:5e:50:10:02:0c, nwk=0x842E, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=170)]))
DEBUG:zigpy_znp.zigbee.application:Pretending we received a ZDO message: b'\x05\x00\x01\x00\x01\xAE\xD5\x62\x34\xC4\xDF\x2F\x75\x0C\x02\x10\x50\x5E\xFE\xFF\x14\x2E\x84\x12\x02\x01\xAA'
DEBUG:zigpy.neighbor:[0x0000] request status: Status.SUCCESS. response: Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=75:2f:df:c4:34:62:d5:ae, ieee=14:ff:fe:5e:50:10:02:0c, nwk=0x842E, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=170)])
DEBUG:zigpy.neighbor:[0x0000] Done scanning. Total 1 neighbours

We can see IEEE is mixed with NWK.

Sometimes there are 2 items, the 2nd is correct

DEBUG:zigpy.util:Tries remaining: 3
DEBUG:zigpy_znp.zigbee.application:Intercepted a ZDO request: dst_addr=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=0, src_ep=0, cluster=ZDOCmd.Mgmt_Lqi_req, sequence=3, options=TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST, radius=30, data=b'\x03\x00'
DEBUG:zigpy_znp.zigbee.application:Intercepted AP ZDO request ZDOCmd.Mgmt_Lqi_req({'StartIndex': 0}) and replaced with ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Sending request: ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:aiosqlite:executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x05E6E0A8>, 'DELETE FROM neighbors WHERE device_ieee = ?', (84:2e:14:ff:fe:5e:50:10,))
DEBUG:aiosqlite:operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x05E6E0A8>, 'DELETE FROM neighbors WHERE device_ieee = ?', (84:2e:14:ff:fe:5e:50:10,)) completed
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiReq.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:aiosqlite:executing functools.partial(<built-in method executemany of sqlite3.Connection object at 0x05E6E0A8>, 'INSERT INTO neighbors VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [(84:2e:14:ff:fe:5e:50:10, 75:2f:df:c4:34:62:d5:ae, 00:12:4b:00:21:9f:c1:f9, 0x0000, 4, <PermitJoins.Unknown: 2>, 0, 252)])
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiRsp.Callback(Src=0x0000, Status=<Status.SUCCESS: 0>, Neighbors=Neighbors(entries=2, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=75:2f:df:c4:34:62:d5:ae, ieee=14:ff:fe:5e:50:10:02:0c, nwk=0x842E, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=170), Neighbor(extended_pan_id=75:2f:df:c4:34:62:d5:ae, ieee=84:2e:14:ff:fe:5e:50:10, nwk=0x020C, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=172)]))
DEBUG:aiosqlite:operation functools.partial(<built-in method executemany of sqlite3.Connection object at 0x05E6E0A8>, 'INSERT INTO neighbors VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [(84:2e:14:ff:fe:5e:50:10, 75:2f:df:c4:34:62:d5:ae, 00:12:4b:00:21:9f:c1:f9, 0x0000, 4, <PermitJoins.Unknown: 2>, 0, 252)]) completed
DEBUG:zigpy_znp.zigbee.application:Pretending we received a ZDO message: b'\x03\x00\x02\x00\x02\xAE\xD5\x62\x34\xC4\xDF\x2F\x75\x0C\x02\x10\x50\x5E\xFE\xFF\x14\x2E\x84\x12\x02\x01\xAA\xAE\xD5\x62\x34\xC4\xDF\x2F\x75\x10\x50\x5E\xFE\xFF\x14\x2E\x84\x0C\x02\x12\x02\x01\xAC'
DEBUG:zigpy.neighbor:[0x0000] request status: Status.SUCCESS. response: Neighbors(entries=2, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=75:2f:df:c4:34:62:d5:ae, ieee=14:ff:fe:5e:50:10:02:0c, nwk=0x842E, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=170), Neighbor(extended_pan_id=75:2f:df:c4:34:62:d5:ae, ieee=84:2e:14:ff:fe:5e:50:10, nwk=0x020C, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=172)])
DEBUG:aiosqlite:executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x05E6E0A8>)
DEBUG:zigpy.neighbor:[0x0000] Done scanning. Total 2 neighbours
@puddly
Copy link
Collaborator

puddly commented Feb 8, 2021

Hmm. Is this only when the ZDO request is being sent to the coordinator itself?

@HiFiPhile
Copy link
Author

I tried to query the valve, it seems the response is correct:

DEBUG:zigpy.util:Tries remaining: 3
DEBUG:zigpy.device:[0x020c] Extending timeout for 0x02 request
DEBUG:zigpy_znp.api:Sending request: ZDO.ExtRouteChk.Req(Dst=0x020C, RtStatus=<RouteStatus.ACTIVE: 1>, Options=<RouteOptions.NO_ROUTE_CACHE|MTO_ROUTE: 3>)
DEBUG:zigpy_znp.zigbee.application:Starting watchdog loop
DEBUG:zigpy_znp.api:Received command: ZDO.ExtRouteChk.Rsp(Status=<RoutingStatus.SUCCESS: 0>)
DEBUG:zigpy_znp.zigbee.application:Intercepted a ZDO request: dst_addr=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x020C), dst_ep=0, src_ep=0, cluster=ZDOCmd.Mgmt_Lqi_req, sequence=2, options=TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST, radius=30, data=b'\x02\x00'
DEBUG:zigpy_znp.zigbee.application:Intercepted AP ZDO request ZDOCmd.Mgmt_Lqi_req({'StartIndex': 0}) and replaced with ZDO.MgmtLqiReq.Req(Dst=0x020C, StartIndex=0)
DEBUG:zigpy_znp.api:Sending request: ZDO.MgmtLqiReq.Req(Dst=0x020C, StartIndex=0)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiReq.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiRsp.Callback(Src=0x020C, Status=<Status.SUCCESS: 0>, Neighbors=Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=75:2f:df:c4:34:62:d5:ae, ieee=00:12:4b:00:21:9f:c1:f9, nwk=0x0000, packed=4, permit_joining=<PermitJoins.Unknown: 2>, depth=0, lqi=252)]))
DEBUG:zigpy_znp.zigbee.application:Pretending we received a ZDO message: b'\x02\x00\x01\x00\x01\xAE\xD5\x62\x34\xC4\xDF\x2F\x75\xF9\xC1\x9F\x21\x00\x4B\x12\x00\x00\x00\x04\x02\x00\xFC'
DEBUG:zigpy.neighbor:[0x020c] request status: Status.SUCCESS. response: Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=75:2f:df:c4:34:62:d5:ae, ieee=00:12:4b:00:21:9f:c1:f9, nwk=0x0000, packed=4, permit_joining=<PermitJoins.Unknown: 2>, depth=0, lqi=252)])
DEBUG:zigpy.neighbor:[0x020c] Done scanning. Total 1 neighbours

@HiFiPhile
Copy link
Author

I can confirme zigpy/zigpy#565 is related to this behavior.

Once the end device is joined both wrong and right neighbor entries are added, after some time the right neighbor is disappeared and end device can no longer be commanded. Both neighbors can be read in ADDRMGR by nvram_read.

It seems it's not just a bug of communication, but the values are wrong on z-stack.

@puddly
Copy link
Collaborator

puddly commented Feb 9, 2021

Does this happen for every end device?

I glanced over the relevant pieces of Z-Stack and no immediate location jumped out at me for where the order of these fields in memory is swapped. My theory is that this is a pair of calls to memset that writes these two fields but the order of the calls is flipped.

I'm almost done parsing every table in NVRAM so while in theory this is something that can possibly be fixed in zigpy-znp, it should be reported to TI.

@HiFiPhile
Copy link
Author

HiFiPhile commented Feb 9, 2021

Does this happen for every end device?

Currently I only have 1 Danfoss Ally for testing.

I did more test from zero with nvram erased.

With @Koenkk 's firmware I can reproduce it easily, with TI's original version compiled by CCS I can't reproduce it after 24 hours test.

I do coordinator.neighbors.scan() after the device is joined. At first neighbor was correct, after some time it became wrong:

DEBUG:zigpy.util:Tries remaining: 3
DEBUG:zigpy_znp.zigbee.application:Intercepted a ZDO request: dst_addr=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=0, src_ep=0, cluster=ZDOCmd.Mgmt_Lqi_req, sequence=36, options=TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST, radius=30, data=b'$\x00'
DEBUG:zigpy_znp.zigbee.application:Intercepted AP ZDO request ZDOCmd.Mgmt_Lqi_req({'StartIndex': 0}) and replaced with ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Sending request: ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiReq.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiRsp.Callback(Src=0x0000, Status=<Status.SUCCESS: 0>, Neighbors=Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=84:2e:14:ff:fe:5e:50:10, nwk=0xD6CE, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=37)]))
DEBUG:zigpy_znp.zigbee.application:Pretending we received a ZDO message: b'\x24\x00\x01\x00\x01\x65\x7D\xD2\xBE\x4C\x28\xA1\xE4\x10\x50\x5E\xFE\xFF\x14\x2E\x84\xCE\xD6\x12\x02\x01\x25'    
DEBUG:zigpy.neighbor:[0x0000] request status: Status.SUCCESS. response: Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=84:2e:14:ff:fe:5e:50:10, nwk=0xD6CE, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=37)])
DEBUG:zigpy.neighbor:[0x0000] Done scanning. Total 1 neighbours
[{'_device': <zigpy.device.Device object at 0x05B8FD48>, '_neighbor': Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=84:2e:14:ff:fe:5e:50:10, nwk=0xD6CE, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=37)}]
DEBUG:zigpy.util:Tries remaining: 3
DEBUG:zigpy_znp.zigbee.application:Intercepted a ZDO request: dst_addr=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=0, src_ep=0, cluster=ZDOCmd.Mgmt_Lqi_req, sequence=37, options=TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST, radius=30, data=b'%\x00'
DEBUG:zigpy_znp.zigbee.application:Intercepted AP ZDO request ZDOCmd.Mgmt_Lqi_req({'StartIndex': 0}) and replaced with ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Sending request: ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiReq.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiRsp.Callback(Src=0x0000, Status=<Status.SUCCESS: 0>, Neighbors=Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=84:2e:14:ff:fe:5e:50:10, nwk=0xD6CE, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=37)]))
DEBUG:zigpy_znp.zigbee.application:Pretending we received a ZDO message: b'\x25\x00\x01\x00\x01\x65\x7D\xD2\xBE\x4C\x28\xA1\xE4\x10\x50\x5E\xFE\xFF\x14\x2E\x84\xCE\xD6\x12\x02\x01\x25'    
DEBUG:zigpy.neighbor:[0x0000] request status: Status.SUCCESS. response: Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=84:2e:14:ff:fe:5e:50:10, nwk=0xD6CE, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=37)])
DEBUG:zigpy.neighbor:[0x0000] Done scanning. Total 1 neighbours
[{'_device': <zigpy.device.Device object at 0x05B8FD48>, '_neighbor': Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=84:2e:14:ff:fe:5e:50:10, nwk=0xD6CE, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=37)}]
DEBUG:zigpy_znp.api:Received command: AF.DataConfirm.Callback(Status=<Status.MAC_TRANSACTION_EXPIRED: 240>, Endpoint=1, TSN=8)
DEBUG:zigpy_znp.zigbee.application:Request failed (Unsuccessful request status code: <Status.MAC_TRANSACTION_EXPIRED: 240>), retry attempt 1 of 5
DEBUG:zigpy_znp.api:Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0xD6CE), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=513, TSN=8, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x08\x0B\x0A\x00')
DEBUG:zigpy_znp.api:Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Sending request: SYS.Ping.Req()
DEBUG:zigpy_znp.api:Received command: SYS.Ping.Rsp(Capabilities=<MTCapabilities.CAP_APP_CNF|CAP_GP|CAP_UTIL|CAP_ZDO|CAP_AF|CAP_SYS: 1625>)
DEBUG:zigpy_znp.api:Received command: AF.DataConfirm.Callback(Status=<Status.MAC_TRANSACTION_EXPIRED: 240>, Endpoint=1, TSN=8)
DEBUG:zigpy_znp.api:Sending request: Util.AssocGetWithAddress.Req(IEEE=84:2e:14:ff:fe:5e:50:10, NWK=0xD6CE)
DEBUG:zigpy_znp.api:Received command: Util.AssocGetWithAddress.Rsp(Device=Device(shortAddr=0xD6CE, addrIdx=0, nodeRelation=<NodeRelation.CHILD_RFD: 1>, devStatus=8, assocCnt=0, age=0, linkInfo=LinkInfo(txCounter=0, txCost=1, rxLqi=37, inKeySeqNum=0, inFrmCntr=65536, txFailure=65535), PaddingByte1=b'\xFF', PaddingByte2=b'\xFF', endDev=AgingEndDevice(endDevCfg=255, deviceTimeout=4294967295), PaddingByte3=b'\xFF', PaddingByte4=b'\xFF', PaddingByte5=b'\xFF', timeoutCounter=4294967295, keepaliveRcv=255, ctrl=255, PaddingByte6=b'\xFF', PaddingByte7=b'\xFF'))      
DEBUG:zigpy_znp.api:Sending request: Util.AssocRemove.Req(IEEE=84:2e:14:ff:fe:5e:50:10)
DEBUG:zigpy_znp.api:Received command: Util.AssocRemove.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Sending request: ZDO.ExtRouteDisc.Req(Dst=0xD6CE, Options=<RouteDiscoveryOptions.UNICAST: 0>, Radius=30)
DEBUG:zigpy_znp.api:Received command: ZDO.ExtRouteDisc.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.zigbee.application:Request failed (Unsuccessful request status code: <Status.MAC_TRANSACTION_EXPIRED: 240>), retry attempt 2 of 5
DEBUG:zigpy_znp.api:Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0xD6CE), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=513, TSN=8, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x08\x0B\x0A\x00')
DEBUG:zigpy_znp.api:Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Received command: AF.DataConfirm.Callback(Status=<Status.NWK_NO_ROUTE: 205>, Endpoint=1, TSN=8)
DEBUG:zigpy_znp.api:Sending request: ZDO.ExtRouteDisc.Req(Dst=0xD6CE, Options=<RouteDiscoveryOptions.UNICAST: 0>, Radius=30)
DEBUG:zigpy_znp.api:Received command: ZDO.ExtRouteDisc.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.zigbee.application:Request failed (Unsuccessful request status code: <Status.NWK_NO_ROUTE: 205>), retry attempt 3 of 5
DEBUG:zigpy_znp.api:Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0xD6CE), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=513, TSN=8, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x08\x0B\x0A\x00')
DEBUG:zigpy_znp.api:Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Received command: AF.DataConfirm.Callback(Status=<Status.NWK_NO_ROUTE: 205>, Endpoint=1, TSN=8)
DEBUG:zigpy_znp.zigbee.application:Request failed (Unsuccessful request status code: <Status.NWK_NO_ROUTE: 205>), retry attempt 4 of 5
DEBUG:zigpy_znp.api:Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0xD6CE), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=513, TSN=8, Options=<TransmitOptions.NONE: 0>, Radius=30, Data=b'\x18\x08\x0B\x0A\x00')
DEBUG:zigpy_znp.api:Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Received command: AF.DataConfirm.Callback(Status=<Status.NWK_NO_ROUTE: 205>, Endpoint=1, TSN=8)
DEBUG:zigpy_znp.zigbee.application:Request failed (Unsuccessful request status code: <Status.NWK_NO_ROUTE: 205>), retry attempt 5 of 5
DEBUG:zigpy_znp.api:Sending request: Util.AssocAdd.Req(NWK=0xD6CE, IEEE=84:2e:14:ff:fe:5e:50:10, NodeRelation=<NodeRelation.CHILD_RFD: 1>)
DEBUG:zigpy_znp.api:Received command: Util.AssocAdd.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy.util:Tries remaining: 3
DEBUG:zigpy_znp.zigbee.application:Intercepted a ZDO request: dst_addr=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=0, src_ep=0, cluster=ZDOCmd.Mgmt_Lqi_req, sequence=38, options=TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST, radius=30, data=b'&\x00'
DEBUG:zigpy_znp.zigbee.application:Intercepted AP ZDO request ZDOCmd.Mgmt_Lqi_req({'StartIndex': 0}) and replaced with ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Sending request: ZDO.MgmtLqiReq.Req(Dst=0x0000, StartIndex=0)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiReq.Rsp(Status=<Status.SUCCESS: 0>)
DEBUG:zigpy_znp.api:Received command: ZDO.MgmtLqiRsp.Callback(Src=0x0000, Status=<Status.SUCCESS: 0>, Neighbors=Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=14:ff:fe:5e:50:10:d6:ce, nwk=0x842E, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=170)]))
DEBUG:zigpy_znp.zigbee.application:Pretending we received a ZDO message: b'\x26\x00\x01\x00\x01\x65\x7D\xD2\xBE\x4C\x28\xA1\xE4\xCE\xD6\x10\x50\x5E\xFE\xFF\x14\x2E\x84\x12\x02\x01\xAA'    
DEBUG:zigpy.neighbor:[0x0000] request status: Status.SUCCESS. response: Neighbors(entries=1, start_index=0, neighbor_table_list=[Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=14:ff:fe:5e:50:10:d6:ce, nwk=0x842E, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=170)])
DEBUG:zigpy.neighbor:[0x0000] Done scanning. Total 1 neighbours
[{'_device': None, '_neighbor': Neighbor(extended_pan_id=e4:a1:28:4c:be:d2:7d:65, ieee=14:ff:fe:5e:50:10:d6:ce, nwk=0x842E, packed=18, permit_joining=<PermitJoins.Unknown: 2>, depth=1, lqi=170)}]
DEBUG:zi

@puddly
Copy link
Collaborator

puddly commented Mar 9, 2021

I believe I just ran into this issue. I formed a test network with three devices on a freshly-erased zzh! stick running the latest build of Z-Stack. The following devices were joined to the coordinator:

  • 00:12:4B:00:1C:4B:6E:8E (0xAE8E)
  • 00:12:4B:00:1C:4B:21:59 (0x765B)
  • D0:CF:5E:FF:FE:CE:3A:F2 (0x8E2F)

When performing a network backup by parsing the NVRAM data structures, I noticed not three but five devices show up:

{
    "nwk_address": "765b",
    "ieee_address": "00124b001c4b2159"  // Sonoff temp/humidity
},
{
    "nwk_address": "ae8e",
    "ieee_address": "00124b001c4b6e8e"  // Sonoff motion
},
{
    "nwk_address": "fffe",
    "ieee_address": "4b001c4b21591f13"  // ???
},
{
    "nwk_address": "0012",
    "ieee_address": "4b001c4b2159d4fc" // ???
},
{
    "nwk_address": "8e2f",
    "ieee_address": "d0cf5efffece3af2",  // Trådfri outlet
    "link_key": {
        "tx_counter": 0,
        "rx_counter": 0,
        "key": "d2b23cb634cda7031b7e0dc49a010ed8"
    }
}

Wireshark confirmed that the coordinator was indeed sending a parent announce message containing these two "devices":

ZigBee Application Support Layer Data, Dst Endpt: 0, Src Endpt: 0
    Frame Control Field: Data (0x08)
    Destination Endpoint: 0
    Parent Announce (Cluster ID: 0x001f)
    Profile: ZigBee Device Profile (0x0000)
    Source Endpoint: 0
    Counter: 8
ZigBee Device Profile, Parent Announce, # children 2 : 4b:00:1c:4b:21:59:1f:13 ...
    Sequence Number: 5
    NumberOfChildren: 2
    Extended Address: 4b:00:1c:4b:21:59:1f:13 (4b:00:1c:4b:21:59:1f:13)
    Extended Address: 4b:00:1c:4b:21:59:d4:fc (4b:00:1c:4b:21:59:d4:fc)

In Z-Stack 3, the address manager table in NVRAM is stored so that each entry has its own "item" that you directly read. I've backed up and restored numerous networks using this parsing code and assume it is correct:

NVRAM[NvSysIds.ZSTACK][ExNvIds.ADDRMGR][0x0000] = AddrMgrEntry(type=<AddrMgrUserType.Assoc: 1>, nwkAddr=0xFFFE, extAddr=4b:00:1c:4b:21:59:1f:13)
NVRAM[NvSysIds.ZSTACK][ExNvIds.ADDRMGR][0x0001] = AddrMgrEntry(type=<AddrMgrUserType.Assoc: 1>, nwkAddr=0x0012, extAddr=4b:00:1c:4b:21:59:d4:fc)

It definitely looks like some Z-Stack bug is causing these bogus devices to be written to NVRAM. I believe some code somewhere in Z-Stack is directly reading the members of a struct like this:

uint8_t extAddr[8];
uint16_t nwkAddr;

But in the wrong order:

uint16_t nwkAddr;
uint8_t extAddr[8];

If you concatenate the NWK and IEEE addresses of the second bogus device, you can see it forms the IEEE address of the Sonoff motion sensor:

// Bogus NWK + IEEE
0x0012 4b:00:1c:4b:21:59:d4:fc

// Sonoff motion IEEE
00124b001c4b2159

This doesn't explain what the two trailing bytes are in either of the two bogus devices' IEEE addresses but it perhaps is the incorrect parsing of some ZDO announcement packet sent by another router? I don't believe a topology scan was performed by zigpy yet so this looks like something triggered by device joining.

@MattWestb
Copy link

If putting all "real devices" and comparing them with the "new" i getting little from all in the 2 new.

Real ones:
765b
00124b001c4b2159
ae8e
0012_4b001c4b_6e8e
8e2f
d0cf5efffece3af2

False ones:
fffe
4b001c4b2159 1f13
0012
4b001c4b2159 d4fc

And found parts in the false ones:

fffe
4b001c4b21591f13
0012
4b001c4b2159d4fc

The problem is the 4b001c4b part can coming from both the Sonoff sensors.

My feeling is that the last part (1f13 and d4fc) is one hashed part of the real devices mwk: 765b ae8e and 8e2f.

@puddly Can you deleting one of the Sonoff and putting in one with more different IEEE (if you is having one with IEEE: 0123456789ABCDEF its one high points device) than you can see witch part that is scrambled.

I only saying INTERESTING !!

And great findings done !!!

@MattWestb
Copy link

If i was having one of those coordinators then i have patching 3 IKEA modules with custom IEEE (flashing custom token with IEEE).
0011223344556677, 8899AABBCCDDEEFF and one with 0123456789ABCDEF and reading the NVRAM from the NCP.

@puddly
Copy link
Collaborator

puddly commented Mar 10, 2021

If I can find a way recreate it again, I will try with devices with less similar IEEE addresses (and hopefully capture the packet responsible for this). Unfortunately it did not happen again after three attempts 😞

@puddly puddly added bug Something isn't working wontfix This will not be worked on labels Jan 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

3 participants