Skip to content

Commit ff20657

Browse files
joerchancarlescufi
authored andcommitted
[nrf fromtree] Bluetooth: host: Fix packet reording in ATT under high ..
load Fix packet reordering in ATT when putting the host under high load. In certain conditions a packet can be transmitted while there is elements in the TX queue in bt_att_send. This means that the packet will skip ahead in the TX queue leading to packet re-ordering. Fix by always appending to the queue, and then initiate sending of the HEAD of the queue. Signed-off-by: Joakim Andersson <[email protected]> (cherry picked from commit d9a89fb) Signed-off-by: Joakim Andersson <[email protected]>
1 parent 3d24489 commit ff20657

File tree

1 file changed

+29
-34
lines changed
  • subsys/bluetooth/host

1 file changed

+29
-34
lines changed

subsys/bluetooth/host/att.c

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,30 @@ static int bt_att_chan_send(struct bt_att_chan *chan, struct net_buf *buf,
471471
return chan_send(chan, buf, cb);
472472
}
473473

474+
static void att_send_process(struct bt_att *att)
475+
{
476+
struct bt_att_chan *chan, *tmp;
477+
struct net_buf *buf;
478+
int err = -ENOENT;
479+
480+
buf = net_buf_get(&att->tx_queue, K_NO_WAIT);
481+
if (!buf) {
482+
return;
483+
}
484+
485+
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
486+
err = bt_att_chan_send(chan, buf, NULL);
487+
if (err >= 0) {
488+
break;
489+
}
490+
}
491+
492+
if (err < 0) {
493+
/* Push it back if it could not be send */
494+
k_queue_prepend(&att->tx_queue._queue, buf);
495+
}
496+
}
497+
474498
static void bt_att_chan_send_rsp(struct bt_att_chan *chan, struct net_buf *buf,
475499
bt_att_chan_sent_t cb)
476500
{
@@ -583,7 +607,7 @@ static int bt_att_chan_req_send(struct bt_att_chan *chan,
583607
return err;
584608
}
585609

586-
static void att_process(struct bt_att *att)
610+
static void att_req_send_process(struct bt_att *att)
587611
{
588612
sys_snode_t *node;
589613
struct bt_att_chan *chan, *tmp;
@@ -649,7 +673,7 @@ static uint8_t att_handle_rsp(struct bt_att_chan *chan, void *pdu, uint16_t len,
649673

650674
process:
651675
/* Process pending requests */
652-
att_process(chan->att);
676+
att_req_send_process(chan->att);
653677
if (func) {
654678
func(chan->att->conn, err, pdu, len, params);
655679
}
@@ -2993,9 +3017,7 @@ void bt_att_req_free(struct bt_att_req *req)
29933017
int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb,
29943018
void *user_data)
29953019
{
2996-
struct bt_att_chan *chan, *tmp;
29973020
struct bt_att *att;
2998-
int ret;
29993021

30003022
__ASSERT_NO_MSG(conn);
30013023
__ASSERT_NO_MSG(buf);
@@ -3014,28 +3036,15 @@ int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb,
30143036
user_data);
30153037
}
30163038

3017-
ret = 0;
3018-
3019-
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
3020-
ret = bt_att_chan_send(chan, buf, NULL);
3021-
if (ret >= 0) {
3022-
break;
3023-
}
3024-
}
3025-
3026-
if (ret < 0) {
3027-
/* Queue buffer to be send later */
3028-
BT_DBG("Queueing buffer %p", buf);
3029-
net_buf_put(&att->tx_queue, buf);
3030-
}
3039+
net_buf_put(&att->tx_queue, buf);
3040+
att_send_process(att);
30313041

30323042
return 0;
30333043
}
30343044

30353045
int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req)
30363046
{
30373047
struct bt_att *att;
3038-
struct bt_att_chan *chan, *tmp;
30393048

30403049
BT_DBG("conn %p req %p", conn, req);
30413050

@@ -3049,22 +3058,8 @@ int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req)
30493058
return -ENOTCONN;
30503059
}
30513060

3052-
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
3053-
/* If there is nothing pending use the channel */
3054-
if (!chan->req) {
3055-
int ret;
3056-
3057-
ret = bt_att_chan_req_send(chan, req);
3058-
if (ret >= 0) {
3059-
return ret;
3060-
}
3061-
}
3062-
}
3063-
3064-
/* Queue the request to be send later */
30653061
sys_slist_append(&att->reqs, &req->node);
3066-
3067-
BT_DBG("req %p queued", req);
3062+
att_req_send_process(att);
30683063

30693064
return 0;
30703065
}

0 commit comments

Comments
 (0)