Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Pauli Virtanen and committed by
Luiz Augusto von Dentz
11770f41 d415ba28

+56 -7
+2 -1
include/net/bluetooth/l2cap.h
··· 955 955 int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, 956 956 bdaddr_t *dst, u8 dst_type, u16 timeout); 957 957 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); 959 960 void l2cap_chan_busy(struct l2cap_chan *chan, int busy); 960 961 void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail); 961 962 int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);
+1 -1
net/bluetooth/6lowpan.c
··· 444 444 memset(&msg, 0, sizeof(msg)); 445 445 iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iv, 1, skb->len); 446 446 447 - err = l2cap_chan_send(chan, &msg, skb->len); 447 + err = l2cap_chan_send(chan, &msg, skb->len, NULL); 448 448 if (err > 0) { 449 449 netdev->stats.tx_bytes += err; 450 450 netdev->stats.tx_packets++;
+38 -3
net/bluetooth/l2cap_core.c
··· 2515 2515 skb_queue_len(&chan->tx_q)); 2516 2516 } 2517 2517 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) 2519 2545 { 2520 2546 struct sk_buff *skb; 2521 2547 int err; ··· 2555 2529 skb = l2cap_create_connless_pdu(chan, msg, len); 2556 2530 if (IS_ERR(skb)) 2557 2531 return PTR_ERR(skb); 2532 + 2533 + l2cap_tx_timestamp(skb, sockc, len); 2558 2534 2559 2535 l2cap_do_send(chan, skb); 2560 2536 return len; ··· 2581 2553 if (err) 2582 2554 return err; 2583 2555 2556 + l2cap_tx_timestamp_seg(&seg_queue, sockc, len); 2557 + 2584 2558 skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2585 2559 2586 2560 l2cap_le_flowctl_send(chan); ··· 2603 2573 skb = l2cap_create_basic_pdu(chan, msg, len); 2604 2574 if (IS_ERR(skb)) 2605 2575 return PTR_ERR(skb); 2576 + 2577 + l2cap_tx_timestamp(skb, sockc, len); 2606 2578 2607 2579 l2cap_do_send(chan, skb); 2608 2580 err = len; ··· 2629 2597 if (err) 2630 2598 break; 2631 2599 2632 - if (chan->mode == L2CAP_MODE_ERTM) 2600 + if (chan->mode == L2CAP_MODE_ERTM) { 2601 + /* TODO: ERTM mode timestamping */ 2633 2602 l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST); 2634 - else 2603 + } else { 2604 + l2cap_tx_timestamp_seg(&seg_queue, sockc, len); 2635 2605 l2cap_streaming_send(chan, &seg_queue); 2606 + } 2636 2607 2637 2608 err = len; 2638 2609
+14 -1
net/bluetooth/l2cap_sock.c
··· 1106 1106 { 1107 1107 struct sock *sk = sock->sk; 1108 1108 struct l2cap_chan *chan = l2cap_pi(sk)->chan; 1109 + struct sockcm_cookie sockc; 1109 1110 int err; 1110 1111 1111 1112 BT_DBG("sock %p, sk %p", sock, sk); ··· 1121 1120 if (sk->sk_state != BT_CONNECTED) 1122 1121 return -ENOTCONN; 1123 1122 1123 + hci_sockcm_init(&sockc, sk); 1124 + 1125 + if (msg->msg_controllen) { 1126 + err = sock_cmsg_send(sk, msg, &sockc); 1127 + if (err) 1128 + return err; 1129 + } 1130 + 1124 1131 lock_sock(sk); 1125 1132 err = bt_sock_wait_ready(sk, msg->msg_flags); 1126 1133 release_sock(sk); ··· 1136 1127 return err; 1137 1128 1138 1129 l2cap_chan_lock(chan); 1139 - err = l2cap_chan_send(chan, msg, len); 1130 + err = l2cap_chan_send(chan, msg, len, &sockc); 1140 1131 l2cap_chan_unlock(chan); 1141 1132 1142 1133 return err; ··· 1176 1167 struct sock *sk = sock->sk; 1177 1168 struct l2cap_pinfo *pi = l2cap_pi(sk); 1178 1169 int err; 1170 + 1171 + if (unlikely(flags & MSG_ERRQUEUE)) 1172 + return sock_recv_errqueue(sk, msg, len, SOL_BLUETOOTH, 1173 + BT_SCM_ERROR); 1179 1174 1180 1175 lock_sock(sk); 1181 1176
+1 -1
net/bluetooth/smp.c
··· 608 608 609 609 iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, iv, 2, 1 + len); 610 610 611 - l2cap_chan_send(chan, &msg, 1 + len); 611 + l2cap_chan_send(chan, &msg, 1 + len, NULL); 612 612 613 613 if (!chan->data) 614 614 return;