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:
parent
80f079a2cd
commit
878d15cf94
1 changed files with 29 additions and 19 deletions
|
@ -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");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue