Skip to content

Commit ce60b92

Browse files
surbanVudentz
authored andcommitted
Bluetooth: compute LE flow credits based on recvbuf space
Previously LE flow credits were returned to the sender even if the socket's receive buffer was full. This meant that no back-pressure was applied to the sender, thus it continued to send data, resulting in data loss without any error being reported. Furthermore, the amount of credits was essentially fixed to a small amount, leading to reduced performance. This is fixed by computing the number of returned LE flow credits based on the estimated available space in the receive buffer of an L2CAP socket. Consequently, if the receive buffer is full, no credits are returned until the buffer is read and thus cleared by user-space. Since the computation of available receive buffer space can only be performed approximately (due to sk_buff overhead) and the receive buffer size may be changed by user-space after flow credits have been sent, superfluous received data is temporary stored within l2cap_pinfo. This is necessary because Bluetooth LE provides no retransmission mechanism once the data has been acked by the physical layer. If receive buffer space estimation is not possible at the moment, we fall back to providing credits for one full packet as before. This is currently the case during connection setup, when MPS is not yet available. Fixes: b1c325c ("Bluetooth: Implement returning of LE L2CAP credits") Signed-off-by: Sebastian Urban <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 73b2652 commit ce60b92

File tree

3 files changed

+132
-26
lines changed

3 files changed

+132
-26
lines changed

include/net/bluetooth/l2cap.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,9 @@ struct l2cap_chan {
554554
__u16 tx_credits;
555555
__u16 rx_credits;
556556

557+
/* estimated available receive buffer space or -1 if unknown */
558+
ssize_t rx_avail;
559+
557560
__u8 tx_state;
558561
__u8 rx_state;
559562

@@ -688,10 +691,15 @@ struct l2cap_user {
688691
/* ----- L2CAP socket info ----- */
689692
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
690693

694+
struct l2cap_rx_busy {
695+
struct list_head list;
696+
struct sk_buff *skb;
697+
};
698+
691699
struct l2cap_pinfo {
692700
struct bt_sock bt;
693701
struct l2cap_chan *chan;
694-
struct sk_buff *rx_busy_skb;
702+
struct list_head rx_busy;
695703
};
696704

697705
enum {
@@ -949,6 +957,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
949957
int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu);
950958
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
951959
void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
960+
void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail);
952961
int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);
953962
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
954963
int l2cap_ertm_init(struct l2cap_chan *chan);

net/bluetooth/l2cap_core.c

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@ struct l2cap_chan *l2cap_chan_create(void)
457457
/* Set default lock nesting level */
458458
atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
459459

460+
/* Available receive buffer space is initially unknown */
461+
chan->rx_avail = -1;
462+
460463
write_lock(&chan_list_lock);
461464
list_add(&chan->global_l, &chan_list);
462465
write_unlock(&chan_list_lock);
@@ -538,6 +541,28 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
538541
}
539542
EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
540543

544+
static __u16 l2cap_le_rx_credits(struct l2cap_chan *chan)
545+
{
546+
size_t sdu_len = chan->sdu ? chan->sdu->len : 0;
547+
548+
if (chan->mps == 0)
549+
return 0;
550+
551+
/* If we don't know the available space in the receiver buffer, give
552+
* enough credits for a full packet.
553+
*/
554+
if (chan->rx_avail == -1)
555+
return (chan->imtu / chan->mps) + 1;
556+
557+
/* If we know how much space is available in the receive buffer, give
558+
* out as many credits as would fill the buffer.
559+
*/
560+
if (chan->rx_avail <= sdu_len)
561+
return 0;
562+
563+
return DIV_ROUND_UP(chan->rx_avail - sdu_len, chan->mps);
564+
}
565+
541566
static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
542567
{
543568
chan->sdu = NULL;
@@ -546,8 +571,7 @@ static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
546571
chan->tx_credits = tx_credits;
547572
/* Derive MPS from connection MTU to stop HCI fragmentation */
548573
chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
549-
/* Give enough credits for a full packet */
550-
chan->rx_credits = (chan->imtu / chan->mps) + 1;
574+
chan->rx_credits = l2cap_le_rx_credits(chan);
551575

552576
skb_queue_head_init(&chan->tx_q);
553577
}
@@ -559,7 +583,7 @@ static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits)
559583
/* L2CAP implementations shall support a minimum MPS of 64 octets */
560584
if (chan->mps < L2CAP_ECRED_MIN_MPS) {
561585
chan->mps = L2CAP_ECRED_MIN_MPS;
562-
chan->rx_credits = (chan->imtu / chan->mps) + 1;
586+
chan->rx_credits = l2cap_le_rx_credits(chan);
563587
}
564588
}
565589

@@ -6512,9 +6536,7 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
65126536
{
65136537
struct l2cap_conn *conn = chan->conn;
65146538
struct l2cap_le_credits pkt;
6515-
u16 return_credits;
6516-
6517-
return_credits = (chan->imtu / chan->mps) + 1;
6539+
u16 return_credits = l2cap_le_rx_credits(chan);
65186540

65196541
if (chan->rx_credits >= return_credits)
65206542
return;
@@ -6533,6 +6555,19 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
65336555
l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
65346556
}
65356557

6558+
void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail)
6559+
{
6560+
if (chan->rx_avail == rx_avail)
6561+
return;
6562+
6563+
BT_DBG("chan %p has %zd bytes avail for rx", chan, rx_avail);
6564+
6565+
chan->rx_avail = rx_avail;
6566+
6567+
if (chan->state == BT_CONNECTED)
6568+
l2cap_chan_le_send_credits(chan);
6569+
}
6570+
65366571
static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
65376572
{
65386573
int err;
@@ -6542,6 +6577,12 @@ static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
65426577
/* Wait recv to confirm reception before updating the credits */
65436578
err = chan->ops->recv(chan, skb);
65446579

6580+
if (err < 0 && chan->rx_avail != -1) {
6581+
BT_ERR("Queueing received LE L2CAP data failed");
6582+
l2cap_send_disconn_req(chan, ECONNRESET);
6583+
return err;
6584+
}
6585+
65456586
/* Update credits whenever an SDU is received */
65466587
l2cap_chan_le_send_credits(chan);
65476588

@@ -6564,7 +6605,8 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
65646605
}
65656606

65666607
chan->rx_credits--;
6567-
BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
6608+
BT_DBG("chan %p: rx_credits %u -> %u",
6609+
chan, chan->rx_credits + 1, chan->rx_credits);
65686610

65696611
/* Update if remote had run out of credits, this should only happens
65706612
* if the remote is not using the entire MPS.

net/bluetooth/l2cap_sock.c

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,34 @@ static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg,
11311131
return err;
11321132
}
11331133

1134+
static void l2cap_publish_rx_avail(struct l2cap_chan *chan)
1135+
{
1136+
struct sock *sk = chan->data;
1137+
ssize_t avail = sk->sk_rcvbuf - atomic_read(&sk->sk_rmem_alloc);
1138+
int expected_skbs, skb_overhead;
1139+
1140+
if (avail <= 0) {
1141+
l2cap_chan_rx_avail(chan, 0);
1142+
return;
1143+
}
1144+
1145+
if (!chan->mps) {
1146+
l2cap_chan_rx_avail(chan, -1);
1147+
return;
1148+
}
1149+
1150+
/* Correct available memory by estimated sk_buff overhead.
1151+
* This is significant due to small transfer sizes. However, accept
1152+
* at least one full packet if receive space is non-zero.
1153+
*/
1154+
expected_skbs = DIV_ROUND_UP(avail, chan->mps);
1155+
skb_overhead = expected_skbs * sizeof(struct sk_buff);
1156+
if (skb_overhead < avail)
1157+
l2cap_chan_rx_avail(chan, avail - skb_overhead);
1158+
else
1159+
l2cap_chan_rx_avail(chan, -1);
1160+
}
1161+
11341162
static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg,
11351163
size_t len, int flags)
11361164
{
@@ -1167,28 +1195,33 @@ static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg,
11671195
else
11681196
err = bt_sock_recvmsg(sock, msg, len, flags);
11691197

1170-
if (pi->chan->mode != L2CAP_MODE_ERTM)
1198+
if (pi->chan->mode != L2CAP_MODE_ERTM &&
1199+
pi->chan->mode != L2CAP_MODE_LE_FLOWCTL &&
1200+
pi->chan->mode != L2CAP_MODE_EXT_FLOWCTL)
11711201
return err;
11721202

1173-
/* Attempt to put pending rx data in the socket buffer */
1174-
11751203
lock_sock(sk);
11761204

1177-
if (!test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state))
1178-
goto done;
1205+
l2cap_publish_rx_avail(pi->chan);
11791206

1180-
if (pi->rx_busy_skb) {
1181-
if (!__sock_queue_rcv_skb(sk, pi->rx_busy_skb))
1182-
pi->rx_busy_skb = NULL;
1183-
else
1207+
/* Attempt to put pending rx data in the socket buffer */
1208+
while (!list_empty(&pi->rx_busy)) {
1209+
struct l2cap_rx_busy *rx_busy =
1210+
list_first_entry(&pi->rx_busy,
1211+
struct l2cap_rx_busy,
1212+
list);
1213+
if (__sock_queue_rcv_skb(sk, rx_busy->skb) < 0)
11841214
goto done;
1215+
list_del(&rx_busy->list);
1216+
kfree(rx_busy);
11851217
}
11861218

11871219
/* Restore data flow when half of the receive buffer is
11881220
* available. This avoids resending large numbers of
11891221
* frames.
11901222
*/
1191-
if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
1223+
if (test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state) &&
1224+
atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
11921225
l2cap_chan_busy(pi->chan, 0);
11931226

11941227
done:
@@ -1449,17 +1482,20 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
14491482
static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
14501483
{
14511484
struct sock *sk = chan->data;
1485+
struct l2cap_pinfo *pi = l2cap_pi(sk);
14521486
int err;
14531487

14541488
lock_sock(sk);
14551489

1456-
if (l2cap_pi(sk)->rx_busy_skb) {
1490+
if (chan->mode == L2CAP_MODE_ERTM && !list_empty(&pi->rx_busy)) {
14571491
err = -ENOMEM;
14581492
goto done;
14591493
}
14601494

14611495
if (chan->mode != L2CAP_MODE_ERTM &&
1462-
chan->mode != L2CAP_MODE_STREAMING) {
1496+
chan->mode != L2CAP_MODE_STREAMING &&
1497+
chan->mode != L2CAP_MODE_LE_FLOWCTL &&
1498+
chan->mode != L2CAP_MODE_EXT_FLOWCTL) {
14631499
/* Even if no filter is attached, we could potentially
14641500
* get errors from security modules, etc.
14651501
*/
@@ -1470,7 +1506,9 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
14701506

14711507
err = __sock_queue_rcv_skb(sk, skb);
14721508

1473-
/* For ERTM, handle one skb that doesn't fit into the recv
1509+
l2cap_publish_rx_avail(chan);
1510+
1511+
/* For ERTM and LE, handle a skb that doesn't fit into the recv
14741512
* buffer. This is important to do because the data frames
14751513
* have already been acked, so the skb cannot be discarded.
14761514
*
@@ -1479,8 +1517,18 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
14791517
* acked and reassembled until there is buffer space
14801518
* available.
14811519
*/
1482-
if (err < 0 && chan->mode == L2CAP_MODE_ERTM) {
1483-
l2cap_pi(sk)->rx_busy_skb = skb;
1520+
if (err < 0 &&
1521+
(chan->mode == L2CAP_MODE_ERTM ||
1522+
chan->mode == L2CAP_MODE_LE_FLOWCTL ||
1523+
chan->mode == L2CAP_MODE_EXT_FLOWCTL)) {
1524+
struct l2cap_rx_busy *rx_busy =
1525+
kmalloc(sizeof(*rx_busy), GFP_KERNEL);
1526+
if (!rx_busy) {
1527+
err = -ENOMEM;
1528+
goto done;
1529+
}
1530+
rx_busy->skb = skb;
1531+
list_add_tail(&rx_busy->list, &pi->rx_busy);
14841532
l2cap_chan_busy(chan, 1);
14851533
err = 0;
14861534
}
@@ -1706,16 +1754,19 @@ static const struct l2cap_ops l2cap_chan_ops = {
17061754

17071755
static void l2cap_sock_destruct(struct sock *sk)
17081756
{
1757+
struct l2cap_rx_busy *rx_busy, *next;
1758+
17091759
BT_DBG("sk %p", sk);
17101760

17111761
if (l2cap_pi(sk)->chan) {
17121762
l2cap_pi(sk)->chan->data = NULL;
17131763
l2cap_chan_put(l2cap_pi(sk)->chan);
17141764
}
17151765

1716-
if (l2cap_pi(sk)->rx_busy_skb) {
1717-
kfree_skb(l2cap_pi(sk)->rx_busy_skb);
1718-
l2cap_pi(sk)->rx_busy_skb = NULL;
1766+
list_for_each_entry_safe(rx_busy, next, &l2cap_pi(sk)->rx_busy, list) {
1767+
kfree_skb(rx_busy->skb);
1768+
list_del(&rx_busy->list);
1769+
kfree(rx_busy);
17191770
}
17201771

17211772
skb_queue_purge(&sk->sk_receive_queue);
@@ -1799,6 +1850,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
17991850

18001851
chan->data = sk;
18011852
chan->ops = &l2cap_chan_ops;
1853+
1854+
l2cap_publish_rx_avail(chan);
18021855
}
18031856

18041857
static struct proto l2cap_proto = {
@@ -1820,6 +1873,8 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
18201873
sk->sk_destruct = l2cap_sock_destruct;
18211874
sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
18221875

1876+
INIT_LIST_HEAD(&l2cap_pi(sk)->rx_busy);
1877+
18231878
chan = l2cap_chan_create();
18241879
if (!chan) {
18251880
sk_free(sk);

0 commit comments

Comments
 (0)