Skip to content

Commit dd39c8e

Browse files
committed
Bluetooth: Mesh: Fix pb-adv link close timeout
Alters the closing timout implementation of the pb-adv so that the provisioner does not close the link until the closing timeout has elapsed. Reduces the timeout from 3 to 2 seconds. Adds minor delay in reprovision persistence test to avoid failure after changes. Signed-off-by: Anders Storrø <[email protected]>
1 parent d11c0a1 commit dd39c8e

File tree

1 file changed

+72
-31
lines changed

1 file changed

+72
-31
lines changed

subsys/bluetooth/mesh/pb_adv.c

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ LOG_MODULE_REGISTER(bt_mesh_pb_adv);
5050

5151
#define RETRANSMIT_TIMEOUT K_MSEC(CONFIG_BT_MESH_PB_ADV_RETRANS_TIMEOUT)
5252
#define BUF_TIMEOUT K_MSEC(400)
53-
#define CLOSING_TIMEOUT 3
53+
#define CLOSING_TIMEOUT 2
5454
#define TRANSACTION_TIMEOUT 30
5555

5656
/* Acked messages, will do retransmissions manually, taking acks into account:
@@ -112,6 +112,15 @@ struct pb_adv {
112112
struct k_work_delayable retransmit;
113113
} tx;
114114

115+
struct {
116+
/* Start timestamp of link close */
117+
int64_t start;
118+
119+
/* Close reason */
120+
enum prov_bearer_link_status reason;
121+
} close_link;
122+
123+
115124
/* Protocol timeout */
116125
struct k_work_delayable prot_timer;
117126
};
@@ -133,11 +142,18 @@ static void link_close(struct prov_rx *rx, struct net_buf_simple *buf);
133142
static void prov_link_close(enum prov_bearer_link_status status);
134143
static void close_link(enum prov_bearer_link_status status);
135144

145+
static inline bool close_timer_elapsed(void)
146+
{
147+
return k_uptime_get() - link.close_link.start > CLOSING_TIMEOUT * MSEC_PER_SEC;
148+
}
149+
136150
static void buf_sent(int err, void *user_data)
137151
{
138152
enum prov_bearer_link_status reason = (enum prov_bearer_link_status)(int)user_data;
139153

140-
if (atomic_test_and_clear_bit(link.flags, ADV_LINK_CLOSING)) {
154+
if (atomic_test_bit(link.flags, ADV_LINK_CLOSING) && close_timer_elapsed()) {
155+
LOG_DBG("Close link timer elapsed - Closing link.");
156+
atomic_clear_bit(link.flags, ADV_LINK_CLOSING);
141157
close_link(reason);
142158
return;
143159
}
@@ -608,24 +624,6 @@ static void send_reliable(void)
608624
k_work_reschedule(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
609625
}
610626

611-
static void prov_retransmit(struct k_work *work)
612-
{
613-
LOG_DBG("");
614-
615-
if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
616-
LOG_WRN("Link not active");
617-
return;
618-
}
619-
620-
if (k_uptime_get() - link.tx.start > link.tx.timeout * MSEC_PER_SEC) {
621-
LOG_WRN("Giving up transaction");
622-
prov_link_close(PROV_BEARER_LINK_STATUS_TIMEOUT);
623-
return;
624-
}
625-
626-
send_reliable();
627-
}
628-
629627
static struct net_buf *ctl_buf_create(uint8_t op, const void *data, uint8_t data_len,
630628
uint8_t retransmits)
631629
{
@@ -663,7 +661,7 @@ static int bearer_ctl_send(struct net_buf *buf)
663661
return 0;
664662
}
665663

666-
static int bearer_ctl_send_unacked(struct net_buf *buf, void *user_data)
664+
static int bearer_ctl_send_unacked(struct net_buf *buf)
667665
{
668666
if (!buf) {
669667
return -ENOMEM;
@@ -672,12 +670,57 @@ static int bearer_ctl_send_unacked(struct net_buf *buf, void *user_data)
672670
prov_clear_tx();
673671
k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT);
674672

675-
bt_mesh_adv_send(buf, &buf_sent_cb, user_data);
673+
bt_mesh_adv_send(buf, NULL, NULL);
676674
net_buf_unref(buf);
677675

678676
return 0;
679677
}
680678

679+
static void bearer_ctl_send_link_close(void)
680+
{ /*
681+
* According to mesh profile spec (5.3.1.4.3), the close message should
682+
* be restransmitted at least three times.
683+
*/
684+
struct net_buf *buf =
685+
ctl_buf_create(LINK_CLOSE, &link.close_link.reason, 1, RETRANSMITS_LINK_CLOSE);
686+
687+
if (!buf) {
688+
LOG_ERR("Failed to create link close buffer");
689+
return;
690+
}
691+
692+
prov_clear_tx();
693+
k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT);
694+
695+
bt_mesh_adv_send(buf, &buf_sent_cb, (void *)link.close_link.reason);
696+
net_buf_unref(buf);
697+
}
698+
699+
static void prov_retransmit(struct k_work *work)
700+
{
701+
LOG_DBG("");
702+
703+
if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
704+
if (close_timer_elapsed()) {
705+
LOG_DBG("Close link timer elapsed - Closing link.");
706+
atomic_clear_bit(link.flags, ADV_LINK_CLOSING);
707+
close_link(link.close_link.reason);
708+
return;
709+
}
710+
711+
bearer_ctl_send_link_close();
712+
k_work_reschedule(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
713+
} else if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
714+
if (k_uptime_get() - link.tx.start > link.tx.timeout * MSEC_PER_SEC) {
715+
LOG_WRN("Giving up transaction");
716+
prov_link_close(PROV_BEARER_LINK_STATUS_TIMEOUT);
717+
return;
718+
}
719+
720+
send_reliable();
721+
}
722+
}
723+
681724
static int prov_send_adv(struct net_buf_simple *msg,
682725
prov_bearer_send_complete_t cb, void *cb_data)
683726
{
@@ -769,8 +812,7 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf)
769812
LOG_DBG("Resending link ack");
770813
/* Ignore errors, message will be attempted again if we keep receiving link open: */
771814
(void)bearer_ctl_send_unacked(
772-
ctl_buf_create(LINK_ACK, NULL, 0, RETRANSMITS_ACK),
773-
(void *)PROV_BEARER_LINK_STATUS_SUCCESS);
815+
ctl_buf_create(LINK_ACK, NULL, 0, RETRANSMITS_ACK));
774816
return;
775817
}
776818

@@ -784,8 +826,7 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf)
784826
net_buf_simple_reset(link.rx.buf);
785827

786828
err = bearer_ctl_send_unacked(
787-
ctl_buf_create(LINK_ACK, NULL, 0, RETRANSMITS_ACK),
788-
(void *)PROV_BEARER_LINK_STATUS_SUCCESS);
829+
ctl_buf_create(LINK_ACK, NULL, 0, RETRANSMITS_ACK));
789830
if (err) {
790831
reset_adv_link();
791832
return;
@@ -926,11 +967,11 @@ static void prov_link_close(enum prov_bearer_link_status status)
926967
* be restransmitted at least three times. Retransmit the LINK_CLOSE
927968
* message until CLOSING_TIMEOUT has elapsed.
928969
*/
929-
link.tx.timeout = CLOSING_TIMEOUT;
930-
/* Ignore errors, the link will time out eventually if this doesn't get sent */
931-
bearer_ctl_send_unacked(
932-
ctl_buf_create(LINK_CLOSE, &status, 1, RETRANSMITS_LINK_CLOSE),
933-
(void *)status);
970+
link.close_link.reason = status;
971+
link.close_link.start = k_uptime_get();
972+
973+
bearer_ctl_send_link_close();
974+
k_work_reschedule(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
934975
}
935976

936977
void bt_mesh_pb_adv_init(void)

0 commit comments

Comments
 (0)