Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PM handler - deleting lowest ranked peer

Hi nRF Support,

I get nRF5 SDK version 17.0.2 and learn Peer Manager handler implementation (pm_handler_flash_clean function). Lets consider this case:

- 2 bonded peers (ranks enabled) that connected one time

- another fds user that fill storage unique data, so dirty_records of fds_stat is 0

or

- a lot of bonded peers that connected one time so storage filled RANK data, so dirty_records of fds_stat is 0

If first peer will connect again then pm_peer_rank_highest function return NRF_ERROR_STORAGE_FULL and pm_peer_ranks_get return PEER_ID of current connected peer because this peer has real lowest rank. And then PM module has attempt to delete connected peer but it is undefined behaviour.

pm_peer_id_t peer_id_to_delete;
err_code = pm_peer_ranks_get(NULL, NULL, &peer_id_to_delete, NULL);
if (err_code == NRF_SUCCESS)
{
    NRF_LOG_INFO("Deleting lowest ranked peer (peer_id: %d)", peer_id_to_delete);
    err_code = pm_peer_delete(peer_id_to_delete);
    APP_ERROR_CHECK(err_code);
    flash_write_after_gc = true;
}

Is it possible issue or probability of this case very low? How to solve this issue?

Best regards,

Konstantin

Parents
  • Hi Konstantin,

    Yes, this is a possible issue. The probability of it happening is application dependent, and how to best handle this is also application dependent.

    If you have a application where you blindly write to FDS without thought of it becoming full or not, then this could happen. I would suggest that you regularly check amount of free FDS space and amount that can be garbage collected. If there is almost no free space left and a lot to garbage collect, simply do garbage collection. If there is almost no free space and nothing to garbage collect, you need to either delete some data or stop writing new data. That way you will never end up in a situation where there is no room to update peer manger ranks.

    If the above is not possible, then you should add a check to verify that you never delete the bond of a currently connected peer, as that is as you write not supported and can lead to undefined behavior. Doing this is always a good idea if there is any chance of getting into the situation  where you could otherwise delete the bond of a currently connected peer.

    Einar

Reply
  • Hi Konstantin,

    Yes, this is a possible issue. The probability of it happening is application dependent, and how to best handle this is also application dependent.

    If you have a application where you blindly write to FDS without thought of it becoming full or not, then this could happen. I would suggest that you regularly check amount of free FDS space and amount that can be garbage collected. If there is almost no free space left and a lot to garbage collect, simply do garbage collection. If there is almost no free space and nothing to garbage collect, you need to either delete some data or stop writing new data. That way you will never end up in a situation where there is no room to update peer manger ranks.

    If the above is not possible, then you should add a check to verify that you never delete the bond of a currently connected peer, as that is as you write not supported and can lead to undefined behavior. Doing this is always a good idea if there is any chance of getting into the situation  where you could otherwise delete the bond of a currently connected peer.

    Einar

Children
  • Hi Einar,

    Thanks for answer. Both strategies looks working. I can implement any in my application.

    Question 1: is implementation below working model?

    // 1) find the lowest ranked peer
    pm_peer_id_t peer_id_to_delete;
    err_code = pm_peer_ranks_get(NULL, NULL, &peer_id_to_delete, NULL);
    if (err_code == NRF_SUCCEESS)
    {
        uint16_t handle = BLE_CONN_HANDLE_INVALID;
        err_code = pm_conn_handle_get(peer_id_to_delete, &handle);
        APP_ERROR_CHECK(err_code);
        
        if (handle != BLE_CONN_HANDLE_INVALID)
        {
    	    // 2) the lowest ranked peer is currently connected => delete any nonconnected peer
    	    peer_id_to_delete = pm_next_peer_id_get(PM_PEER_ID_INVALID);
    	    while (peer_id_to_delete != PM_PEER_ID_INVALID)
    	    {
    		    err_code = pm_conn_handle_get(peer_id_to_delete, &handle);
    		    APP_ERROR_CHECK(err_code);
    		    if (handle == BLE_CONN_HANDLE_INVALID)
    			    break;
    
    		    peer_id_to_delete = pm_next_peer_id_get(peer_id_to_delete);
    	    }
        }
        
        // 3) delete finded peer
        if (peer_id_to_delete != PM_PEER_ID_INVALID)
        {
    	    err_code = pm_peer_delete(peer_id_to_delete);
    	    APP_ERROR_CHECK(err_code);
        }
    }
    

    Question 2: will a solution of issue be offered in peer_manager_handler in new version SDK?

    Konstantin

Related