Skip to content

Commit

Permalink
bluetooth: mesh: Remove illegal use of NET_BUF_FRAG in friend.c
Browse files Browse the repository at this point in the history
This commit removes illegal use of NET_BUF_FRAG in friend.c, which is an
internal flag.

Now `struct bt_mesh_friend_seg` keeps pointer to a first received
segment of a segmented message. The rest segments are added as fragments
using net_buf API. Friend Queue keeps only head of the fragments.
When one segment (currently head of fragments) is removed from Friend
Queue, the next segment is added to the queue. Head has always 2
references: one when allocated, another one when added as fragments
head.

Signed-off-by: Pavel Vasilyev <[email protected]>
  • Loading branch information
PavelVPV authored and jhedberg committed Dec 6, 2022
1 parent 3d306c1 commit 5d05911
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 27 deletions.
65 changes: 39 additions & 26 deletions subsys/bluetooth/mesh/friend.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,22 @@ 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
Expand Down Expand Up @@ -166,8 +175,10 @@ 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];

purge_buffers(&seg->queue);
seg->seg_count = 0U;
if (seg->buf) {
purge_seg_buffers(seg->buf);
seg->seg_count = 0U;
}
}

STRUCT_SECTION_FOREACH(bt_mesh_friend_cb, cb) {
Expand Down Expand Up @@ -1054,7 +1065,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)

static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_zero)
{
struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue);
struct net_buf *buf = seg->buf;
struct net_buf_simple_state state;
uint16_t buf_seq_zero;
uint16_t buf_src;
Expand Down Expand Up @@ -1087,7 +1098,7 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
return seg;
}

if (!unassigned && !sys_slist_peek_head(&seg->queue)) {
if (!unassigned && !seg->buf) {
unassigned = seg;
}
}
Expand Down Expand Up @@ -1122,16 +1133,13 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
return;
}

net_buf_slist_put(&seg->queue, buf);
seg->buf = net_buf_frag_add(seg->buf, buf);

if (type == BT_MESH_FRIEND_PDU_COMPLETE) {
sys_slist_merge_slist(&frnd->queue, &seg->queue);
net_buf_slist_put(&frnd->queue, seg->buf);

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;
}
}

Expand Down Expand Up @@ -1248,6 +1256,15 @@ 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);
Expand All @@ -1256,10 +1273,6 @@ 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--;

Expand Down Expand Up @@ -1333,16 +1346,11 @@ 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;
Expand Down Expand Up @@ -1636,11 +1644,16 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t add
frnd->queue_size--;
avail_space++;

pending_segments = (buf->flags & NET_BUF_FRAGS);
if (buf != net_buf_frag_last(buf)) {
struct net_buf *next;

next = net_buf_frag_del(NULL, buf);

/* Make sure old slist entry state doesn't remain */
buf->frags = NULL;
buf->flags &= ~NET_BUF_FRAGS;
net_buf_frag_add(NULL, next);
sys_slist_prepend(&frnd->queue, &next->node);

pending_segments = true;
}

net_buf_unref(buf);
}
Expand Down Expand Up @@ -1761,7 +1774,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_buffers(&seg->queue);
purge_seg_buffers(seg->buf);
seg->seg_count = 0U;
break;
}
Expand Down
5 changes: 4 additions & 1 deletion subsys/bluetooth/mesh/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ struct bt_mesh_friend {
struct k_work_delayable timer;

struct bt_mesh_friend_seg {
sys_slist_t queue;
/* First received segment of a segmented message. Rest
* segments are added as net_buf fragments.
*/
struct net_buf *buf;

/* The target number of segments, i.e. not necessarily
* the current number of segments, in the queue. This is
Expand Down

0 comments on commit 5d05911

Please sign in to comment.