Bluetooth: Mesh: Align handling of seg_ack to spec

Updates the handling of incoming seg ack messages to comply with
the mesh protocol specification, section 3.5.3.3.2 and section
3.5.3.3.3.

Previous implementation did not restart the retransmission timer unless
the incoming ack contained at least one segment newly marked as
acknowledged. According to the spec, the timer should be restated
regardless. The implementation depends on the retransmission
timer to end the transmission early if there was no more retransmission
attempts. Checks have been added to ensure that this now happens
immediately.

Signed-off-by: Anders Storrø <anders.storro@nordicsemi.no>
This commit is contained in:
Anders Storrø 2023-07-19 11:14:35 +02:00 committed by Fabio Baltieri
commit 878d15cf94

View file

@ -255,6 +255,7 @@ static void seg_tx_reset(struct seg_tx *tx)
tx->nack_count = 0;
tx->seg_send_started = 0;
tx->ack_received = 0;
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_IVU_PENDING)) {
LOG_DBG("Proceeding with pending IV Update");
@ -918,27 +919,36 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
/* If transmission is not in progress it means
* that Retransmission Timer is running
*/
if (new_seg_ack) {
if (tx->seg_o == 0) {
uint32_t delta_ms = (uint32_t)(k_uptime_get() -
tx->adv_start_timestamp);
k_timeout_t timeout = K_NO_WAIT;
if (tx->seg_o == 0) {
k_timeout_t timeout = K_NO_WAIT;
/* According to the Bluetooth Mesh Profile specification,
* section 3.5.3.3, we should reset the retransmit timer and
* retransmit immediately when receiving a valid ack message
* while Retransmisison timer is running. However, transport should
* still keep segment transmission interval time between
* transmission of each segment.
*/
if (delta_ms < BT_MESH_SAR_TX_SEG_INT_MS) {
timeout = K_MSEC(BT_MESH_SAR_TX_SEG_INT_MS - delta_ms);
}
k_work_reschedule(&tx->retransmit, timeout);
} else {
tx->ack_received = 1U;
/* If there are no retransmission attempts left we
* immediately trigger the retransmit call that will
* end the transmission.
*/
if ((BT_MESH_ADDR_IS_UNICAST(tx->dst) &&
!tx->attempts_left_without_progress) ||
!tx->attempts_left) {
goto reschedule;
}
uint32_t delta_ms = (uint32_t)(k_uptime_get() - tx->adv_start_timestamp);
/* According to the Bluetooth Mesh Profile specification,
* section 3.5.3.3, we should reset the retransmit timer and
* retransmit immediately when receiving a valid ack message
* while Retransmisison timer is running. However, transport should
* still keep segment transmission interval time between
* transmission of each segment.
*/
if (delta_ms < BT_MESH_SAR_TX_SEG_INT_MS) {
timeout = K_MSEC(BT_MESH_SAR_TX_SEG_INT_MS - delta_ms);
}
reschedule:
k_work_reschedule(&tx->retransmit, timeout);
} else {
tx->ack_received = 1U;
}
} else {
LOG_DBG("SDU TX complete");