This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Mesh TX after node reset

Hello,

I have a statically provisioned mesh network (keys and addresses are pre-set in code to make it simple for now) in which each device periodically broadcasts it's status to the mesh for other devices to be aware of (to illustrate it it might be considered some form of pinging). It all works ok and because of low frequency of the broadcasts all devices are able to receive the pings from each other and update their internal state. This is all great and is working fine. 

My problem starts whenever one of the devices resets - whenever this happens the rebooted device will transmit the messages but no other nodes in the network will receive the pings. The rebooted device correctly receives pings from other nodes.

If i remember correctly there is some sort of messgae counter which makes mesh ignore messages which are older than the last received message. Is there a way to make the rebooted device "catch up" with the network and update it's transmitted message counter to the value in last received packet?

Parents
  • Hi,

    If by "reset" you mean the "node reset" functionality, which means the node is unprovisioned and then provisioned again, with the same address both before and after, then yes. It may be the counter that you mention.

    Bluetooth Mesh implements replay protection by each message from a particular address including a sequence number. Each node in the network keeps track of how far each address has come in this sequencing, and when a message contains an outdated sequence number it is discarded as a potential replay attack.

    Also by specification, the sequencing is reset to start from 0 on "node reset". So when provisioning the node with the same address, all messages from that address will look like replay attempts until it overtakes the highest sequence number sent from that address previously.

    Recommended in the Bluetooth Mesh specification is to use a new address after node reset. The alternative would be to remove the unprovisioned device from the replay protection arrays of all other nodes, for which there is no specified mechanism.

    I do not know any good way to bump the sequence number as you suggest. Because of the inner workings of our Bluetooth Mesh implementation, the sequence number does get bumped every time you reboot the device (i.e. SoC reset, not "node reset",) but there is really no simple way to know how far all the other nodes think that the node has counted previously.

    If by "reset" you do not mean "node reset", then I have no clue. Then you should provide some more detailed information, optimally some example code for easily showcasing / reproducing the behavior.

    Regards,
    Terje

  • Hello,

    My case of reset is "SoC reset". After reset the device load's it's previously stored (from fstorage or even hard-coded to remove fstorage issue out of the question) so it's provisioned.

    Maybe fast forwarding of the node to catch up with the network could be done by somehow extracting last received mesh message sequence ID or changing that other nodes of the mesh network clear the replay protection if they encounter a message with sequence ID = 0 for example?

  • It sounds like this is a separate issue. Thing is, it keeps its sequence number in RAM, but it also has written a higher number in Flash. On reboot it starts from that higher number. Whenever the sequence number in RAM reaches the number in Flash, a new number is written to Flash. You can look at it as "allocating" blocks of sequence numbers to itself, and since on a reboot it does not remember how far it has come in the current block it will start from the next one. So if you have not done anything to change this behavior then it should not have to do with sequence numbering.

    Please note that the place it should start from cannot be hard coded, as it must start higher each time.

    Also note that always accepting sequence ID 0 would be a huge security hole, as it opens for replay attacks, which is exactly what sequence numbering is supposed to protect against in the first place.

    You should figure out, through debugging, what sequence numbers the node is using, to see if that is indeed the issue here.

  • I am working on a setup for throughput testing and since my code already uses persistent storage that would probably be the case as I had to disable mesh PS to avoid colisions (or migrating to Mesh SDK storage). I understand the security risks and this is not a concern at this moment and just wanted to see where to look for the current value of message sequence ID. I've looked into packet and packet_buffer sources but couldn't find the variable storing the sequence number.

  • Hi,

    I am very sorry for the delays, I have been a lot out-of-office lately.

    The sequence number is in net_state.c. Current "maximum allocated" is in m_net_state.seqnum_max_available, and also written to flash. Maximum value gets bumped and written to flash in seqnum_block_allocate(). It gets bumped by NETWORK_SEQNUM_FLASH_BLOCK_SIZE which is defined in nrf_mesh_config_core.h, so that is where you configure how much is "allocated" each time if you should need that.

    The maximum value is fetched from flash as part of net_state_recover_from_flash(), which iterates through the entries searching for the FLASH_HANDLE_SEQNUM handle. Note that it then calls seqnum_block_allocate() in order to allocate a new block. (This recovery is done after reset, and so one must continue past the previously allocated maximum value in order to be sure the sequence number is higher.)

    Regards,
    Terje

Reply
  • Hi,

    I am very sorry for the delays, I have been a lot out-of-office lately.

    The sequence number is in net_state.c. Current "maximum allocated" is in m_net_state.seqnum_max_available, and also written to flash. Maximum value gets bumped and written to flash in seqnum_block_allocate(). It gets bumped by NETWORK_SEQNUM_FLASH_BLOCK_SIZE which is defined in nrf_mesh_config_core.h, so that is where you configure how much is "allocated" each time if you should need that.

    The maximum value is fetched from flash as part of net_state_recover_from_flash(), which iterates through the entries searching for the FLASH_HANDLE_SEQNUM handle. Note that it then calls seqnum_block_allocate() in order to allocate a new block. (This recovery is done after reset, and so one must continue past the previously allocated maximum value in order to be sure the sequence number is higher.)

    Regards,
    Terje

Children
No Data
Related