Skip to content

Commit 11770f4

Browse files
pvVudentz
authored andcommitted
Bluetooth: L2CAP: add TX timestamping
Support TX timestamping in L2CAP sockets. Support MSG_ERRQUEUE recvmsg. For other than SOCK_STREAM L2CAP sockets, if a packet from sendmsg() is fragmented, only the first ACL fragment is timestamped. For SOCK_STREAM L2CAP sockets, use the bytestream convention and timestamp the last fragment and count bytes in tskey. Timestamps are not generated in the Enhanced Retransmission mode, as meaning of COMPLETION stamp is unclear if L2CAP layer retransmits. Signed-off-by: Pauli Virtanen <pav@iki.fi> Reviewed-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
1 parent d415ba2 commit 11770f4

File tree

5 files changed

+56
-7
lines changed

5 files changed

+56
-7
lines changed

include/net/bluetooth/l2cap.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason);
955955
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
956956
bdaddr_t *dst, u8 dst_type, u16 timeout);
957957
int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu);
958-
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
958+
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
959+
const struct sockcm_cookie *sockc);
959960
void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
960961
void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail);
961962
int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);

net/bluetooth/6lowpan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb,
444444
memset(&msg, 0, sizeof(msg));
445445
iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iv, 1, skb->len);
446446

447-
err = l2cap_chan_send(chan, &msg, skb->len);
447+
err = l2cap_chan_send(chan, &msg, skb->len, NULL);
448448
if (err > 0) {
449449
netdev->stats.tx_bytes += err;
450450
netdev->stats.tx_packets++;

net/bluetooth/l2cap_core.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,7 +2515,33 @@ static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
25152515
skb_queue_len(&chan->tx_q));
25162516
}
25172517

2518-
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
2518+
static void l2cap_tx_timestamp(struct sk_buff *skb,
2519+
const struct sockcm_cookie *sockc,
2520+
size_t len)
2521+
{
2522+
struct sock *sk = skb ? skb->sk : NULL;
2523+
2524+
if (sk && sk->sk_type == SOCK_STREAM)
2525+
hci_setup_tx_timestamp(skb, len, sockc);
2526+
else
2527+
hci_setup_tx_timestamp(skb, 1, sockc);
2528+
}
2529+
2530+
static void l2cap_tx_timestamp_seg(struct sk_buff_head *queue,
2531+
const struct sockcm_cookie *sockc,
2532+
size_t len)
2533+
{
2534+
struct sk_buff *skb = skb_peek(queue);
2535+
struct sock *sk = skb ? skb->sk : NULL;
2536+
2537+
if (sk && sk->sk_type == SOCK_STREAM)
2538+
l2cap_tx_timestamp(skb_peek_tail(queue), sockc, len);
2539+
else
2540+
l2cap_tx_timestamp(skb, sockc, len);
2541+
}
2542+
2543+
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
2544+
const struct sockcm_cookie *sockc)
25192545
{
25202546
struct sk_buff *skb;
25212547
int err;
@@ -2530,6 +2556,8 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
25302556
if (IS_ERR(skb))
25312557
return PTR_ERR(skb);
25322558

2559+
l2cap_tx_timestamp(skb, sockc, len);
2560+
25332561
l2cap_do_send(chan, skb);
25342562
return len;
25352563
}
@@ -2553,6 +2581,8 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
25532581
if (err)
25542582
return err;
25552583

2584+
l2cap_tx_timestamp_seg(&seg_queue, sockc, len);
2585+
25562586
skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
25572587

25582588
l2cap_le_flowctl_send(chan);
@@ -2574,6 +2604,8 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
25742604
if (IS_ERR(skb))
25752605
return PTR_ERR(skb);
25762606

2607+
l2cap_tx_timestamp(skb, sockc, len);
2608+
25772609
l2cap_do_send(chan, skb);
25782610
err = len;
25792611
break;
@@ -2597,10 +2629,13 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
25972629
if (err)
25982630
break;
25992631

2600-
if (chan->mode == L2CAP_MODE_ERTM)
2632+
if (chan->mode == L2CAP_MODE_ERTM) {
2633+
/* TODO: ERTM mode timestamping */
26012634
l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
2602-
else
2635+
} else {
2636+
l2cap_tx_timestamp_seg(&seg_queue, sockc, len);
26032637
l2cap_streaming_send(chan, &seg_queue);
2638+
}
26042639

26052640
err = len;
26062641

net/bluetooth/l2cap_sock.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,7 @@ static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg,
11061106
{
11071107
struct sock *sk = sock->sk;
11081108
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1109+
struct sockcm_cookie sockc;
11091110
int err;
11101111

11111112
BT_DBG("sock %p, sk %p", sock, sk);
@@ -1120,14 +1121,22 @@ static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg,
11201121
if (sk->sk_state != BT_CONNECTED)
11211122
return -ENOTCONN;
11221123

1124+
hci_sockcm_init(&sockc, sk);
1125+
1126+
if (msg->msg_controllen) {
1127+
err = sock_cmsg_send(sk, msg, &sockc);
1128+
if (err)
1129+
return err;
1130+
}
1131+
11231132
lock_sock(sk);
11241133
err = bt_sock_wait_ready(sk, msg->msg_flags);
11251134
release_sock(sk);
11261135
if (err)
11271136
return err;
11281137

11291138
l2cap_chan_lock(chan);
1130-
err = l2cap_chan_send(chan, msg, len);
1139+
err = l2cap_chan_send(chan, msg, len, &sockc);
11311140
l2cap_chan_unlock(chan);
11321141

11331142
return err;
@@ -1168,6 +1177,10 @@ static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg,
11681177
struct l2cap_pinfo *pi = l2cap_pi(sk);
11691178
int err;
11701179

1180+
if (unlikely(flags & MSG_ERRQUEUE))
1181+
return sock_recv_errqueue(sk, msg, len, SOL_BLUETOOTH,
1182+
BT_SCM_ERROR);
1183+
11711184
lock_sock(sk);
11721185

11731186
if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP,

net/bluetooth/smp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
608608

609609
iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, iv, 2, 1 + len);
610610

611-
l2cap_chan_send(chan, &msg, 1 + len);
611+
l2cap_chan_send(chan, &msg, 1 + len, NULL);
612612

613613
if (!chan->data)
614614
return;

0 commit comments

Comments
 (0)