Skip to content

Commit c393bfd

Browse files
Johan Hedbergjhedberg
authored andcommitted
Bluetooth: Mesh: Fix Friend messaging state tracking
There were several issues with the code: - queue_size wasn't properly kept up to date, leading to erroneous buffer discarding logic. - Poll timeout when there were buffers in the Friend Queue didn't work because we didn't track if there'd been a preceding request for messages or not (hence the added pending_req variable). - We would overwrite the recv_delay timer if there was another request while the previous one was still sending (a likely scenario if we send out multiple advertising events per packet). - We weren't canceling the sending of a buffer if the Friendship was suddenly cleared. Signed-off-by: Johan Hedberg <[email protected]>
1 parent 49c5e55 commit c393bfd

File tree

2 files changed

+54
-29
lines changed

2 files changed

+54
-29
lines changed

subsys/bluetooth/host/mesh/friend.c

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,9 @@ static void discard_buffer(void)
7575
}
7676
}
7777

78-
BT_WARN("Discarding buffer for LPN 0x%04x", frnd->lpn);
79-
8078
buf = net_buf_slist_get(&frnd->queue);
8179
__ASSERT_NO_MSG(buf != NULL);
80+
BT_WARN("Discarding buffer %p for LPN 0x%04x", buf, frnd->lpn);
8281
net_buf_unref(buf);
8382
}
8483

@@ -163,6 +162,11 @@ static void friend_clear(struct bt_mesh_friend *frnd)
163162
friend_cred_del(frnd->net_idx, frnd->lpn);
164163

165164
if (frnd->last) {
165+
/* Cancel the sending if necessary */
166+
if (frnd->pending_buf) {
167+
BT_MESH_ADV(frnd->last)->busy = 0;
168+
}
169+
166170
net_buf_unref(frnd->last);
167171
frnd->last = NULL;
168172
}
@@ -184,6 +188,7 @@ static void friend_clear(struct bt_mesh_friend *frnd)
184188
frnd->pending_buf = 0;
185189
frnd->fsn = 0;
186190
frnd->queue_size = 0;
191+
frnd->pending_req = 0;
187192
memset(frnd->sub_list, 0, sizeof(frnd->sub_list));
188193
}
189194

@@ -440,6 +445,13 @@ static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact)
440445
frnd->send_last = 1;
441446
}
442447

448+
static void friend_recv_delay(struct bt_mesh_friend *frnd)
449+
{
450+
frnd->pending_req = 1;
451+
k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
452+
BT_DBG("Waiting RecvDelay of %d ms", recv_delay(frnd));
453+
}
454+
443455
int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
444456
struct net_buf_simple *buf)
445457
{
@@ -462,7 +474,7 @@ int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
462474
return 0;
463475
}
464476

465-
k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
477+
friend_recv_delay(frnd);
466478

467479
xact = net_buf_simple_pull_u8(buf);
468480

@@ -472,8 +484,6 @@ int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
472484

473485
enqueue_sub_cfm(frnd, xact);
474486

475-
BT_DBG("Waiting RecvDelay of %d ms", recv_delay(frnd));
476-
477487
return 0;
478488
}
479489

@@ -499,7 +509,7 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
499509
return 0;
500510
}
501511

502-
k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
512+
friend_recv_delay(frnd);
503513

504514
xact = net_buf_simple_pull_u8(buf);
505515

@@ -509,8 +519,6 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
509519

510520
enqueue_sub_cfm(frnd, xact);
511521

512-
BT_DBG("Waiting RecvDelay of %d ms", recv_delay(frnd));
513-
514522
return 0;
515523
}
516524

@@ -560,19 +568,24 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
560568
return 0;
561569
}
562570

563-
k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
571+
BT_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn);
572+
573+
friend_recv_delay(frnd);
564574

565575
if (!frnd->established) {
566576
BT_DBG("Friendship established with 0x%04x", frnd->lpn);
567577
frnd->established = 1;
568578
}
569579

570-
BT_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn);
571-
572580
if (msg->fsn == frnd->fsn && frnd->last) {
573581
BT_DBG("Re-sending last PDU");
574582
frnd->send_last = 1;
575583
} else {
584+
if (frnd->last) {
585+
net_buf_unref(frnd->last);
586+
frnd->last = NULL;
587+
}
588+
576589
frnd->fsn = msg->fsn;
577590

578591
if (sys_slist_is_empty(&frnd->queue)) {
@@ -581,8 +594,6 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
581594
}
582595
}
583596

584-
BT_DBG("Waiting RecvDelay of %d ms", recv_delay(frnd));
585-
586597
return 0;
587598
}
588599

@@ -733,7 +744,12 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
733744

734745
frnd->counter++;
735746

736-
enqueue_buf(frnd, buf);
747+
if (frnd->last) {
748+
net_buf_unref(frnd->last);
749+
}
750+
751+
frnd->last = buf;
752+
frnd->send_last = 1;
737753
}
738754

739755
#define RECV_WIN CONFIG_BT_MESH_FRIEND_RECV_WIN
@@ -944,6 +960,12 @@ static void buf_send_start(u16_t duration, int err, void *user_data)
944960
BT_DBG("err %d", err);
945961

946962
frnd->pending_buf = 0;
963+
964+
/* Friend Offer doesn't follow the re-sending semantics */
965+
if (!frnd->established) {
966+
net_buf_unref(frnd->last);
967+
frnd->last = NULL;
968+
}
947969
}
948970

949971
static void buf_send_end(int err, void *user_data)
@@ -952,17 +974,18 @@ static void buf_send_end(int err, void *user_data)
952974

953975
BT_DBG("err %d", err);
954976

977+
if (frnd->pending_req) {
978+
BT_WARN("Another request before previous completed sending");
979+
return;
980+
}
981+
955982
if (frnd->established) {
956983
k_delayed_work_submit(&frnd->timer, frnd->poll_to);
957984
BT_DBG("Waiting %u ms for next poll", frnd->poll_to);
958985
} else {
959986
/* Friend offer timeout is 1 second */
960987
k_delayed_work_submit(&frnd->timer, K_SECONDS(1));
961988
BT_DBG("Waiting for first poll");
962-
963-
/* Friend Offer doesn't follow the re-sending semantics */
964-
net_buf_unref(frnd->last);
965-
frnd->last = NULL;
966989
}
967990
}
968991

@@ -981,31 +1004,30 @@ static void friend_timeout(struct k_work *work)
9811004
frnd->send_last, frnd->last);
9821005

9831006
if (frnd->send_last && frnd->last) {
984-
BT_DBG("Sending frnd->last");
1007+
BT_DBG("Sending frnd->last %p", frnd->last);
9851008
frnd->send_last = 0;
9861009
goto send_last;
9871010
}
9881011

989-
if (frnd->last) {
990-
net_buf_unref(frnd->last);
1012+
if (frnd->established && !frnd->pending_req) {
1013+
BT_WARN("Friendship lost with 0x%04x", frnd->lpn);
1014+
friend_clear(frnd);
1015+
return;
9911016
}
9921017

993-
/* If the timeout is triggered without anything in the queue, it
994-
* means that there was no poll/req from the LPN and the timeout
995-
* occured because we hit the poll timeout.
996-
*/
9971018
frnd->last = net_buf_slist_get(&frnd->queue);
9981019
if (!frnd->last) {
999-
BT_WARN("Friendship %s",
1000-
frnd->established ? "lost" : "not established");
1020+
BT_WARN("Friendship not established with 0x%04x", frnd->lpn);
10011021
friend_clear(frnd);
10021022
return;
10031023
}
10041024

10051025
BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
10061026
frnd->last, frnd->lpn);
1027+
frnd->queue_size--;
10071028

10081029
send_last:
1030+
frnd->pending_req = 0;
10091031
frnd->pending_buf = 1;
10101032
bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
10111033
}
@@ -1049,6 +1071,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
10491071
BT_DBG("Removing old ack from Friend Queue");
10501072

10511073
sys_slist_remove(&frnd->queue, prev, cur);
1074+
frnd->queue_size--;
10521075
/* Make sure old slist entry state doesn't remain */
10531076
buf->frags = NULL;
10541077

@@ -1066,7 +1089,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
10661089
struct friend_pdu_info info;
10671090
struct net_buf *buf;
10681091

1069-
BT_DBG("LPN 0x%04x", frnd->lpn);
1092+
BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size);
10701093

10711094
if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) {
10721095
friend_purge_old_ack(frnd, seq_auth, rx->ctx.addr);
@@ -1101,7 +1124,8 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
11011124

11021125
enqueue_friend_pdu(frnd, type, buf);
11031126

1104-
BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
1127+
BT_DBG("Queued message for LPN 0x%04x, queue_size %u",
1128+
frnd->lpn, frnd->queue_size);
11051129
}
11061130

11071131
static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,

subsys/bluetooth/host/mesh/net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct bt_mesh_friend {
7878
u8_t recv_delay;
7979
u8_t fsn:1,
8080
send_last:1,
81+
pending_req:1,
8182
sec_update:1,
8283
pending_buf:1,
8384
valid:1,

0 commit comments

Comments
 (0)