From 7b4f94220dbd5d65d18a2a5c5272fb9c4432a524 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 16 Dec 2022 16:54:39 +0100 Subject: [PATCH] Revert "bluetooth: mesh: Remove illegal use of NET_BUF_FRAG in friend.c" This reverts commit 5d059117fd279ee0eec4fb1c4d0244a37937013c. Signed-off-by: Pavel Vasilyev --- subsys/bluetooth/mesh/friend.c | 65 ++++++++++++++-------------------- subsys/bluetooth/mesh/net.h | 5 +-- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/subsys/bluetooth/mesh/friend.c b/subsys/bluetooth/mesh/friend.c index 5a2670d7176..5a9688e3df8 100644 --- a/subsys/bluetooth/mesh/friend.c +++ b/subsys/bluetooth/mesh/friend.c @@ -135,22 +135,13 @@ static void purge_buffers(sys_slist_t *list) buf = (void *)sys_slist_get_not_empty(list); + buf->frags = NULL; + buf->flags &= ~NET_BUF_FRAGS; + net_buf_unref(buf); } } -static void purge_seg_buffers(struct net_buf *buf) -{ - /* Fragments head has always 2 references: one when allocated, one when becomes - * fragments head. - */ - net_buf_unref(buf); - - do { - buf = net_buf_frag_del(NULL, buf); - } while (buf != NULL); -} - /* Intentionally start a little bit late into the ReceiveWindow when * it's large enough. This may improve reliability with some platforms, * like the PTS, where the receiver might not have sufficiently compensated @@ -186,10 +177,8 @@ static void friend_clear(struct bt_mesh_friend *frnd) for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { struct bt_mesh_friend_seg *seg = &frnd->seg[i]; - if (seg->buf) { - purge_seg_buffers(seg->buf); - seg->seg_count = 0U; - } + purge_buffers(&seg->queue); + seg->seg_count = 0U; } STRUCT_SECTION_FOREACH(bt_mesh_friend_cb, cb) { @@ -1076,7 +1065,7 @@ init_friend: static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_zero) { - struct net_buf *buf = seg->buf; + struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue); struct net_buf_simple_state state; uint16_t buf_seq_zero; uint16_t buf_src; @@ -1109,7 +1098,7 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, return seg; } - if (!unassigned && !seg->buf) { + if (!unassigned && !sys_slist_peek_head(&seg->queue)) { unassigned = seg; } } @@ -1144,13 +1133,16 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, return; } - seg->buf = net_buf_frag_add(seg->buf, buf); + net_buf_slist_put(&seg->queue, buf); if (type == BT_MESH_FRIEND_PDU_COMPLETE) { - net_buf_slist_put(&frnd->queue, seg->buf); + sys_slist_merge_slist(&frnd->queue, &seg->queue); frnd->queue_size += seg->seg_count; seg->seg_count = 0U; + } else { + /* Mark the buffer as having more to come after it */ + buf->flags |= NET_BUF_FRAGS; } } @@ -1267,15 +1259,6 @@ static void friend_timeout(struct k_work *work) return; } - /* Put next segment to the friend queue. */ - if (frnd->last != net_buf_frag_last(frnd->last)) { - struct net_buf *next; - - next = net_buf_frag_del(NULL, frnd->last); - net_buf_frag_add(NULL, next); - sys_slist_prepend(&frnd->queue, &next->node); - } - md = (uint8_t)(sys_slist_peek_head(&frnd->queue) != NULL); update_overwrite(frnd->last, md); @@ -1284,6 +1267,10 @@ static void friend_timeout(struct k_work *work) return; } + /* Clear the flag we use for segment tracking */ + frnd->last->flags &= ~NET_BUF_FRAGS; + frnd->last->frags = NULL; + LOG_DBG("Sending buf %p from Friend Queue of LPN 0x%04x", frnd->last, frnd->lpn); frnd->queue_size--; @@ -1357,11 +1344,16 @@ int bt_mesh_friend_init(void) for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; + int j; sys_slist_init(&frnd->queue); k_work_init_delayable(&frnd->timer, friend_timeout); k_work_init_delayable(&frnd->clear.timer, clear_timeout); + + for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) { + sys_slist_init(&frnd->seg[j].queue); + } } return 0; @@ -1655,16 +1647,11 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t add frnd->queue_size--; avail_space++; - if (buf != net_buf_frag_last(buf)) { - struct net_buf *next; + pending_segments = (buf->flags & NET_BUF_FRAGS); - next = net_buf_frag_del(NULL, buf); - - net_buf_frag_add(NULL, next); - sys_slist_prepend(&frnd->queue, &next->node); - - pending_segments = true; - } + /* Make sure old slist entry state doesn't remain */ + buf->frags = NULL; + buf->flags &= ~NET_BUF_FRAGS; net_buf_unref(buf); } @@ -1785,7 +1772,7 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src, LOG_WRN("Clearing incomplete segments for 0x%04x", src); - purge_seg_buffers(seg->buf); + purge_buffers(&seg->queue); seg->seg_count = 0U; break; } diff --git a/subsys/bluetooth/mesh/net.h b/subsys/bluetooth/mesh/net.h index f8d86951682..a5002bbd68f 100644 --- a/subsys/bluetooth/mesh/net.h +++ b/subsys/bluetooth/mesh/net.h @@ -67,10 +67,7 @@ struct bt_mesh_friend { struct k_work_delayable timer; struct bt_mesh_friend_seg { - /* First received segment of a segmented message. Rest - * segments are added as net_buf fragments. - */ - struct net_buf *buf; + sys_slist_t queue; /* The target number of segments, i.e. not necessarily * the current number of segments, in the queue. This is