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

access_model_publish() requires p_message->p_buffer for retransmissions on loopback but not on radio

Hi,

When publishing a message with access_model_publish() the p_message->p_buffer must be remain valid until all retransmissions have completed for loopback message but not those that are sent via the upper transport layer.

access_model_publish() will call packet_alloc_and_tx() that copies p_message->p_buffer into allocated memory.

If the model is configured to do retransmissions it will call access_publish_retransmission_message_add() that queues the message for later retransmission.

When it's time to do the retransmission packet_tx() is called via retransmissions_timer_cb() -> access_packet_tx().This function, packet_tx(), contains the following that handles loopback packets.

    if (loopback_packet)
    {
        access_loopback_request_t request =
        {
        ...
            .p_data = p_tx_message->p_buffer,
            .length = p_tx_message->length,
        ...
However, further down in the same function one can see the following
    if (!loopback_packet || (dst_address.type != NRF_MESH_ADDRESS_TYPE_UNICAST))
    {
        
        ...
        
        tx_params.p_data = p_access_payload;
        tx_params.data_len = access_payload_len;
        tx_params.tx_token = p_tx_message->access_token;

        status = nrf_mesh_packet_send(&tx_params, NULL);
        if (status == NRF_SUCCESS)
        {
            __LOG(LOG_SRC_ACCESS, LOG_LEVEL_DBG1, "TX: [aop: 0x%04x] \n", p_tx_message->opcode.opcode);
            __LOG_XB(LOG_SRC_ACCESS, LOG_LEVEL_DBG1, "TX: Msg", p_tx_message->p_buffer, p_tx_message->length);
        }
Here it's actually p_access_payload that is send to the upper transport layer and not p_tx_message->p_buffer. But p_tx_message->p_buffer is what gets logged and used for loopback. This is misleading as the data logged is not the same that is sent to the upper layers.If p_message->p_buffer was freed after the call to access_model_publish() the message would still be correctly sent to the upper transport layers during retransmission but for loopback and logging it would use unallocated memory instead.The following patch makes it work properly.
diff --git a/mesh/access/src/access.c b/mesh/access/src/access.c
index 85b0ced..81e1492 100644
--- a/mesh/access/src/access.c
+++ b/mesh/access/src/access.c
@@ -369,8 +369,8 @@ static uint32_t packet_tx(access_model_handle_t handle,
         {
             .token = p_tx_message->access_token,
             .opcode = p_tx_message->opcode, /*lint !e64 Type mismatch */
-            .p_data = p_tx_message->p_buffer,
-            .length = p_tx_message->length,
+            .p_data = &p_access_payload[access_utils_opcode_size_get(p_tx_message->opcode)],
+            .length = access_payload_len - access_utils_opcode_size_get(p_tx_message->opcode),
             .src_value = src_address,
             .dst = dst_address,              /*lint !e64 Type mismatch */
             .ttl = ttl,
@@ -424,7 +424,9 @@ static uint32_t packet_tx(access_model_handle_t handle,
         if (status == NRF_SUCCESS)
         {
             __LOG(LOG_SRC_ACCESS, LOG_LEVEL_DBG1, "TX: [aop: 0x%04x] \n", p_tx_message->opcode.opcode);
-            __LOG_XB(LOG_SRC_ACCESS, LOG_LEVEL_DBG1, "TX: Msg", p_tx_message->p_buffer, p_tx_message->length);
+            __LOG_XB(LOG_SRC_ACCESS, LOG_LEVEL_DBG1, "TX: Msg",
+                    &p_access_payload[access_utils_opcode_size_get(p_tx_message->opcode)],
+                    access_payload_len - access_utils_opcode_size_get(p_tx_message->opcode));
         }
     }
 
I'm using SDK For Mesh v3.1.0.I've noticed that access_model_reliable_publish() and access_reliable_t have a note that says "The data pointed to must be retained for the entire reliable transfer." and points to MBTLE-1540, but for access_model_publish() I haven't found anything similar.Thanks.

Parents Reply Children
Related