Skip to content

Commit 30cc1aa

Browse files
committed
[nrf fromtree] bluetooth: mesh: pb_adv: Fix resending Generic Transaction Ack PDU
The Generic Provisioning protocol requires that a transaction must be acknowledged before the next Generic Provisioning PDU is processed (section 5.3.3, MshPRT_v1.1). In the current PB-ADV implementation, if there is an ongoing transaction (link.tx.adv points to a valid advertisement), any received Generic Provisioning Start and Continuation PDUs are ignored. This creates a scenario where a remote device misses the Transaction Acknowledgment PDU and retransmits the last PDUs, but they are ignored by the local device because the local device has already started sending the next Provisioning PDU. In particular, in the observed failure, the Provisioner missed the Generic Transaction Acknowledgment PDU during the transmission of the Provisioning Data PDU. This commit modifies the processing logic for Generic Provisioning Start and Continuation PDUs by checking if the received PDU has already been received. If so, it attempts to re-send the Generic Transaction Acknowledgment PDU. Signed-off-by: Pavel Vasilyev <[email protected]> (cherry picked from commit 7592b04) Signed-off-by: Pavel Vasilyev <[email protected]>
1 parent db413b6 commit 30cc1aa

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

subsys/bluetooth/mesh/pb_adv.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -482,14 +482,16 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
482482
{
483483
uint8_t seg = CONT_SEG_INDEX(rx->gpc);
484484

485-
if (link.tx.adv[0]) {
486-
LOG_DBG("Ongoing tx transaction has not been completed yet");
487-
return;
488-
}
489-
490485
LOG_DBG("len %u, seg_index %u", buf->len, seg);
491486

487+
/* When link.rx.seg is zero for a valid link.rx.id, this means that transaction
488+
* has already been received. The other device probably missed the Transaction
489+
* Acknowledgment PDU, so we need to resend it regardless of the active transmission.
490+
*/
492491
if (!link.rx.seg && link.rx.id == rx->xact_id) {
492+
/* Send ack if another ack is NOT pending for transmission. Otherwise, skip sending
493+
* this ack for now.
494+
*/
493495
if (!ack_pending()) {
494496
LOG_DBG("Resending ack");
495497
gen_prov_ack_send(rx->xact_id);
@@ -498,6 +500,11 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
498500
return;
499501
}
500502

503+
if (link.tx.adv[0]) {
504+
LOG_DBG("Ongoing tx transaction has not been completed yet");
505+
return;
506+
}
507+
501508
if (!link.rx.seg &&
502509
next_transaction_id(link.rx.id) == rx->xact_id) {
503510
LOG_DBG("Start segment lost");
@@ -575,21 +582,28 @@ static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
575582
{
576583
uint8_t seg = SEG_NVAL;
577584

585+
/* When link.rx.seg is zero for a valid link.rx.id, this means that transaction
586+
* has already been received. The other device probably missed the Transaction
587+
* Acknowledgment PDU, so we need to resend it regardless of the active transmission.
588+
*/
589+
if (rx->xact_id == link.rx.id && !link.rx.seg) {
590+
/* Send ack if another ack is NOT pending for transmission. Otherwise, skip sending
591+
* this ack for now.
592+
*/
593+
if (!ack_pending()) {
594+
LOG_DBG("Resending ack");
595+
gen_prov_ack_send(rx->xact_id);
596+
}
597+
598+
return;
599+
}
600+
578601
if (link.tx.adv[0]) {
579602
LOG_DBG("Ongoing tx transaction has not been completed yet");
580603
return;
581604
}
582605

583606
if (rx->xact_id == link.rx.id) {
584-
if (!link.rx.seg) {
585-
if (!ack_pending()) {
586-
LOG_DBG("Resending ack");
587-
gen_prov_ack_send(rx->xact_id);
588-
}
589-
590-
return;
591-
}
592-
593607
if (!(link.rx.seg & BIT(0))) {
594608
LOG_DBG("Ignoring duplicate segment");
595609
return;

0 commit comments

Comments
 (0)