net: Bluetooth: add TX timestamping for ISO/L2CAP/SCO
Subsystems (8)
v5 cover net: Bluetooth: add TX timestamping for ISO/L2CAP/SCO
Add support for TX timestamping in Bluetooth ISO/L2CAP/SCO sockets.
Add new COMPLETION timestamp type, to report a software timestamp when the hardware reports a packet completed. (Cc netdev for this)
Previous discussions:
https://lore.kernel.org/linux-bluetooth/[email protected]/
https://lore.kernel.org/linux-bluetooth/[email protected]/
https://lore.kernel.org/all/[email protected]/
https://lore.kernel.org/all/[email protected]/
Changes
=======
v5:
- Revert to v3 vs decoupled SND & COMPLETION, just use the bit in tx_flags.
- Add hci_sockcm_init() and use it.
- Emit COMPLETION also for SCO if flowctl enabled, now that we enable it for some HW (most HW doesn't seem to support it)
v4:
- Change meaning of SOF_TIMESTAMPING_TX_COMPLETION, to save a bit in skb_shared_info.tx_flags:
It now enables COMPLETION only for packets that also have software SND enabled. The flag can now be enabled only via a socket option, but coupling with SND allows user to still choose for which packets SND+COMPLETION should be generated. This choice maybe is OK for applications which can skip SND if they're not interested.
However, this would make the timestamping API not uniform, as the other TX flags can be enabled via CMSG.
IIUC, sizeof skb_shared_info cannot be easily changed and I'm not sure there is somewhere else in general skb info, where one could safely put the extra separate flag bit for COMPLETION. So here's alternative suggestion.
- Better name in sof_timestamping_names
- I decided to keep using sockcm_init(), to avoid open coding READ_ONCE and since it's passed to sock_cmsg_send() which anyway also may init such fields.
v3:
- Add new COMPLETION timestamp type, and emit it in HCI completion.
- Emit SND instead of SCHED, when sending to driver.
- Do not emit SCHED timestamps.
- Don't safeguard tx_q length explicitly. Now that hci_sched_acl_blk() is no more, the scheduler flow control is guaranteed to keep it bounded.
- Fix L2CAP stream sockets to use the bytestream timestamp conventions.
Overview
========
The packet flow in Bluetooth is the following. Timestamps added here indicated:
user sendmsg() generates skbs
|
* skb waits in net/bluetooth queue for a free HW packet slot |
* orphan skb, send to driver -> TSTAMP_SND
|
* driver: send packet data to transport (eg. USB)
|
* wait for transport completion
|
* driver: transport tx completion, free skb (some do this immediately) |
* packet waits in HW side queue
|
* HCI report for packet completion -> TSTAMP_COMPLETION (for non-SCO)
In addition, we may want to do the following in future (but not implemented in this series as we don't have ISO sequence number synchronization yet which is needed first, moreover e.g. Intel controllers return only zeros in timestamps):
* if packet is ISO, send HCI LE Read ISO TX Sync
|
* HCI response -> hardware TSTAMP_SND for the packet the response corresponds to if it was waiting for one, might not be possible to get a tstamp for every packet
Bluetooth does not have tx timestamps in the completion reports from hardware, and only for ISO packets there are HCI commands in specification for querying timestamps afterward.
The drivers do not provide ways to get timestamps either, I'm also not aware if some devices would have vendor-specific commands to get them.
Driver-side timestamps
======================
Generating SND on driver side may be slightly more accurate, but that requires changing the BT driver API to not orphan skbs first. In theory this probably won't cause problems, but it is not done in this patchset.
For some of the drivers it won't gain much. E.g. btusb immediately submits the URB, so if one would emit SND just before submit (as drivers/net/usb/usbnet.c does), it is essentially identical to emitting before sending to driver. btintel_pcie looks like it does synchronous send, so looks the same. hci_serdev has internal queue, iiuc flushing as fast as data can be transferred, but it shouldn't be waiting for hardware slots due to HCI flow control.
Unless HW buffers are full, packets mostly wait on the HW side. E.g. with btusb (non-SCO) median time from sendmsg() to URB generation is ~0.1 ms, to USB completion ~0.5 ms, and HCI completion report at ~5 ms.
The exception is SCO, for which HCI flow control is disabled, so they do not get completion events so it's possible to build up queues inside the driver. For SCO, COMPLETION needs to be generated from driver side, eg. for btusb maybe at URB completion. This could be useful for SCO PCM modes (but which are more or less obsolete nowadays), where USB isoc data rate matches audio data rate, so queues on USB side may build up.
Use cases
=========
In audio use cases we want to track and avoid queues building up, to control latency, especially in cases like ISO where the controller has a fixed schedule that the sending application must match. E.g. application can aim to keep 1 packet in HW queue, so it has 2*7.5ms of slack for being woken up too late.
Applications can use SND & COMPLETION timestamps to track in-kernel and in-HW packet queues separately. This can matter for ISO, where the specification allows HW to use the timings when it gets packets to determine what packets are synchronized together. Applications can use SND to track that.
Tests
=====
See
https://lore.kernel.org/linux-bluetooth/[email protected]/
Pauli Virtanen (5):
net-timestamp: COMPLETION timestamp on packet tx completion
Bluetooth: add support for skb TX SND/COMPLETION timestamping
Bluetooth: ISO: add TX timestamping
Bluetooth: L2CAP: add TX timestamping
Bluetooth: SCO: add TX timestamping
Documentation/networking/timestamping.rst | 8 ++ include/linux/skbuff.h | 7 +- include/net/bluetooth/bluetooth.h | 1 + include/net/bluetooth/hci_core.h | 20 ++++ include/net/bluetooth/l2cap.h | 3 +- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 +- net/bluetooth/6lowpan.c | 2 +- net/bluetooth/hci_conn.c | 122 ++++++++++++++++++++++ net/bluetooth/hci_core.c | 15 ++- net/bluetooth/hci_event.c | 4 + net/bluetooth/iso.c | 24 ++++- net/bluetooth/l2cap_core.c | 41 +++++++- net/bluetooth/l2cap_sock.c | 15 ++- net/bluetooth/sco.c | 19 +++- net/bluetooth/smp.c | 2 +- net/core/skbuff.c | 2 + net/ethtool/common.c | 1 + net/socket.c | 3 + 19 files changed, 274 insertions(+), 22 deletions(-)
Signature · 1 line
2.48.1
PATCH v5 1/5 net-timestamp: COMPLETION timestamp on packet tx completion
Add SOF_TIMESTAMPING_TX_COMPLETION, for requesting a software timestamp when hardware reports a packet completed.
Completion tstamp is useful for Bluetooth, as hardware timestamps do not exist in the HCI specification except for ISO packets, and the hardware has a queue where packets may wait. In this case the software SND timestamp only reflects the kernel-side part of the total latency (usually small) and queue length (usually 0 unless HW buffers congested), whereas the completion report time is more informative of the true latency.
It may also be useful in other cases where HW TX timestamps cannot be obtained and user wants to estimate an upper bound to when the TX probably happened.
---
Notes:
v5:
- back to decoupled COMPLETION & SND, like in v3
- BPF reporting not implemented here
Documentation/networking/timestamping.rst | 8 ++++++++ include/linux/skbuff.h | 7 ++++--- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 ++++-- net/core/skbuff.c | 2 ++ net/ethtool/common.c | 1 + net/socket.c | 3 +++ 7 files changed, 23 insertions(+), 5 deletions(-)
Documentation/networking/timestamping.rst +8 -0
@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK: cumulative acknowledgment. The mechanism ignores SACK and FACK. This flag can be enabled via both socket options and control messages. +SOF_TIMESTAMPING_TX_COMPLETION: + Request tx timestamps on packet tx completion. The completion + timestamp is generated by the kernel when it receives packet a + completion report from the hardware. Hardware may report multiple + packets at once, and completion timestamps reflect the timing of the + report and not actual tx time. This flag can be enabled via both + socket options and control messages. + 1.3.2 Timestamp Reporting ^^^^^^^^^^^^^^^^^^^^^^^^^
include/linux/skbuff.h +4 -3
@@ -478,8 +478,8 @@ enum {/* device driver is going to provide hardware time stamp */ SKBTX_IN_PROGRESS =1 <<2 , -/* reserved */ -SKBTX_RESERVED =1 <<3 , +/* generate software time stamp on packet tx completion */ +SKBTX_COMPLETION_TSTAMP =1 <<3 ,/* generate wifi status information (where possible) */ SKBTX_WIFI_STATUS = 1 << 4,
@@ -498,7 +498,8 @@ enum {#define SKBTX_ANY_SW_TSTAMP (SKBTX_SW_TSTAMP | \ SKBTX_SCHED_TSTAMP | \ - SKBTX_BPF) + SKBTX_BPF | \ + SKBTX_COMPLETION_TSTAMP)#define SKBTX_ANY_TSTAMP (SKBTX_HW_TSTAMP | \ SKBTX_ANY_SW_TSTAMP)
include/uapi/linux/errqueue.h +1 -0
@@ -73,6 +73,7 @@ enum {SCM_TSTAMP_SND ,/* driver passed skb to NIC, or HW */ SCM_TSTAMP_SCHED ,/* data entered the packet scheduler */ SCM_TSTAMP_ACK ,/* data acknowledged by peer */ + SCM_TSTAMP_COMPLETION, /* packet tx completion */ };#endif /* _UAPI_LINUX_ERRQUEUE_H */
include/uapi/linux/net_tstamp.h +4 -2
@@ -44,8 +44,9 @@ enum {SOF_TIMESTAMPING_BIND_PHC = (1 <<15 ),SOF_TIMESTAMPING_OPT_ID_TCP = (1 <<16 ),SOF_TIMESTAMPING_OPT_RX_FILTER = (1 <<17 ), +SOF_TIMESTAMPING_TX_COMPLETION = (1 <<18 ), -SOF_TIMESTAMPING_LAST =SOF_TIMESTAMPING_OPT_RX_FILTER , +SOF_TIMESTAMPING_LAST =SOF_TIMESTAMPING_TX_COMPLETION ,SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST -1 ) | SOF_TIMESTAMPING_LAST };
@@ -58,7 +59,8 @@ enum {#define SOF_TIMESTAMPING_TX_RECORD_MASK (SOF_TIMESTAMPING_TX_HARDWARE | \ SOF_TIMESTAMPING_TX_SOFTWARE | \ SOF_TIMESTAMPING_TX_SCHED | \ - SOF_TIMESTAMPING_TX_ACK) + SOF_TIMESTAMPING_TX_ACK | \ + SOF_TIMESTAMPING_TX_COMPLETION)/** * struct so_timestamping - SO_TIMESTAMPING parameter
net/core/skbuff.c +2 -0
@@ -5523,6 +5523,8 @@ static bool skb_tstamp_tx_report_so_timestamping(struct sk_buff *skb, SKBTX_SW_TSTAMP);case SCM_TSTAMP_ACK :return TCP_SKB_CB (skb)->txstamp_ack &TSTAMP_ACK_SK ; +case SCM_TSTAMP_COMPLETION : +return skb_shinfo (skb)->tx_flags &SKBTX_COMPLETION_TSTAMP ; }return false;
net/ethtool/common.c +1 -0
@@ -476,6 +476,7 @@ const char sof_timestamping_names[][ETH_GSTRING_LEN] = { [const_ilog2(SOF_TIMESTAMPING_BIND_PHC)] = "bind-phc", [const_ilog2(SOF_TIMESTAMPING_OPT_ID_TCP)] = "option-id-tcp", [const_ilog2(SOF_TIMESTAMPING_OPT_RX_FILTER)] = "option-rx-filter", + [const_ilog2 (SOF_TIMESTAMPING_TX_COMPLETION )] ="tx-completion" , };static_assert (ARRAY_SIZE (sof_timestamping_names) == __SOF_TIMESTAMPING_CNT);
net/socket.c +3 -0
@@ -689,6 +689,9 @@ void __sock_tx_timestamp(__u32 tsflags, __u8 *tx_flags)if (tsflags &SOF_TIMESTAMPING_TX_SCHED ) flags |=SKBTX_SCHED_TSTAMP ; +if (tsflags &SOF_TIMESTAMPING_TX_COMPLETION ) + flags |=SKBTX_COMPLETION_TSTAMP ; + *tx_flags = flags; }EXPORT_SYMBOL (__sock_tx_timestamp);
Signature · 1 line
2.48.1
This is an automated email and please do not reply to this email.
Dear Submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.
----- Output -----
error: patch failed: include/linux/skbuff.h:478
error: include/linux/skbuff.h: patch does not apply
error: patch failed: net/core/skbuff.c:5523
error: net/core/skbuff.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch
Please resolve the issue and submit the patches again.
---
Regards,
Linux Bluetooth
Luiz Augusto von Dentz
maintainerHi Pauli,
Quoted 10 lines · On Tue, Mar 18, 2025 at 3:15 PM <[email protected]> wrote:
This is an automated email and please do not reply to this email.
Dear Submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.----- Output -----
Quoted 7 lines
error: patch failed:
include/linux/skbuff.h:478
error:include/linux/skbuff.h: patch does not apply
error: patch failed:net/core/skbuff.c:5523
error:net/core/skbuff.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patchPlease resolve the issue and submit the patches again.
Did you base in something other than bluetooth-next? Do we need to rebase bluetooth-next to net-next perhaps?
Signature · 1 line
Luiz Augusto von Dentz
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=945296
---Test result---
Test Summary:
CheckPatch PENDING 0.24 seconds GitLint PENDING 0.25 seconds SubjectPrefix FAIL 0.75 seconds BuildKernel PASS 24.54 seconds CheckAllWarning PASS 27.22 seconds CheckSparse WARNING 31.06 seconds BuildKernel32 PASS 24.33 seconds TestRunnerSetup PASS 432.00 seconds TestRunner_l2cap-tester FAIL 21.34 seconds TestRunner_iso-tester PASS 28.24 seconds TestRunner_bnep-tester PASS 4.78 seconds TestRunner_mgmt-tester PASS 121.31 seconds TestRunner_rfcomm-tester PASS 7.82 seconds TestRunner_sco-tester PASS 12.14 seconds TestRunner_ioctl-tester PASS 8.36 seconds TestRunner_mesh-tester PASS 5.88 seconds TestRunner_smp-tester PASS 7.18 seconds TestRunner_userchan-tester PASS 4.96 seconds IncrementalBuild PENDING 0.86 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: SubjectPrefix - FAIL
Desc: Check subject contains "Bluetooth" prefix
Output:
"Bluetooth: " prefix is not specified in the subject
##############################
Test: CheckSparse - WARNING
Desc: Run sparse tool with linux kernel
Output:net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):net/bluetooth/sco.c: note: in included file:./include/net/bluetooth/hci_core.h:147:35: warning: array of flexible structures
##############################
Test: TestRunner_l2cap-tester - FAIL
Desc: Run l2cap-tester with test-runner
Output:
Total: 61, Passed: 58 (95.1%), Failed: 1, Not Run: 2
Failed Test Cases
L2CAP LE Client - Write 32k Success Failed 0.402 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series Output:
---
Regards,
Linux Bluetooth
Re: [PATCH v5 1/5] net-timestamp: COMPLETION timestamp on packet tx completion
In reply to Pauli VirtanenQuoted 12 lines · Pauli Virtanen
Add
SOF_TIMESTAMPING_TX_COMPLETION, for requesting a software timestamp when hardware reports a packet completed.Completion tstamp is useful for Bluetooth, as hardware timestamps do not exist in the HCI specification except for ISO packets, and the hardware has a queue where packets may wait. In this case the software SND timestamp only reflects the kernel-side part of the total latency (usually small) and queue length (usually 0 unless HW buffers congested), whereas the completion report time is more informative of the true latency.
Quoted 5 lines
It may also be useful in other cases where HW TX timestamps cannot be obtained and user wants to estimate an upper bound to when the TX probably happened.
Signed-off-by Pauli Virtanen <[email protected]>
Hi Pauli,
This patch overall looks good to me but it depends on the small question in another patch that is relevant to how we use this new flag in reality. Let's discuss a bit there.
Thanks,
Jason
Quoted 140 lines
---
Notes:
v5:
- back to decoupled COMPLETION & SND, like in v3
- BPF reporting not implemented hereDocumentation/networking/timestamping.rst | 8 ++++++++ include/linux/skbuff.h | 7 ++++--- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 ++++-- net/core/skbuff.c | 2 ++ net/ethtool/common.c | 1 + net/socket.c | 3 +++ 7 files changed, 23 insertions(+), 5 deletions(-)Documentation/networking/timestamping.rst +8
-0@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK: cumulative acknowledgment. The mechanism ignores SACK and FACK. This flag can be enabled via both socket options and control messages. +SOF_TIMESTAMPING_TX_COMPLETION: + Request tx timestamps on packet tx completion. The completion + timestamp is generated by the kernel when it receives packet a + completion report from the hardware. Hardware may report multiple + packets at once, and completion timestamps reflect the timing of the + report and not actual tx time. This flag can be enabled via both + socket options and control messages. + 1.3.2 Timestamp Reporting ^^^^^^^^^^^^^^^^^^^^^^^^^include/linux/skbuff.h +4
-3@@ -478,8 +478,8 @@ enum {/* device driver is going to provide hardware time stamp */ SKBTX_IN_PROGRESS =1 <<2 , -/* reserved */ -SKBTX_RESERVED =1 <<3 , +/* generate software time stamp on packet tx completion */ +SKBTX_COMPLETION_TSTAMP =1 <<3 ,/* generate wifi status information (where possible) */ SKBTX_WIFI_STATUS = 1 << 4,@@ -498,7 +498,8 @@ enum {#define SKBTX_ANY_SW_TSTAMP (SKBTX_SW_TSTAMP | \ SKBTX_SCHED_TSTAMP | \ - SKBTX_BPF) + SKBTX_BPF | \ + SKBTX_COMPLETION_TSTAMP)#define SKBTX_ANY_TSTAMP (SKBTX_HW_TSTAMP | \ SKBTX_ANY_SW_TSTAMP)include/uapi/linux/errqueue.h +1
-0@@ -73,6 +73,7 @@ enum {SCM_TSTAMP_SND ,/* driver passed skb to NIC, or HW */ SCM_TSTAMP_SCHED ,/* data entered the packet scheduler */ SCM_TSTAMP_ACK ,/* data acknowledged by peer */ + SCM_TSTAMP_COMPLETION, /* packet tx completion */ };#endif /* _UAPI_LINUX_ERRQUEUE_H */ include/uapi/linux/net_tstamp.h +4
-2@@ -44,8 +44,9 @@ enum {SOF_TIMESTAMPING_BIND_PHC = (1 <<15 ),SOF_TIMESTAMPING_OPT_ID_TCP = (1 <<16 ),SOF_TIMESTAMPING_OPT_RX_FILTER = (1 <<17 ), +SOF_TIMESTAMPING_TX_COMPLETION = (1 <<18 ), -SOF_TIMESTAMPING_LAST =SOF_TIMESTAMPING_OPT_RX_FILTER , +SOF_TIMESTAMPING_LAST =SOF_TIMESTAMPING_TX_COMPLETION ,SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST -1 ) | SOF_TIMESTAMPING_LAST };@@ -58,7 +59,8 @@ enum {#define SOF_TIMESTAMPING_TX_RECORD_MASK (SOF_TIMESTAMPING_TX_HARDWARE | \ SOF_TIMESTAMPING_TX_SOFTWARE | \ SOF_TIMESTAMPING_TX_SCHED | \ - SOF_TIMESTAMPING_TX_ACK) + SOF_TIMESTAMPING_TX_ACK | \ + SOF_TIMESTAMPING_TX_COMPLETION)/** * struct so_timestamping - SO_TIMESTAMPING parameter net/core/skbuff.c +2
-0@@ -5523,6 +5523,8 @@ static bool skb_tstamp_tx_report_so_timestamping(struct sk_buff *skb, SKBTX_SW_TSTAMP);case SCM_TSTAMP_ACK :return TCP_SKB_CB (skb)->txstamp_ack &TSTAMP_ACK_SK ; +case SCM_TSTAMP_COMPLETION : +return skb_shinfo (skb)->tx_flags &SKBTX_COMPLETION_TSTAMP ; }return false;net/ethtool/common.c +1
-0@@ -476,6 +476,7 @@ const char sof_timestamping_names[][ETH_GSTRING_LEN] = { [const_ilog2(SOF_TIMESTAMPING_BIND_PHC)] = "bind-phc", [const_ilog2(SOF_TIMESTAMPING_OPT_ID_TCP)] = "option-id-tcp", [const_ilog2(SOF_TIMESTAMPING_OPT_RX_FILTER)] = "option-rx-filter", + [const_ilog2 (SOF_TIMESTAMPING_TX_COMPLETION )] ="tx-completion" , };static_assert (ARRAY_SIZE (sof_timestamping_names) == __SOF_TIMESTAMPING_CNT);net/socket.c +3
-1@@ -689,6 +689,9 @@ void __sock_tx_timestamp(__u32 tsflags, __u8 *tx_flags)if (tsflags &SOF_TIMESTAMPING_TX_SCHED ) flags |=SKBTX_SCHED_TSTAMP ; +if (tsflags &SOF_TIMESTAMPING_TX_COMPLETION ) + flags |=SKBTX_COMPLETION_TSTAMP ; + *tx_flags = flags; }EXPORT_SYMBOL (__sock_tx_timestamp); --2.48.1
Willem de Bruijn
maintainerRe: [PATCH v5 1/5] net-timestamp: COMPLETION timestamp on packet tx completion
In reply to Pauli VirtanenQuoted 37 lines · Pauli Virtanen
Add
SOF_TIMESTAMPING_TX_COMPLETION, for requesting a software timestamp when hardware reports a packet completed.Completion tstamp is useful for Bluetooth, as hardware timestamps do not exist in the HCI specification except for ISO packets, and the hardware has a queue where packets may wait. In this case the software SND timestamp only reflects the kernel-side part of the total latency (usually small) and queue length (usually 0 unless HW buffers congested), whereas the completion report time is more informative of the true latency.
It may also be useful in other cases where HW TX timestamps cannot be obtained and user wants to estimate an upper bound to when the TX probably happened.
Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- back to decoupled COMPLETION & SND, like in v3
- BPF reporting not implemented hereDocumentation/networking/timestamping.rst | 8 ++++++++ include/linux/skbuff.h | 7 ++++--- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 ++++-- net/core/skbuff.c | 2 ++ net/ethtool/common.c | 1 + net/socket.c | 3 +++ 7 files changed, 23 insertions(+), 5 deletions(-)Documentation/networking/timestamping.rst +0
-0
Documentation/networking/timestamping.rst SOF_TIMESTAMPING_TX_ACK: · line 144
Quoted 5 lines
Documentation/networking/timestamping.rst +2
-0@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK: cumulative acknowledgment. The mechanism ignores SACK and FACK. This flag can be enabled via both socket options and control messages. +SOF_TIMESTAMPING_TX_COMPLETION: + Request tx timestamps on packet tx completion. The completion
Minor: double space above, grammar issue below "receives [packet] a".
Documentation/networking/timestamping.rst SOF_TIMESTAMPING_TX_ACK: · line 150
Quoted 6 lines
Documentation/networking/timestamping.rst +6
-0+ timestamp is generated by the kernel when it receives packet a + completion report from the hardware. Hardware may report multiple + packets at once, and completion timestamps reflect the timing of the + report and not actual tx time. This flag can be enabled via both + socket options and control messages. +
Otherwise the patch LGTM.
Re: [PATCH v5 1/5] net-timestamp: COMPLETION timestamp on packet tx completion
In reply to Pauli VirtanenDear Pauli,
Thank you for your patch. Two minor comments, should you resend.
You could make the summary/title a statement:
Add COMPLETION timestamp on packet tx completion
Am 18.03.25 um 20:06 schrieb Pauli Virtanen:
Quoted 37 lines
Add
SOF_TIMESTAMPING_TX_COMPLETION, for requesting a software timestamp when hardware reports a packet completed.Completion tstamp is useful for Bluetooth, as hardware timestamps do not exist in the HCI specification except for ISO packets, and the hardware has a queue where packets may wait. In this case the software SND timestamp only reflects the kernel-side part of the total latency (usually small) and queue length (usually 0 unless HW buffers congested), whereas the completion report time is more informative of the true latency.
It may also be useful in other cases where HW TX timestamps cannot be obtained and user wants to estimate an upper bound to when the TX probably happened.
Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- back to decoupled COMPLETION & SND, like in v3
- BPF reporting not implemented hereDocumentation/networking/timestamping.rst | 8 ++++++++ include/linux/skbuff.h | 7 ++++--- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 ++++-- net/core/skbuff.c | 2 ++ net/ethtool/common.c | 1 + net/socket.c | 3 +++ 7 files changed, 23 insertions(+), 5 deletions(-)Documentation/networking/timestamping.rst +0
-0
Documentation/networking/timestamping.rst SOF_TIMESTAMPING_TX_ACK: · line 146
Quoted 7 lines
Documentation/networking/timestamping.rst +4
-0@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK: cumulative acknowledgment. The mechanism ignores SACK and FACK. This flag can be enabled via both socket options and control messages. +SOF_TIMESTAMPING_TX_COMPLETION: + Request tx timestamps on packet tx completion. The completion + timestamp is generated by the kernel when it receives packet a + completion report from the hardware. Hardware may report multiple
… receives packate a completion … sounds strange to me, but I am a non-native speaker.
[…]
Kind regards,
Paul
Luiz Augusto von Dentz
maintainerRe: [PATCH v5 1/5] net-timestamp: COMPLETION timestamp on packet tx completion
Hi Pauli, Willem, Jason,
Quoted 59 lines · Paul Menzel
Dear Pauli,
Thank you for your patch. Two minor comments, should you resend.
You could make the summary/title a statement:
Add COMPLETION timestamp on packet tx completion
Am 18.03.25 um 20:06 schrieb Pauli Virtanen:
Quoted 37 lines
Add
SOF_TIMESTAMPING_TX_COMPLETION, for requesting a software timestamp when hardware reports a packet completed.Completion tstamp is useful for Bluetooth, as hardware timestamps do not exist in the HCI specification except for ISO packets, and the hardware has a queue where packets may wait. In this case the software SND timestamp only reflects the kernel-side part of the total latency (usually small) and queue length (usually 0 unless HW buffers congested), whereas the completion report time is more informative of the true latency.
It may also be useful in other cases where HW TX timestamps cannot be obtained and user wants to estimate an upper bound to when the TX probably happened.
Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- back to decoupled COMPLETION & SND, like in v3
- BPF reporting not implemented hereDocumentation/networking/timestamping.rst | 8 ++++++++ include/linux/skbuff.h | 7 ++++--- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 ++++-- net/core/skbuff.c | 2 ++ net/ethtool/common.c | 1 + net/socket.c | 3 +++ 7 files changed, 23 insertions(+), 5 deletions(-)Documentation/networking/timestamping.rst +0
-0Documentation/networking/timestamping.rst SOF_TIMESTAMPING_TX_ACK: · line 146
Quoted 7 lines
Documentation/networking/timestamping.rst +4
-0@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK: cumulative acknowledgment. The mechanism ignores SACK and FACK. This flag can be enabled via both socket options and control messages. +SOF_TIMESTAMPING_TX_COMPLETION: + Request tx timestamps on packet tx completion. The completion + timestamp is generated by the kernel when it receives packet a + completion report from the hardware. Hardware may report multiple… receives packate a completion … sounds strange to me, but I am a non-native speaker.
Quoted 6 lines
[…]
Kind regards,
Paul
Is v5 considered good enough to be merged into bluetooth-next and can this be send to in this merge window or you think it is best to leave for the next? In my opinion it could go in so we use the RC period to stabilize it.
Signature · 1 line
Luiz Augusto von Dentz
Re: [PATCH v5 1/5] net-timestamp: COMPLETION timestamp on packet tx completion
Quoted 65 lines · Luiz Augusto von Dentz
Hi Pauli, Willem, Jason,
Quoted 62 lines · Paul Menzel
Dear Pauli,
Thank you for your patch. Two minor comments, should you resend.
You could make the summary/title a statement:
Add COMPLETION timestamp on packet tx completion
Am 18.03.25 um 20:06 schrieb Pauli Virtanen:
Quoted 37 lines
Add
SOF_TIMESTAMPING_TX_COMPLETION, for requesting a software timestamp when hardware reports a packet completed.Completion tstamp is useful for Bluetooth, as hardware timestamps do not exist in the HCI specification except for ISO packets, and the hardware has a queue where packets may wait. In this case the software SND timestamp only reflects the kernel-side part of the total latency (usually small) and queue length (usually 0 unless HW buffers congested), whereas the completion report time is more informative of the true latency.
It may also be useful in other cases where HW TX timestamps cannot be obtained and user wants to estimate an upper bound to when the TX probably happened.
Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- back to decoupled COMPLETION & SND, like in v3
- BPF reporting not implemented hereDocumentation/networking/timestamping.rst | 8 ++++++++ include/linux/skbuff.h | 7 ++++--- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 ++++-- net/core/skbuff.c | 2 ++ net/ethtool/common.c | 1 + net/socket.c | 3 +++ 7 files changed, 23 insertions(+), 5 deletions(-)Documentation/networking/timestamping.rst +0
-0Documentation/networking/timestamping.rst SOF_TIMESTAMPING_TX_ACK: · line 146
Quoted 7 lines
Documentation/networking/timestamping.rst +4
-0@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK: cumulative acknowledgment. The mechanism ignores SACK and FACK. This flag can be enabled via both socket options and control messages. +SOF_TIMESTAMPING_TX_COMPLETION: + Request tx timestamps on packet tx completion. The completion + timestamp is generated by the kernel when it receives packet a + completion report from the hardware. Hardware may report multiple… receives packate a completion … sounds strange to me, but I am a non-native speaker.
[…]
Quoted 8 lines
Quoted 3 lines
Kind regards,
Paul
Is v5 considered good enough to be merged into bluetooth-next and can this be send to in this merge window or you think it is best to leave for the next? In my opinion it could go in so we use the RC period to stabilize it.
I'm fine with merging as is.
Most of my comments were design points for consideration. If Pauli prefers as is, no objections from me.
For the series:
Re: [PATCH v5 1/5] net-timestamp: COMPLETION timestamp on packet tx completion
In reply to Luiz Augusto von DentzHi,
to, 2025-03-20 kello 10:43 -0400, Luiz Augusto von Dentz kirjoitti:
Quoted 65 lines
Hi Pauli, Willem, Jason,
Quoted 62 lines · Paul Menzel
Dear Pauli,
Thank you for your patch. Two minor comments, should you resend.
You could make the summary/title a statement:
Add COMPLETION timestamp on packet tx completion
Am 18.03.25 um 20:06 schrieb Pauli Virtanen:
Quoted 37 lines
Add
SOF_TIMESTAMPING_TX_COMPLETION, for requesting a software timestamp when hardware reports a packet completed.Completion tstamp is useful for Bluetooth, as hardware timestamps do not exist in the HCI specification except for ISO packets, and the hardware has a queue where packets may wait. In this case the software SND timestamp only reflects the kernel-side part of the total latency (usually small) and queue length (usually 0 unless HW buffers congested), whereas the completion report time is more informative of the true latency.
It may also be useful in other cases where HW TX timestamps cannot be obtained and user wants to estimate an upper bound to when the TX probably happened.
Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- back to decoupled COMPLETION & SND, like in v3
- BPF reporting not implemented hereDocumentation/networking/timestamping.rst | 8 ++++++++ include/linux/skbuff.h | 7 ++++--- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 ++++-- net/core/skbuff.c | 2 ++ net/ethtool/common.c | 1 + net/socket.c | 3 +++ 7 files changed, 23 insertions(+), 5 deletions(-)Documentation/networking/timestamping.rst +0
-0Documentation/networking/timestamping.rst SOF_TIMESTAMPING_TX_ACK: · line 146
Quoted 7 lines
Documentation/networking/timestamping.rst +4
-0@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK: cumulative acknowledgment. The mechanism ignores SACK and FACK. This flag can be enabled via both socket options and control messages. +SOF_TIMESTAMPING_TX_COMPLETION: + Request tx timestamps on packet tx completion. The completion + timestamp is generated by the kernel when it receives packet a + completion report from the hardware. Hardware may report multiple… receives packate a completion … sounds strange to me, but I am a non-native speaker.
[…]
Quoted 8 lines
Quoted 3 lines
Kind regards,
Paul
Is v5 considered good enough to be merged into bluetooth-next and can this be send to in this merge window or you think it is best to leave for the next? In my opinion it could go in so we use the RC period to stabilize it.
From my side v5 should be good enough, if we want it now.
The remaining things were:
- Typo in documentation
- Better tx_queue implementation: probably not highly important for these use cases, as queues are likely just a few packets so there will be only that amount of non-timestamped skbs cloned.
In future, we might consider emitting SCM_TSTAMP_ACK timestamps eg. for L2CAP LE credit-based flow control, and there this would matter more as you'd need to hang on to the packets for a longer time.
- I'd leave handling of unsupported sockcm fields as it is in v5, as BT sockets have also previously just silently ignored them so no change in behavior here.
- BPF: separate patch series, also need the tests for that
Signature · 1 line
Pauli Virtanen
Jason Xing
Reviewed-byRe: [PATCH v5 1/5] net-timestamp: COMPLETION timestamp on packet tx completion
Hi,
Quoted 71 lines · Pauli Virtanen
Hi,
to, 2025-03-20 kello 10:43 -0400, Luiz Augusto von Dentz kirjoitti:
Quoted 67 lines
Hi Pauli, Willem, Jason,
Quoted 64 lines · Paul Menzel
Dear Pauli,
Thank you for your patch. Two minor comments, should you resend.
You could make the summary/title a statement:
Add COMPLETION timestamp on packet tx completion
Am 18.03.25 um 20:06 schrieb Pauli Virtanen:
Quoted 37 lines
Add
SOF_TIMESTAMPING_TX_COMPLETION, for requesting a software timestamp when hardware reports a packet completed.Completion tstamp is useful for Bluetooth, as hardware timestamps do not exist in the HCI specification except for ISO packets, and the hardware has a queue where packets may wait. In this case the software SND timestamp only reflects the kernel-side part of the total latency (usually small) and queue length (usually 0 unless HW buffers congested), whereas the completion report time is more informative of the true latency.
It may also be useful in other cases where HW TX timestamps cannot be obtained and user wants to estimate an upper bound to when the TX probably happened.
Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- back to decoupled COMPLETION & SND, like in v3
- BPF reporting not implemented hereDocumentation/networking/timestamping.rst | 8 ++++++++ include/linux/skbuff.h | 7 ++++--- include/uapi/linux/errqueue.h | 1 + include/uapi/linux/net_tstamp.h | 6 ++++-- net/core/skbuff.c | 2 ++ net/ethtool/common.c | 1 + net/socket.c | 3 +++ 7 files changed, 23 insertions(+), 5 deletions(-)Documentation/networking/timestamping.rst +0
-0Documentation/networking/timestamping.rst SOF_TIMESTAMPING_TX_ACK: · line 146
Quoted 7 lines
Documentation/networking/timestamping.rst +4
-0@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK: cumulative acknowledgment. The mechanism ignores SACK and FACK. This flag can be enabled via both socket options and control messages. +SOF_TIMESTAMPING_TX_COMPLETION: + Request tx timestamps on packet tx completion. The completion + timestamp is generated by the kernel when it receives packet a + completion report from the hardware. Hardware may report multiple… receives packate a completion … sounds strange to me, but I am a non-native speaker.
[…]
Kind regards,
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
Paul
Is v5 considered good enough to be merged into bluetooth-next and can this be send to in this merge window or you think it is best to leave for the next? In my opinion it could go in so we use the RC period to stabilize it.
From my side v5 should be good enough, if we want it now.
Sorry for seeing this too late, I think I miss adding the reviewed-by tags. Anyway,
Thanks for working on this!!
Quoted 14 lines
The remaining things were:
- Typo in documentation
- Better
tx_queueimplementation: probably not highly important for these use cases, as queues are likely just a few packets so there will be only that amount of non-timestamped skbs cloned.In future, we might consider emitting
SCM_TSTAMP_ACKtimestamps eg. for L2CAP LE credit-based flow control, and there this would matter more as you'd need to hang on to the packets for a longer time.
Quoted 5 lines
- I'd leave handling of unsupported sockcm fields as it is in v5, as BT sockets have also previously just silently ignored them so no change in behavior here.
- BPF: separate patch series, also need the tests for that
Right, I agree :)
Thanks,
Jason
Quoted 4 lines
--
Pauli Virtanen
PATCH v5 2/5 Bluetooth: add support for skb TX SND/COMPLETION timestamping
In reply to Pauli VirtanenSupport enabling TX timestamping for some skbs, and track them until packet completion. Generate software SCM_TSTAMP_COMPLETION when getting completion report from hardware.
Generate software SCM_TSTAMP_SND before sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.
Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
The tx_q queue length is bounded by the hdev flow control, which will not send new packets before it has got completion reports for old ones.
---
Notes:
v5:
- Add hci_sockm_init()
- Back to decoupled COMPLETION & SND, like in v3
- Handle SCO flow controlled case
include/net/bluetooth/hci_core.h | 20 +++++ net/bluetooth/hci_conn.c | 122 +++++++++++++++++++++++++++++++ net/bluetooth/hci_core.c | 15 +++- net/bluetooth/hci_event.c | 4 + 4 files changed, 157 insertions(+), 4 deletions(-)
include/net/bluetooth/hci_core.h +20 -0
@@ -261,6 +261,12 @@ struct adv_info {struct delayed_work rpa_expired_cb; }; +struct tx_queue { +struct sk_buff_head queue; +unsigned int extra; +unsigned int tracked; +}; +#define HCI_MAX_ADV_INSTANCES 5#define HCI_DEFAULT_ADV_DURATION 2
@@ -733,6 +739,8 @@ struct hci_conn {struct sk_buff_head data_q;struct list_head chan_list; +struct tx_queue tx_q; +struct delayed_work disc_work;struct delayed_work auto_accept_work;struct delayed_work idle_work;
@@ -1572,6 +1580,18 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);void hci_conn_failed (struct hci_conn *conn,u8 status);u8 hci_conn_set_handle (struct hci_conn *conn,u16 handle); +void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb); +void hci_conn_tx_dequeue (struct hci_conn *conn); +void hci_setup_tx_timestamp (struct sk_buff *skb,size_t key_offset, +const struct sockcm_cookie *sockc); + +static inline void hci_sockcm_init (struct sockcm_cookie *sockc,struct sock *sk) +{ + *sockc = (struct sockcm_cookie ) { + .tsflags =READ_ONCE (sk->sk_tsflags), + }; +} +/* * hci_conn_get() and hci_conn_put() are used to control the life-time of an * "hci_conn" object. They do not guarantee that the hci_conn object is running,
net/bluetooth/hci_conn.c +122 -0
143 lines not on this page · raw message
net/bluetooth/hci_core.c +11 -4
@@ -3029,6 +3029,13 @@ static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)return 0 ; } +static int hci_send_conn_frame (struct hci_dev *hdev,struct hci_conn *conn, +struct sk_buff *skb) +{ +hci_conn_tx_queue (conn, skb); +return hci_send_frame (hdev, skb); +} +/* Send HCI command */ int hci_send_cmd (struct hci_dev *hdev,__u16 opcode,__u32 plen,const void *param)
@@ -3575,7 +3582,7 @@ static void hci_sched_sco(struct hci_dev *hdev, __u8 type)while (*cnt && (conn =hci_low_sent (hdev, type, "e))) {while (quote-- && (skb =skb_dequeue (&conn->data_q))) {BT_DBG ("skb %p len %d" , skb, skb->len); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, conn, skb); conn->sent++;if (conn->sent == ~0 )
@@ -3618,7 +3625,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)hci_conn_enter_active_mode (chan->conn,bt_cb (skb)->force_active); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, chan->conn, skb); hdev->acl_last_tx = jiffies; hdev->acl_cnt--;
@@ -3674,7 +3681,7 @@ static void hci_sched_le(struct hci_dev *hdev) skb =skb_dequeue (&chan->data_q); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, chan->conn, skb); hdev->le_last_tx = jiffies; (*cnt)--;
@@ -3708,7 +3715,7 @@ static void hci_sched_iso(struct hci_dev *hdev)while (*cnt && (conn =hci_low_sent (hdev,ISO_LINK , "e))) {while (quote-- && (skb =skb_dequeue (&conn->data_q))) {BT_DBG ("skb %p len %d" , skb, skb->len); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, conn, skb); conn->sent++;if (conn->sent == ~0 )
net/bluetooth/hci_event.c +4 -0
@@ -4415,6 +4415,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,struct hci_comp_pkts_info *info = &ev->handles[i];struct hci_conn *conn;__u16 handle, count; +unsigned int i; handle =__le16_to_cpu (info->handle); count =__le16_to_cpu (info->count);
@@ -4425,6 +4426,9 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, conn->sent -= count; +for (i =0 ; i < count; ++i) +hci_conn_tx_dequeue (conn); +switch (conn->type) {case ACL_LINK : hdev->acl_cnt += count;
Signature · 1 line
2.48.1
Re: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
Quoted 139 lines · Pauli Virtanen
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
The
tx_qqueue length is bounded by the hdev flow control, which will not send new packets before it has got completion reports for old ones.Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- Addhci_sockm_init()
- Back to decoupled COMPLETION & SND, like in v3
- Handle SCO flow controlled caseinclude/net/bluetooth/hci_core.h | 20 +++++ net/bluetooth/hci_conn.c | 122 +++++++++++++++++++++++++++++++ net/bluetooth/hci_core.c | 15 +++- net/bluetooth/hci_event.c | 4 + 4 files changed, 157 insertions(+), 4 deletions(-)include/net/bluetooth/hci_core.h +20
-0@@ -261,6 +261,12 @@ struct adv_info {struct delayed_work rpa_expired_cb; }; +struct tx_queue { +struct sk_buff_head queue; +unsigned int extra; +unsigned int tracked; +}; +#define HCI_MAX_ADV_INSTANCES 5#define HCI_DEFAULT_ADV_DURATION 2@@ -733,6 +739,8 @@ struct hci_conn {struct sk_buff_head data_q;struct list_head chan_list; +struct tx_queue tx_q; +struct delayed_work disc_work;struct delayed_work auto_accept_work;struct delayed_work idle_work;@@ -1572,6 +1580,18 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);void hci_conn_failed (struct hci_conn *conn,u8 status);u8 hci_conn_set_handle (struct hci_conn *conn,u16 handle); +void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb); +void hci_conn_tx_dequeue (struct hci_conn *conn); +void hci_setup_tx_timestamp (struct sk_buff *skb,size_t key_offset, +const struct sockcm_cookie *sockc); + +static inline void hci_sockcm_init (struct sockcm_cookie *sockc,struct sock *sk) +{ + *sockc = (struct sockcm_cookie ) { + .tsflags =READ_ONCE (sk->sk_tsflags), + }; +} +/* * hci_conn_get() and hci_conn_put() are used to control the life-time of an * "hci_conn" object. They do not guarantee that the hci_conn object is running, net/bluetooth/hci_conn.c +33
-0@@ -27,6 +27,7 @@#include <linux/export.h> #include <linux/debugfs.h> +#include <linux/errqueue.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -1002,6 +1003,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t }skb_queue_head_init (&conn->data_q); +skb_queue_head_init (&conn->tx_q.queue);INIT_LIST_HEAD (&conn->chan_list);INIT_LIST_HEAD (&conn->link_list);@@ -1155,6 +1157,7 @@ void hci_conn_del(struct hci_conn *conn) }skb_queue_purge (&conn->data_q); +skb_queue_purge (&conn->tx_q.queue);/* Remove the connection from the list and cleanup its remaining * state. This is a separate function since for some cases like @@ -3064,3 +3067,122 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)*/ return hci_cmd_sync_run_once (hdev, abort_conn_sync, conn,NULL ); } + +void hci_setup_tx_timestamp (struct sk_buff *skb,size_t key_offset, +const struct sockcm_cookie *sockc) +{ +struct sock *sk = skb ? skb->sk :NULL ; + +/* This shall be called on a single skb of those generated by user +* sendmsg(), and only when the sendmsg() does not return error to +* user. This is required for keeping the tskey that increments here in +* sync with possible sendmsg() counting by user. +* +* Stream sockets shall set key_offset to sendmsg() length in bytes +* and call with the last fragment, others to 1 and first fragment. +*/ + +if (!skb || !sockc || !sk || !key_offset) +return ; + +sock_tx_timestamp (sk, sockc, &skb_shinfo (skb)->tx_flags); + +if (sockc->tsflags &SOF_TIMESTAMPING_OPT_ID && + sockc->tsflags &SOF_TIMESTAMPING_TX_RECORD_MASK ) { +if (sockc->tsflags &SOCKCM_FLAG_TS_OPT_ID ) { +skb_shinfo (skb)->tskey = sockc->ts_opt_id; + }else { +int key =atomic_add_return (key_offset, &sk->sk_tskey); + +skb_shinfo (skb)->tskey = key -1 ; + } + }
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3109
Quoted 10 lines
net/bluetooth/hci_conn.c +10
-0+} + +void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb) +{ +struct tx_queue *comp = &conn->tx_q; +bool track = false; + +/* Emit SND now, ie. just before sending to driver */ +if (skb_shinfo (skb)->tx_flags &SKBTX_SW_TSTAMP ) +__skb_tstamp_tx (skb,NULL ,NULL , skb->sk,SCM_TSTAMP_SND );
It's a bit strange that SCM_TSTAMP_SND is under the control of SKBTX_SW_TSTAMP. Can we use the same flag for both lines here directly? I suppose I would use SKBTX_SW_TSTAMP then.
Quoted 63 lines
net/bluetooth/hci_conn.c +63
-0+ +/* COMPLETION tstamp is emitted for tracked skb later in Number of +* Completed Packets event. Available only for flow controlled cases. +* +* TODO: SCO support without flowctl (needs to be done in drivers) +*/ +switch (conn->type) { +case ISO_LINK : +case ACL_LINK : +case LE_LINK : +break ; +case SCO_LINK : +case ESCO_LINK : +if (!hci_dev_test_flag (conn->hdev,HCI_SCO_FLOWCTL )) +return ; +break ; +default : +return ; + } + +if (skb->sk && (skb_shinfo (skb)->tx_flags &SKBTX_COMPLETION_TSTAMP )) + track = true; + +/* If nothing is tracked, just count extra skbs at the queue head */ +if (!track && !comp->tracked) { + comp->extra++; +return ; + } + +if (track) { + skb =skb_clone_sk (skb); +if (!skb) + goto count_only; + + comp->tracked++; + }else { + skb =skb_clone (skb,GFP_KERNEL ); +if (!skb) + goto count_only; + } + +skb_queue_tail (&comp->queue, skb); +return ; + +count_only: +/* Stop tracking skbs, and only count. This will not emit timestamps for +* the packets, but if we get here something is more seriously wrong. +*/ + comp->tracked =0 ; + comp->extra +=skb_queue_len (&comp->queue) +1 ; +skb_queue_purge (&comp->queue); +} + +void hci_conn_tx_dequeue (struct hci_conn *conn) +{ +struct tx_queue *comp = &conn->tx_q; +struct sk_buff *skb; + +/* If there are tracked skbs, the counted extra go before dequeuing real +* skbs, to keep ordering. When nothing is tracked, the ordering doesn't +* matter so dequeue real skbs first to get rid of them ASAP. +*/ +if (comp->extra && (comp->tracked ||skb_queue_empty (&comp->queue))) {
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3182
Quoted 10 lines
net/bluetooth/hci_conn.c +10
-0+ comp->extra--; +return ; + } + + skb =skb_dequeue (&comp->queue); +if (!skb) +return ; + +if (skb->sk) { + comp->tracked--;
Need an explicit if statement here?
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3184
Quoted 2 lines
net/bluetooth/hci_conn.c +2
-0+__skb_tstamp_tx (skb,NULL ,NULL , skb->sk, +SCM_TSTAMP_COMPLETION );
This is the socket timestamping, and that's right. My minor question
is: for the use of bpf timestamping (that should be easy as you've done in patch 1, I presume), I'm not sure if you're familiar with it. If not, I plan to implement it myself in a follow-up patch and then let you do some tests? Of course, I will provide the bpf test script :)
Thanks,
Jason
Quoted 84 lines
net/bluetooth/hci_conn.c +4
-0+ } + +kfree_skb (skb); +}net/bluetooth/hci_core.c +11
-4@@ -3029,6 +3029,13 @@ static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)return 0 ; } +static int hci_send_conn_frame (struct hci_dev *hdev,struct hci_conn *conn, +struct sk_buff *skb) +{ +hci_conn_tx_queue (conn, skb); +return hci_send_frame (hdev, skb); +} +/* Send HCI command */ int hci_send_cmd (struct hci_dev *hdev,__u16 opcode,__u32 plen,const void *param)@@ -3575,7 +3582,7 @@ static void hci_sched_sco(struct hci_dev *hdev, __u8 type)while (*cnt && (conn =hci_low_sent (hdev, type, "e))) {while (quote-- && (skb =skb_dequeue (&conn->data_q))) {BT_DBG ("skb %p len %d" , skb, skb->len); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, conn, skb); conn->sent++;if (conn->sent == ~0 )@@ -3618,7 +3625,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)hci_conn_enter_active_mode (chan->conn,bt_cb (skb)->force_active); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, chan->conn, skb); hdev->acl_last_tx = jiffies; hdev->acl_cnt--;@@ -3674,7 +3681,7 @@ static void hci_sched_le(struct hci_dev *hdev) skb =skb_dequeue (&chan->data_q); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, chan->conn, skb); hdev->le_last_tx = jiffies; (*cnt)--;@@ -3708,7 +3715,7 @@ static void hci_sched_iso(struct hci_dev *hdev)while (*cnt && (conn =hci_low_sent (hdev,ISO_LINK , "e))) {while (quote-- && (skb =skb_dequeue (&conn->data_q))) {BT_DBG ("skb %p len %d" , skb, skb->len); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, conn, skb); conn->sent++;if (conn->sent == ~0 )net/bluetooth/hci_event.c +4
-1@@ -4415,6 +4415,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,struct hci_comp_pkts_info *info = &ev->handles[i];struct hci_conn *conn;__u16 handle, count; +unsigned int i; handle =__le16_to_cpu (info->handle); count =__le16_to_cpu (info->count);@@ -4425,6 +4426,9 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, conn->sent -= count; +for (i =0 ; i < count; ++i) +hci_conn_tx_dequeue (conn); +switch (conn->type) {case ACL_LINK : hdev->acl_cnt += count; --2.48.1
Willem de Bruijn
maintainerRe: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
Quoted 6 lines · Jason Xing
Quoted 5 lines · Pauli Virtanen
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.
Quoted 8 lines
Quoted 8 lines
Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
Why count packets at all? And if useful separate from completions, should that be a separate patch?
Quoted 4 lines
Quoted 4 lines
net/bluetooth/hci_conn.c +4
-0+void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb) +{ +struct tx_queue *comp = &conn->tx_q; +bool track = false;
Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3109
Quoted 4 lines
net/bluetooth/hci_conn.c +4
-0+ +/* Emit SND now, ie. just before sending to driver */ +if (skb_shinfo (skb)->tx_flags &SKBTX_SW_TSTAMP ) +__skb_tstamp_tx (skb,NULL ,NULL , skb->sk,SCM_TSTAMP_SND );It's a bit strange that
SCM_TSTAMP_SNDis under the control ofSKBTX_SW_TSTAMP. Can we use the same flag for both lines here directly? I suppose I would useSKBTX_SW_TSTAMPthen.
This is the established behavior.
Quoted 33 lines
Quoted 33 lines
net/bluetooth/hci_conn.c +32
-0+ +/* COMPLETION tstamp is emitted for tracked skb later in Number of +* Completed Packets event. Available only for flow controlled cases. +* +* TODO: SCO support without flowctl (needs to be done in drivers) +*/ +switch (conn->type) { +case ISO_LINK : +case ACL_LINK : +case LE_LINK : +break ; +case SCO_LINK : +case ESCO_LINK : +if (!hci_dev_test_flag (conn->hdev,HCI_SCO_FLOWCTL )) +return ; +break ; +default : +return ; + } + +if (skb->sk && (skb_shinfo (skb)->tx_flags &SKBTX_COMPLETION_TSTAMP )) + track = true; + +/* If nothing is tracked, just count extra skbs at the queue head */ +if (!track && !comp->tracked) { + comp->extra++; +return ; + } + +if (track) { + skb =skb_clone_sk (skb); +if (!skb)
Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3149
Quoted 8 lines
net/bluetooth/hci_conn.c +8
-0+ goto count_only; + + comp->tracked++; + }else { + skb =skb_clone (skb,GFP_KERNEL ); +if (!skb) + goto count_only; + }
What is the difference between track and comp->tracked
Re: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
Hi,
ke, 2025-03-19 kello 10:44 -0400, Willem de Bruijn kirjoitti:
Quoted 11 lines
Quoted 10 lines · Jason Xing
Quoted 9 lines · Pauli Virtanen
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.
Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
Why count packets at all? And if useful separate from completions, should that be a separate patch?
This paragraph was commenting on the implementation of struct tx_queue, and maybe how it works should be explicitly explained somewhere (code comment?). Here's some explanation of it:
1) We have to hang on (clones of) skbs until completion reports for them arrive, in order to emit COMPLETION timestamps. There's no existing queue that does this in net/bluetooth (drivers may just copy data & discard skbs, and they don't know about completion reports), so something new needs to be added.
2) It is only needed for emitting COMPLETION timestamps. So it's better to not do any extra work (clones etc.) when there are no such timestamps to be emitted.
3) The new queue should work correctly when timestamping is turned on or off, or only some packets are timestamped. It should also eventually return to a state where no extra work is done, when new skbs don't request COMPLETION timestamps.
struct tx_queue implements such queue that only "tracks" some skbs. Logical structure:
HEAD
<no stored skb> } <no stored skb> } tx_queue::extra is the number of non-tracked ... } logical items at queue head <no stored skb> }
<tracked skb> } tx_queue::queue contains mixture of
<non-tracked skb> } tracked items (skb->sk != NULL) and
<non-tracked skb> } non-tracked items (skb->sk == NULL).
<tracked skb> } These are ordered after the "extra" items.
TAIL
tx_queue::tracked is the number of tracked skbs in tx_queue::queue.
hci_conn_tx_queue() determines whether skb is tracked (= COMPLETION timestamp shall be emitted for it) and pushes a logical item to TAIL.
hci_conn_tx_dequeue() pops a logical item from HEAD, and emits timestamp if it corresponds to a tracked skb.
When tracked == 0, queue() can just increment tx_queue::extra, and dequeue() can remove any skb from tx_queue::queue, or if empty then decrement tx_queue::extra. This allows it to return to a state with empty tx_queue::queue when new skbs no longer request timestamps.
When tracked != 0, the ordering of items in the queue needs to be respected strictly, so queue() always pushes real skb (tracked or not) to TAIL, and dequeue() has to decrement extra to zero, before it can pop skb from queue head.
Quoted 49 lines
Quoted 4 lines
Quoted 4 lines
net/bluetooth/hci_conn.c +4
-0+void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb) +{ +struct tx_queue *comp = &conn->tx_q; +bool track = false;Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3109
Quoted 4 lines
net/bluetooth/hci_conn.c +4
-0+ +/* Emit SND now, ie. just before sending to driver */ +if (skb_shinfo (skb)->tx_flags &SKBTX_SW_TSTAMP ) +__skb_tstamp_tx (skb,NULL ,NULL , skb->sk,SCM_TSTAMP_SND );It's a bit strange that
SCM_TSTAMP_SNDis under the control ofSKBTX_SW_TSTAMP. Can we use the same flag for both lines here directly? I suppose I would useSKBTX_SW_TSTAMPthen.This is the established behavior.
Quoted 35 lines
Quoted 35 lines
net/bluetooth/hci_conn.c +34
-0+ +/* COMPLETION tstamp is emitted for tracked skb later in Number of +* Completed Packets event. Available only for flow controlled cases. +* +* TODO: SCO support without flowctl (needs to be done in drivers) +*/ +switch (conn->type) { +case ISO_LINK : +case ACL_LINK : +case LE_LINK : +break ; +case SCO_LINK : +case ESCO_LINK : +if (!hci_dev_test_flag (conn->hdev,HCI_SCO_FLOWCTL )) +return ; +break ; +default : +return ; + } + +if (skb->sk && (skb_shinfo (skb)->tx_flags &SKBTX_COMPLETION_TSTAMP )) + track = true; + +/* If nothing is tracked, just count extra skbs at the queue head */ +if (!track && !comp->tracked) { + comp->extra++; +return ; + } + +if (track) { + skb =skb_clone_sk (skb); +if (!skb) + goto count_only; +
Quoted 8 lines
Quoted 6 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3149
Quoted 6 lines
net/bluetooth/hci_conn.c +6
-0+ comp->tracked++; + }else { + skb =skb_clone (skb,GFP_KERNEL ); +if (!skb) + goto count_only; + }What is the difference between track and
comp->tracked
I hope the answer above is clear.
Signature · 1 line
Pauli Virtanen
Willem de Bruijn
maintainerRe: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
Quoted 32 lines · Pauli Virtanen
Hi,
ke, 2025-03-19 kello 10:44 -0400, Willem de Bruijn kirjoitti:
Quoted 11 lines
Quoted 10 lines · Jason Xing
Quoted 9 lines · Pauli Virtanen
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
Why count packets at all? And if useful separate from completions, should that be a separate patch?
This paragraph was commenting on the implementation of struct
tx_queue, and maybe how it works should be explicitly explained somewhere (code comment?). Here's some explanation of it:1) We have to hang on (clones of) skbs until completion reports for them arrive, in order to emit COMPLETION timestamps. There's no existing queue that does this in net/bluetooth (drivers may just copy data & discard skbs, and they don't know about completion reports), so something new needs to be added.
Quoted 8 lines
2) It is only needed for emitting COMPLETION timestamps. So it's better to not do any extra work (clones etc.) when there are no such timestamps to be emitted.
3) The new queue should work correctly when timestamping is turned on or off, or only some packets are timestamped. It should also eventually return to a state where no extra work is done, when new skbs don't request COMPLETION timestamps.
So far, fully understood.
Quoted 27 lines
struct
tx_queueimplements such queue that only "tracks" some skbs. Logical structure:HEAD
<no stored skb> } <no stored skb> } tx_queue::extra is the number of non-tracked ... } logical items at queue head <no stored skb> }<tracked skb> }
tx_queue::queuecontains mixture of
<non-tracked skb> } tracked items (skb->sk!= NULL) and
<non-tracked skb> } non-tracked items (skb->sk== NULL).
<tracked skb> } These are ordered after the "extra" items.
TAIL
tx_queue::trackedis the number of tracked skbs intx_queue::queue.
hci_conn_tx_queue()determines whether skb is tracked (= COMPLETION timestamp shall be emitted for it) and pushes a logical item to TAIL.
hci_conn_tx_dequeue()pops a logical item from HEAD, and emits timestamp if it corresponds to a tracked skb.When tracked == 0,
queue()can just incrementtx_queue::extra, anddequeue()can remove any skb fromtx_queue::queue, or if empty then decrementtx_queue::extra. This allows it to return to a state with emptytx_queue::queuewhen new skbs no longer request timestamps.
Quoted 4 lines
When tracked != 0, the ordering of items in the queue needs to be respected strictly, so
queue()always pushes real skb (tracked or not) to TAIL, anddequeue()has to decrement extra to zero, before it can pop skb from queue head.
Thanks. I did not understand why you need to queue or track any sbs aside from those that have SKBTX_COMPLETION_TSTAMP.
If I follow correctly this is to be able to associate the tx completion with the right skb on the queue.
The usual model in Ethernet drivers is that every tx descriptor (and completion descriptor) in the ring is associated with a pure software ring of metadata structures, which can point to an skb (or NULL).
In a pinch, instead the skb on the queue itself could record the descriptor id that it is associated with. But hci_conn_tx_queue is too far removed from the HW, so has no direct access to that. And similarly hci_conn_tx_dequeue has no such low level details.
So long story short you indeed have to track this out of band with a separate counter. I also don't immediately see a simpler way.
Though you can perhaps replace the skb_clone (not the skb_clone_sk!) with some sentinel value that just helps count?
Re: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
Hi,
ke, 2025-03-19 kello 16:00 -0400, Willem de Bruijn kirjoitti:
Quoted 74 lines
Quoted 30 lines · Pauli Virtanen
ke, 2025-03-19 kello 10:44 -0400, Willem de Bruijn kirjoitti:
Quoted 11 lines
Quoted 10 lines · Jason Xing
Quoted 9 lines · Pauli Virtanen
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
Why count packets at all? And if useful separate from completions, should that be a separate patch?
This paragraph was commenting on the implementation of struct
tx_queue, and maybe how it works should be explicitly explained somewhere (code comment?). Here's some explanation of it:1) We have to hang on (clones of) skbs until completion reports for them arrive, in order to emit COMPLETION timestamps. There's no existing queue that does this in net/bluetooth (drivers may just copy data & discard skbs, and they don't know about completion reports), so something new needs to be added.
Quoted 8 lines
2) It is only needed for emitting COMPLETION timestamps. So it's better to not do any extra work (clones etc.) when there are no such timestamps to be emitted.
3) The new queue should work correctly when timestamping is turned on or off, or only some packets are timestamped. It should also eventually return to a state where no extra work is done, when new skbs don't request COMPLETION timestamps.
So far, fully understood.
Quoted 27 lines
struct
tx_queueimplements such queue that only "tracks" some skbs. Logical structure:HEAD
<no stored skb> } <no stored skb> } tx_queue::extra is the number of non-tracked ... } logical items at queue head <no stored skb> }<tracked skb> }
tx_queue::queuecontains mixture of
<non-tracked skb> } tracked items (skb->sk!= NULL) and
<non-tracked skb> } non-tracked items (skb->sk== NULL).
<tracked skb> } These are ordered after the "extra" items.
TAIL
tx_queue::trackedis the number of tracked skbs intx_queue::queue.
hci_conn_tx_queue()determines whether skb is tracked (= COMPLETION timestamp shall be emitted for it) and pushes a logical item to TAIL.
hci_conn_tx_dequeue()pops a logical item from HEAD, and emits timestamp if it corresponds to a tracked skb.When tracked == 0,
queue()can just incrementtx_queue::extra, anddequeue()can remove any skb fromtx_queue::queue, or if empty then decrementtx_queue::extra. This allows it to return to a state with emptytx_queue::queuewhen new skbs no longer request timestamps.Quoted 4 lines
When tracked != 0, the ordering of items in the queue needs to be respected strictly, so
queue()always pushes real skb (tracked or not) to TAIL, anddequeue()has to decrement extra to zero, before it can pop skb from queue head.
Quoted 5 lines
Thanks. I did not understand why you need to queue or track any sbs aside from those that have
SKBTX_COMPLETION_TSTAMP.If I follow correctly this is to be able to associate the tx completion with the right skb on the queue.
Yes, it was done to maintain the queue/dequeue ordering.
Quoted 9 lines
The usual model in Ethernet drivers is that every tx descriptor (and completion descriptor) in the ring is associated with a pure software ring of metadata structures, which can point to an skb (or NULL).
In a pinch, instead the skb on the queue itself could record the descriptor id that it is associated with. But
hci_conn_tx_queueis too far removed from the HW, so has no direct access to that. And similarlyhci_conn_tx_dequeuehas no such low level details.
Quoted 5 lines
So long story short you indeed have to track this out of band with a separate counter. I also don't immediately see a simpler way.
Though you can perhaps replace the
skb_clone(not theskb_clone_sk!) with some sentinel value that just helps count?
It probably could be done a bit smarter, it could eg. use something else than skb_queue. Or, I think we can clobber cb here as the clones are only used for timestamping, so:
struct tx_queue {
unsigned int pre_items;
struct sk_buff_head queue;
};struct tx_queue_cb {
unsigned int post_items;
};static void hci_tx_queue_push(struct tx_queue *q, struct sk_buff *skb)
{
struct tx_queue_cb *cb;
/* HEAD
* <non-tracked item> }
* ... } tx_queue::pre_items of these
* <non-tracked item> }
* <tracked skb1> <- tx_queue::queue first item
* <non-tracked item> }
* ... } ((struct tx_queue_cb *)skb1->cb)->post_items
* <non-tracked item> }
* ...
* <tracked skbn> <- tx_queue::queue n-th item
* <non-tracked item> }
* ... } ((struct tx_queue_cb *)skbn->cb)->post_items
* <non-tracked item> }
* TAIL
*/
if (skb) {
cb = (struct tx_queue_cb *)skb->cb;
cb->post_items = 0;
skb_queue_tail(&q->queue, skb);
} else {
skb = skb_peek_tail(&q->queue);
if (skb) {
cb = (struct tx_queue_cb *)skb->cb;
cb->post_items++;
} else {
q->pre_items++;
}
}
}static struct sk_buff *hci_tx_queue_pop(struct tx_queue *q)
{
struct sk_buff *skb;
struct tx_queue_cb *cb;
if (q->pre_items) {
q->pre_items--;
return NULL;
}
skb = skb_dequeue(&q->queue);
if (skb) {
cb = (struct tx_queue_cb *)skb->cb;
q->pre_items += cb->post_items;
}
return skb;
}void hci_conn_tx_queue(struct hci_conn *conn, struct sk_buff *skb)
{
/* Emit SND now, ie. just before sending to driver */
if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP)
__skb_tstamp_tx(skb, NULL, NULL, skb->sk, SCM_TSTAMP_SND);
/* COMPLETION tstamp is emitted for tracked skb later in Number of
* Completed Packets event. Available only for flow controlled cases.
*
* TODO: SCO support without flowctl (needs to be done in drivers)
*/
switch (conn->type) {
case ISO_LINK:
case ACL_LINK:
case LE_LINK:
break;
case SCO_LINK:
case ESCO_LINK:
if (!hci_dev_test_flag(conn->hdev, HCI_SCO_FLOWCTL))
return;
break;
default:
return;
}
if (skb->sk && (skb_shinfo(skb)->tx_flags & SKBTX_COMPLETION_TSTAMP))
skb = skb_clone_sk(skb);
else
skb = NULL;
hci_tx_queue_push(&conn->tx_q, skb);
return;
}void hci_conn_tx_dequeue(struct hci_conn *conn)
{
struct sk_buff *skb = hci_tx_queue_pop(&conn->tx_q);
if (skb) {
__skb_tstamp_tx(skb, NULL, NULL, skb->sk,
SCM_TSTAMP_COMPLETION);
kfree_skb(skb);
}
}Signature · 1 line
Pauli Virtanen
Willem de Bruijn
maintainerRe: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
Quoted 202 lines · Pauli Virtanen
Hi,
ke, 2025-03-19 kello 16:00 -0400, Willem de Bruijn kirjoitti:
Quoted 74 lines
Quoted 30 lines · Pauli Virtanen
ke, 2025-03-19 kello 10:44 -0400, Willem de Bruijn kirjoitti:
Quoted 11 lines
Quoted 10 lines · Jason Xing
Quoted 9 lines · Pauli Virtanen
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
Why count packets at all? And if useful separate from completions, should that be a separate patch?
This paragraph was commenting on the implementation of struct
tx_queue, and maybe how it works should be explicitly explained somewhere (code comment?). Here's some explanation of it:1) We have to hang on (clones of) skbs until completion reports for them arrive, in order to emit COMPLETION timestamps. There's no existing queue that does this in net/bluetooth (drivers may just copy data & discard skbs, and they don't know about completion reports), so something new needs to be added.
Quoted 8 lines
2) It is only needed for emitting COMPLETION timestamps. So it's better to not do any extra work (clones etc.) when there are no such timestamps to be emitted.
3) The new queue should work correctly when timestamping is turned on or off, or only some packets are timestamped. It should also eventually return to a state where no extra work is done, when new skbs don't request COMPLETION timestamps.
So far, fully understood.
Quoted 27 lines
struct
tx_queueimplements such queue that only "tracks" some skbs. Logical structure:HEAD
<no stored skb> } <no stored skb> } tx_queue::extra is the number of non-tracked ... } logical items at queue head <no stored skb> }<tracked skb> }
tx_queue::queuecontains mixture of
<non-tracked skb> } tracked items (skb->sk!= NULL) and
<non-tracked skb> } non-tracked items (skb->sk== NULL).
<tracked skb> } These are ordered after the "extra" items.
TAIL
tx_queue::trackedis the number of tracked skbs intx_queue::queue.
hci_conn_tx_queue()determines whether skb is tracked (= COMPLETION timestamp shall be emitted for it) and pushes a logical item to TAIL.
hci_conn_tx_dequeue()pops a logical item from HEAD, and emits timestamp if it corresponds to a tracked skb.When tracked == 0,
queue()can just incrementtx_queue::extra, anddequeue()can remove any skb fromtx_queue::queue, or if empty then decrementtx_queue::extra. This allows it to return to a state with emptytx_queue::queuewhen new skbs no longer request timestamps.Quoted 4 lines
When tracked != 0, the ordering of items in the queue needs to be respected strictly, so
queue()always pushes real skb (tracked or not) to TAIL, anddequeue()has to decrement extra to zero, before it can pop skb from queue head.Quoted 5 lines
Thanks. I did not understand why you need to queue or track any sbs aside from those that have
SKBTX_COMPLETION_TSTAMP.If I follow correctly this is to be able to associate the tx completion with the right skb on the queue.
Yes, it was done to maintain the queue/dequeue ordering.
Quoted 9 lines
The usual model in Ethernet drivers is that every tx descriptor (and completion descriptor) in the ring is associated with a pure software ring of metadata structures, which can point to an skb (or NULL).
In a pinch, instead the skb on the queue itself could record the descriptor id that it is associated with. But
hci_conn_tx_queueis too far removed from the HW, so has no direct access to that. And similarlyhci_conn_tx_dequeuehas no such low level details.Quoted 5 lines
So long story short you indeed have to track this out of band with a separate counter. I also don't immediately see a simpler way.
Though you can perhaps replace the
skb_clone(not theskb_clone_sk!) with some sentinel value that just helps count?It probably could be done a bit smarter, it could eg. use something else than
skb_queue. Or, I think we can clobber cb here as the clones are only used for timestamping, so:struct tx_queue { unsigned int pre_items; struct sk_buff_head queue; };struct tx_queue_cb { unsigned int post_items; };static void
hci_tx_queue_push(struct tx_queue *q, struct sk_buff *skb){ struct tx_queue_cb *cb; /* HEAD * <non-tracked item> } * ... } tx_queue::pre_items of these * <non-tracked item> } * <tracked skb1> <- tx_queue::queue first item * <non-tracked item> } * ... } ((struct tx_queue_cb *)skb1->cb)->post_items * <non-tracked item> } * ... * <tracked skbn> <- tx_queue::queue n-th item * <non-tracked item> } * ... } ((struct tx_queue_cb *)skbn->cb)->post_items * <non-tracked item> } * TAIL */ if (skb) { cb = (struct tx_queue_cb *)skb->cb; cb->post_items = 0; skb_queue_tail(&q->queue, skb); } else { skb = skb_peek_tail(&q->queue); if (skb) { cb = (struct tx_queue_cb *)skb->cb; cb->post_items++; } else { q->pre_items++; } } }static struct
sk_buff*hci_tx_queue_pop(structtx_queue*q){ struct sk_buff *skb; struct tx_queue_cb *cb; if (q->pre_items) { q->pre_items--; return NULL; } skb = skb_dequeue(&q->queue); if (skb) { cb = (struct tx_queue_cb *)skb->cb; q->pre_items += cb->post_items; } return skb; }void
hci_conn_tx_queue(struct hci_conn *conn, struct sk_buff *skb){ /* Emit SND now, ie. just before sending to driver */ if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP) __skb_tstamp_tx(skb, NULL, NULL, skb->sk, SCM_TSTAMP_SND); /* COMPLETION tstamp is emitted for tracked skb later in Number of * Completed Packets event. Available only for flow controlled cases. * * TODO: SCO support without flowctl (needs to be done in drivers) */ switch (conn->type) { case ISO_LINK: case ACL_LINK: case LE_LINK: break; case SCO_LINK: case ESCO_LINK: if (!hci_dev_test_flag(conn->hdev, HCI_SCO_FLOWCTL)) return; break; default: return; } if (skb->sk && (skb_shinfo(skb)->tx_flags & SKBTX_COMPLETION_TSTAMP)) skb = skb_clone_sk(skb); else skb = NULL; hci_tx_queue_push(&conn->tx_q, skb); return; }void
hci_conn_tx_dequeue(struct hci_conn *conn)
Quoted 9 lines
{
struct sk_buff *skb = hci_tx_queue_pop(&conn->tx_q);
if (skb) {
__skb_tstamp_tx(skb, NULL, NULL, skb->sk,
SCM_TSTAMP_COMPLETION);
kfree_skb(skb);
}
}Neat. To be clear, your call. Just if the expectation is that timestamped packets are rare even when enabled (e.g., due to sampling, or enabling only for one of many sockets), then avoiding the skb_clone in the common case may be worthwhile.
Luiz Augusto von Dentz
maintainerRe: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
In reply to Pauli VirtanenHi Pauli,
Quoted 33 lines · Pauli Virtanen
Hi,
ke, 2025-03-19 kello 10:44 -0400, Willem de Bruijn kirjoitti:
Quoted 11 lines
Quoted 10 lines · Jason Xing
Quoted 9 lines · Pauli Virtanen
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
Why count packets at all? And if useful separate from completions, should that be a separate patch?
This paragraph was commenting on the implementation of struct
tx_queue, and maybe how it works should be explicitly explained somewhere (code comment?). Here's some explanation of it:1) We have to hang on (clones of) skbs until completion reports for them arrive, in order to emit COMPLETION timestamps. There's no existing queue that does this in net/bluetooth (drivers may just copy data & discard skbs, and they don't know about completion reports), so something new needs to be added.
Quoted 8 lines
2) It is only needed for emitting COMPLETION timestamps. So it's better to not do any extra work (clones etc.) when there are no such timestamps to be emitted.
3) The new queue should work correctly when timestamping is turned on or off, or only some packets are timestamped. It should also eventually return to a state where no extra work is done, when new skbs don't request COMPLETION timestamps.
I don't think it would hurt to put some of the above text as code comments, but I think it would actually be better if we start doing some documentation for Bluetooth in general, or we can put as part of the manpages in userspace though that normally cover only the interface not the internals, but I think it is a good idea to add documentation to the likes of l2cap.rst covering the usage of SO_TIMESTAMPING:
https://github.com/bluez/bluez/blob/master/doc/l2cap.rst
It is on my TODO to do something similar to SCO and ISO(once it is stable) sockets.
Quoted 96 lines
struct
tx_queueimplements such queue that only "tracks" some skbs. Logical structure:HEAD
<no stored skb> } <no stored skb> } tx_queue::extra is the number of non-tracked ... } logical items at queue head <no stored skb> } <tracked skb> } tx_queue::queue contains mixture of <non-tracked skb> } tracked items (skb->sk != NULL) and <non-tracked skb> } non-tracked items (skb->sk == NULL). <tracked skb> } These are ordered after the "extra" items.TAIL
tx_queue::trackedis the number of tracked skbs intx_queue::queue.
hci_conn_tx_queue()determines whether skb is tracked (= COMPLETION timestamp shall be emitted for it) and pushes a logical item to TAIL.
hci_conn_tx_dequeue()pops a logical item from HEAD, and emits timestamp if it corresponds to a tracked skb.When tracked == 0,
queue()can just incrementtx_queue::extra, anddequeue()can remove any skb fromtx_queue::queue, or if empty then decrementtx_queue::extra. This allows it to return to a state with emptytx_queue::queuewhen new skbs no longer request timestamps.When tracked != 0, the ordering of items in the queue needs to be respected strictly, so
queue()always pushes real skb (tracked or not) to TAIL, anddequeue()has to decrement extra to zero, before it can pop skb from queue head.Quoted 49 lines
Quoted 4 lines
Quoted 4 lines
net/bluetooth/hci_conn.c +4
-0+void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb) +{ +struct tx_queue *comp = &conn->tx_q; +bool track = false;Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3109
Quoted 4 lines
net/bluetooth/hci_conn.c +4
-0+ +/* Emit SND now, ie. just before sending to driver */ +if (skb_shinfo (skb)->tx_flags &SKBTX_SW_TSTAMP ) +__skb_tstamp_tx (skb,NULL ,NULL , skb->sk,SCM_TSTAMP_SND );It's a bit strange that
SCM_TSTAMP_SNDis under the control ofSKBTX_SW_TSTAMP. Can we use the same flag for both lines here directly? I suppose I would useSKBTX_SW_TSTAMPthen.This is the established behavior.
Quoted 35 lines
Quoted 35 lines
net/bluetooth/hci_conn.c +34
-0+ +/* COMPLETION tstamp is emitted for tracked skb later in Number of +* Completed Packets event. Available only for flow controlled cases. +* +* TODO: SCO support without flowctl (needs to be done in drivers) +*/ +switch (conn->type) { +case ISO_LINK : +case ACL_LINK : +case LE_LINK : +break ; +case SCO_LINK : +case ESCO_LINK : +if (!hci_dev_test_flag (conn->hdev,HCI_SCO_FLOWCTL )) +return ; +break ; +default : +return ; + } + +if (skb->sk && (skb_shinfo (skb)->tx_flags &SKBTX_COMPLETION_TSTAMP )) + track = true; + +/* If nothing is tracked, just count extra skbs at the queue head */ +if (!track && !comp->tracked) { + comp->extra++; +return ; + } + +if (track) { + skb =skb_clone_sk (skb); +if (!skb) + goto count_only; +Quoted 8 lines
Quoted 6 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3149
Quoted 6 lines
net/bluetooth/hci_conn.c +6
-0+ comp->tracked++; + }else { + skb =skb_clone (skb,GFP_KERNEL ); +if (!skb) + goto count_only; + }What is the difference between track and
comp->trackedI hope the answer above is clear.
--
Pauli Virtanen
Signature · 1 line
Luiz Augusto von Dentz
Re: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
In reply to Jason XingHi,
ke, 2025-03-19 kello 08:39 +0800, Jason Xing kirjoitti:
Quoted 146 lines · Pauli Virtanen
Quoted 145 lines
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
The
tx_qqueue length is bounded by the hdev flow control, which will not send new packets before it has got completion reports for old ones.Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- Addhci_sockm_init()
- Back to decoupled COMPLETION & SND, like in v3
- Handle SCO flow controlled caseinclude/net/bluetooth/hci_core.h | 20 +++++ net/bluetooth/hci_conn.c | 122 +++++++++++++++++++++++++++++++ net/bluetooth/hci_core.c | 15 +++- net/bluetooth/hci_event.c | 4 + 4 files changed, 157 insertions(+), 4 deletions(-)include/net/bluetooth/hci_core.h +20
-0@@ -261,6 +261,12 @@ struct adv_info {struct delayed_work rpa_expired_cb; }; +struct tx_queue { +struct sk_buff_head queue; +unsigned int extra; +unsigned int tracked; +}; +#define HCI_MAX_ADV_INSTANCES 5#define HCI_DEFAULT_ADV_DURATION 2@@ -733,6 +739,8 @@ struct hci_conn {struct sk_buff_head data_q;struct list_head chan_list; +struct tx_queue tx_q; +struct delayed_work disc_work;struct delayed_work auto_accept_work;struct delayed_work idle_work;@@ -1572,6 +1580,18 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);void hci_conn_failed (struct hci_conn *conn,u8 status);u8 hci_conn_set_handle (struct hci_conn *conn,u16 handle); +void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb); +void hci_conn_tx_dequeue (struct hci_conn *conn); +void hci_setup_tx_timestamp (struct sk_buff *skb,size_t key_offset, +const struct sockcm_cookie *sockc); + +static inline void hci_sockcm_init (struct sockcm_cookie *sockc,struct sock *sk) +{ + *sockc = (struct sockcm_cookie ) { + .tsflags =READ_ONCE (sk->sk_tsflags), + }; +} +/* * hci_conn_get() and hci_conn_put() are used to control the life-time of an * "hci_conn" object. They do not guarantee that the hci_conn object is running, net/bluetooth/hci_conn.c +39
-0@@ -27,6 +27,7 @@#include <linux/export.h> #include <linux/debugfs.h> +#include <linux/errqueue.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -1002,6 +1003,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t }skb_queue_head_init (&conn->data_q); +skb_queue_head_init (&conn->tx_q.queue);INIT_LIST_HEAD (&conn->chan_list);INIT_LIST_HEAD (&conn->link_list);@@ -1155,6 +1157,7 @@ void hci_conn_del(struct hci_conn *conn) }skb_queue_purge (&conn->data_q); +skb_queue_purge (&conn->tx_q.queue);/* Remove the connection from the list and cleanup its remaining * state. This is a separate function since for some cases like @@ -3064,3 +3067,122 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)*/ return hci_cmd_sync_run_once (hdev, abort_conn_sync, conn,NULL ); } + +void hci_setup_tx_timestamp (struct sk_buff *skb,size_t key_offset, +const struct sockcm_cookie *sockc) +{ +struct sock *sk = skb ? skb->sk :NULL ; + +/* This shall be called on a single skb of those generated by user +* sendmsg(), and only when the sendmsg() does not return error to +* user. This is required for keeping the tskey that increments here in +* sync with possible sendmsg() counting by user. +* +* Stream sockets shall set key_offset to sendmsg() length in bytes +* and call with the last fragment, others to 1 and first fragment. +*/ + +if (!skb || !sockc || !sk || !key_offset) +return ; + +sock_tx_timestamp (sk, sockc, &skb_shinfo (skb)->tx_flags); + +if (sockc->tsflags &SOF_TIMESTAMPING_OPT_ID && + sockc->tsflags &SOF_TIMESTAMPING_TX_RECORD_MASK ) { +if (sockc->tsflags &SOCKCM_FLAG_TS_OPT_ID ) { +skb_shinfo (skb)->tskey = sockc->ts_opt_id; + }else { +int key =atomic_add_return (key_offset, &sk->sk_tskey); + +skb_shinfo (skb)->tskey = key -1 ; + } + } +} + +void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb) +{ +struct tx_queue *comp = &conn->tx_q; +bool track = false;
Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3109
Quoted 4 lines
net/bluetooth/hci_conn.c +4
-0+ +/* Emit SND now, ie. just before sending to driver */ +if (skb_shinfo (skb)->tx_flags &SKBTX_SW_TSTAMP ) +__skb_tstamp_tx (skb,NULL ,NULL , skb->sk,SCM_TSTAMP_SND );It's a bit strange that
SCM_TSTAMP_SNDis under the control ofSKBTX_SW_TSTAMP. Can we use the same flag for both lines here directly? I suppose I would useSKBTX_SW_TSTAMPthen.
This is more or less open-coded skb_tx_timestamp(), which drivers do before sending to HW, for the Bluetooth case. AFAIK it should be done like this.
Quoted 68 lines
Quoted 68 lines
net/bluetooth/hci_conn.c +67
-0+ +/* COMPLETION tstamp is emitted for tracked skb later in Number of +* Completed Packets event. Available only for flow controlled cases. +* +* TODO: SCO support without flowctl (needs to be done in drivers) +*/ +switch (conn->type) { +case ISO_LINK : +case ACL_LINK : +case LE_LINK : +break ; +case SCO_LINK : +case ESCO_LINK : +if (!hci_dev_test_flag (conn->hdev,HCI_SCO_FLOWCTL )) +return ; +break ; +default : +return ; + } + +if (skb->sk && (skb_shinfo (skb)->tx_flags &SKBTX_COMPLETION_TSTAMP )) + track = true; + +/* If nothing is tracked, just count extra skbs at the queue head */ +if (!track && !comp->tracked) { + comp->extra++; +return ; + } + +if (track) { + skb =skb_clone_sk (skb); +if (!skb) + goto count_only; + + comp->tracked++; + }else { + skb =skb_clone (skb,GFP_KERNEL ); +if (!skb) + goto count_only; + } + +skb_queue_tail (&comp->queue, skb); +return ; + +count_only: +/* Stop tracking skbs, and only count. This will not emit timestamps for +* the packets, but if we get here something is more seriously wrong. +*/ + comp->tracked =0 ; + comp->extra +=skb_queue_len (&comp->queue) +1 ; +skb_queue_purge (&comp->queue); +} + +void hci_conn_tx_dequeue (struct hci_conn *conn) +{ +struct tx_queue *comp = &conn->tx_q; +struct sk_buff *skb; + +/* If there are tracked skbs, the counted extra go before dequeuing real +* skbs, to keep ordering. When nothing is tracked, the ordering doesn't +* matter so dequeue real skbs first to get rid of them ASAP. +*/ +if (comp->extra && (comp->tracked ||skb_queue_empty (&comp->queue))) { + comp->extra--; +return ; + } +
Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3182
Quoted 6 lines
net/bluetooth/hci_conn.c +6
-0+ skb =skb_dequeue (&comp->queue); +if (!skb) +return ; + +if (skb->sk) { + comp->tracked--;Need an explicit if statement here?
I think no, see explanation of how it works in the reply to Willem:
https://lore.kernel.org/linux-bluetooth/[email protected]/
Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3184
Quoted 2 lines
net/bluetooth/hci_conn.c +2
-0+__skb_tstamp_tx (skb,NULL ,NULL , skb->sk, +SCM_TSTAMP_COMPLETION );This is the socket timestamping, and that's right. My minor question
is: for the use of bpf timestamping (that should be easy as you've done in patch 1, I presume), I'm not sure if you're familiar with it. If not, I plan to implement it myself in a follow-up patch and then let you do some tests? Of course, I will provide the bpf test script
I saw the BPF timestamping things, but didn't look in full detail yet. I don't know much about BPF, but IIUC, is it just as simple as adding BPF_SOCK_OPS_TSTAMP_COMPLETION_CB and then modifying skb_tstamp_tx_report_bpf_timestamping() accordingly?
I think we'd want to add also the BPF tests in the Bluetooth socket timestamping tests
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/test-runner.rst
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/tester.h#n91
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/iso-tester.c#n2275
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/sco-tester.c#n755
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/l2cap-tester.c#n1369
If you could show an example how to setup the BPF tstamps and pass the resulting tstamp data in some way back to the application, that could be very helpful (and I could postpone learning BPF for a little while longer :)
Quoted 89 lines
:)
Thanks,
JasonQuoted 84 lines
net/bluetooth/hci_conn.c +4
-0+ } + +kfree_skb (skb); +}net/bluetooth/hci_core.c +11
-4@@ -3029,6 +3029,13 @@ static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)return 0 ; } +static int hci_send_conn_frame (struct hci_dev *hdev,struct hci_conn *conn, +struct sk_buff *skb) +{ +hci_conn_tx_queue (conn, skb); +return hci_send_frame (hdev, skb); +} +/* Send HCI command */ int hci_send_cmd (struct hci_dev *hdev,__u16 opcode,__u32 plen,const void *param)@@ -3575,7 +3582,7 @@ static void hci_sched_sco(struct hci_dev *hdev, __u8 type)while (*cnt && (conn =hci_low_sent (hdev, type, "e))) {while (quote-- && (skb =skb_dequeue (&conn->data_q))) {BT_DBG ("skb %p len %d" , skb, skb->len); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, conn, skb); conn->sent++;if (conn->sent == ~0 )@@ -3618,7 +3625,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)hci_conn_enter_active_mode (chan->conn,bt_cb (skb)->force_active); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, chan->conn, skb); hdev->acl_last_tx = jiffies; hdev->acl_cnt--;@@ -3674,7 +3681,7 @@ static void hci_sched_le(struct hci_dev *hdev) skb =skb_dequeue (&chan->data_q); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, chan->conn, skb); hdev->le_last_tx = jiffies; (*cnt)--;@@ -3708,7 +3715,7 @@ static void hci_sched_iso(struct hci_dev *hdev)while (*cnt && (conn =hci_low_sent (hdev,ISO_LINK , "e))) {while (quote-- && (skb =skb_dequeue (&conn->data_q))) {BT_DBG ("skb %p len %d" , skb, skb->len); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, conn, skb); conn->sent++;if (conn->sent == ~0 )net/bluetooth/hci_event.c +4
-1@@ -4415,6 +4415,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,struct hci_comp_pkts_info *info = &ev->handles[i];struct hci_conn *conn;__u16 handle, count; +unsigned int i; handle =__le16_to_cpu (info->handle); count =__le16_to_cpu (info->count);@@ -4425,6 +4426,9 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, conn->sent -= count; +for (i =0 ; i < count; ++i) +hci_conn_tx_dequeue (conn); +switch (conn->type) {case ACL_LINK : hdev->acl_cnt += count; --2.48.1
Signature · 1 line
Pauli Virtanen
Re: [PATCH v5 2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
Quoted 159 lines · Pauli Virtanen
Hi,
ke, 2025-03-19 kello 08:39 +0800, Jason Xing kirjoitti:
Quoted 146 lines · Pauli Virtanen
Quoted 145 lines
Support enabling TX timestamping for some skbs, and track them until packet completion. Generate software
SCM_TSTAMP_COMPLETIONwhen getting completion report from hardware.Generate software
SCM_TSTAMP_SNDbefore sending to driver. Sending from driver requires changes in the driver API, and drivers mostly are going to send the skb immediately.Make the default situation with no COMPLETION TX timestamping more efficient by only counting packets in the queue when there is nothing to track. When there is something to track, we need to make clones, since the driver may modify sent skbs.
The
tx_qqueue length is bounded by the hdev flow control, which will not send new packets before it has got completion reports for old ones.Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- Addhci_sockm_init()
- Back to decoupled COMPLETION & SND, like in v3
- Handle SCO flow controlled caseinclude/net/bluetooth/hci_core.h | 20 +++++ net/bluetooth/hci_conn.c | 122 +++++++++++++++++++++++++++++++ net/bluetooth/hci_core.c | 15 +++- net/bluetooth/hci_event.c | 4 + 4 files changed, 157 insertions(+), 4 deletions(-)include/net/bluetooth/hci_core.h +20
-0@@ -261,6 +261,12 @@ struct adv_info {struct delayed_work rpa_expired_cb; }; +struct tx_queue { +struct sk_buff_head queue; +unsigned int extra; +unsigned int tracked; +}; +#define HCI_MAX_ADV_INSTANCES 5#define HCI_DEFAULT_ADV_DURATION 2@@ -733,6 +739,8 @@ struct hci_conn {struct sk_buff_head data_q;struct list_head chan_list; +struct tx_queue tx_q; +struct delayed_work disc_work;struct delayed_work auto_accept_work;struct delayed_work idle_work;@@ -1572,6 +1580,18 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);void hci_conn_failed (struct hci_conn *conn,u8 status);u8 hci_conn_set_handle (struct hci_conn *conn,u16 handle); +void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb); +void hci_conn_tx_dequeue (struct hci_conn *conn); +void hci_setup_tx_timestamp (struct sk_buff *skb,size_t key_offset, +const struct sockcm_cookie *sockc); + +static inline void hci_sockcm_init (struct sockcm_cookie *sockc,struct sock *sk) +{ + *sockc = (struct sockcm_cookie ) { + .tsflags =READ_ONCE (sk->sk_tsflags), + }; +} +/* * hci_conn_get() and hci_conn_put() are used to control the life-time of an * "hci_conn" object. They do not guarantee that the hci_conn object is running, net/bluetooth/hci_conn.c +39
-0@@ -27,6 +27,7 @@#include <linux/export.h> #include <linux/debugfs.h> +#include <linux/errqueue.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -1002,6 +1003,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t }skb_queue_head_init (&conn->data_q); +skb_queue_head_init (&conn->tx_q.queue);INIT_LIST_HEAD (&conn->chan_list);INIT_LIST_HEAD (&conn->link_list);@@ -1155,6 +1157,7 @@ void hci_conn_del(struct hci_conn *conn) }skb_queue_purge (&conn->data_q); +skb_queue_purge (&conn->tx_q.queue);/* Remove the connection from the list and cleanup its remaining * state. This is a separate function since for some cases like @@ -3064,3 +3067,122 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)*/ return hci_cmd_sync_run_once (hdev, abort_conn_sync, conn,NULL ); } + +void hci_setup_tx_timestamp (struct sk_buff *skb,size_t key_offset, +const struct sockcm_cookie *sockc) +{ +struct sock *sk = skb ? skb->sk :NULL ; + +/* This shall be called on a single skb of those generated by user +* sendmsg(), and only when the sendmsg() does not return error to +* user. This is required for keeping the tskey that increments here in +* sync with possible sendmsg() counting by user. +* +* Stream sockets shall set key_offset to sendmsg() length in bytes +* and call with the last fragment, others to 1 and first fragment. +*/ + +if (!skb || !sockc || !sk || !key_offset) +return ; + +sock_tx_timestamp (sk, sockc, &skb_shinfo (skb)->tx_flags); + +if (sockc->tsflags &SOF_TIMESTAMPING_OPT_ID && + sockc->tsflags &SOF_TIMESTAMPING_TX_RECORD_MASK ) { +if (sockc->tsflags &SOCKCM_FLAG_TS_OPT_ID ) { +skb_shinfo (skb)->tskey = sockc->ts_opt_id; + }else { +int key =atomic_add_return (key_offset, &sk->sk_tskey); + +skb_shinfo (skb)->tskey = key -1 ; + } + } +} + +void hci_conn_tx_queue (struct hci_conn *conn,struct sk_buff *skb) +{ +struct tx_queue *comp = &conn->tx_q; +bool track = false;Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3109
Quoted 4 lines
net/bluetooth/hci_conn.c +4
-0+ +/* Emit SND now, ie. just before sending to driver */ +if (skb_shinfo (skb)->tx_flags &SKBTX_SW_TSTAMP ) +__skb_tstamp_tx (skb,NULL ,NULL , skb->sk,SCM_TSTAMP_SND );It's a bit strange that
SCM_TSTAMP_SNDis under the control ofSKBTX_SW_TSTAMP. Can we use the same flag for both lines here directly? I suppose I would useSKBTX_SW_TSTAMPthen.
Quoted 3 lines
This is more or less open-coded
skb_tx_timestamp(), which drivers do before sending to HW, for the Bluetooth case. AFAIK it should be done like this.
You're right. Sorry for misreading this part yesterday somehow...
Quoted 90 lines
Quoted 69 lines
Quoted 69 lines
net/bluetooth/hci_conn.c +67
-0+ +/* COMPLETION tstamp is emitted for tracked skb later in Number of +* Completed Packets event. Available only for flow controlled cases. +* +* TODO: SCO support without flowctl (needs to be done in drivers) +*/ +switch (conn->type) { +case ISO_LINK : +case ACL_LINK : +case LE_LINK : +break ; +case SCO_LINK : +case ESCO_LINK : +if (!hci_dev_test_flag (conn->hdev,HCI_SCO_FLOWCTL )) +return ; +break ; +default : +return ; + } + +if (skb->sk && (skb_shinfo (skb)->tx_flags &SKBTX_COMPLETION_TSTAMP )) + track = true; + +/* If nothing is tracked, just count extra skbs at the queue head */ +if (!track && !comp->tracked) { + comp->extra++; +return ; + } + +if (track) { + skb =skb_clone_sk (skb); +if (!skb) + goto count_only; + + comp->tracked++; + }else { + skb =skb_clone (skb,GFP_KERNEL ); +if (!skb) + goto count_only; + } + +skb_queue_tail (&comp->queue, skb); +return ; + +count_only: +/* Stop tracking skbs, and only count. This will not emit timestamps for +* the packets, but if we get here something is more seriously wrong. +*/ + comp->tracked =0 ; + comp->extra +=skb_queue_len (&comp->queue) +1 ; +skb_queue_purge (&comp->queue); +} + +void hci_conn_tx_dequeue (struct hci_conn *conn) +{ +struct tx_queue *comp = &conn->tx_q; +struct sk_buff *skb; + +/* If there are tracked skbs, the counted extra go before dequeuing real +* skbs, to keep ordering. When nothing is tracked, the ordering doesn't +* matter so dequeue real skbs first to get rid of them ASAP. +*/ +if (comp->extra && (comp->tracked ||skb_queue_empty (&comp->queue))) { + comp->extra--; +return ; + } +Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3182
Quoted 6 lines
net/bluetooth/hci_conn.c +6
-0+ skb =skb_dequeue (&comp->queue); +if (!skb) +return ; + +if (skb->sk) { + comp->tracked--;Need an explicit if statement here?
I think no, see explanation of how it works in the reply to Willem:
https://lore.kernel.org/linux-bluetooth/[email protected]/Quoted 8 lines
net/bluetooth/hci_conn.c int hci_abort_conn(struct hci_conn *conn, u8 reason) · line 3184
Quoted 2 lines
net/bluetooth/hci_conn.c +2
-0+__skb_tstamp_tx (skb,NULL ,NULL , skb->sk, +SCM_TSTAMP_COMPLETION );This is the socket timestamping, and that's right. My minor question
is: for the use of bpf timestamping (that should be easy as you've done in patch 1, I presume), I'm not sure if you're familiar with it. If not, I plan to implement it myself in a follow-up patch and then let you do some tests? Of course, I will provide the bpf test script
Quoted 7 lines
I saw the BPF timestamping things, but didn't look in full detail yet. I don't know much about BPF, but IIUC, is it just as simple as adding
BPF_SOCK_OPS_TSTAMP_COMPLETION_CBand then modifyingskb_tstamp_tx_report_bpf_timestamping()accordingly?I think we'd want to add also the BPF tests in the Bluetooth socket timestamping tests
Good to know that!
Quoted 11 lines
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/test-runner.rst
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/tester.h#n91
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/iso-tester.c#n2275
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/sco-tester.c#n755
https://web.git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/l2cap-tester.c#n1369If you could show an example how to setup the BPF tstamps and pass the resulting tstamp data in some way back to the application, that could be very helpful (and I could postpone learning BPF for a little while longer :)
Sure, I can leave it to you as long as you want to take over it :)
A simple case where I re-support the bpf extension for socket timestamping goes like this commit [1]. And the selftest can be seen here[2].
A rough thought is that letting it pass in skb_tstamp_tx_report_bpf_timestamping() and adding corresponding BPF flag as you mentioned before are the key to do it on top of the current series. It should not be that hard. If you have any questions on how we move on about this point, please feel free to reach out to me anytime.
[1]: https://web.git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=6b98ec7e882af1c3088a88757e2226d06c8514f9
[2]: https://web.git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=f4924aec58dd9e14779f4bc11a6bf3a830a42a6c
Note: you will compile tools/testing/selftests/bpf/ and run
./test_progs -t net_timestamp to see how it works.
Thanks,
Jason
Quoted 93 lines
Quoted 80 lines
:)
Thanks,
JasonQuoted 74 lines
net/bluetooth/hci_conn.c +4
-0+ } + +kfree_skb (skb); +}net/bluetooth/hci_core.c +11
-4@@ -3029,6 +3029,13 @@ static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)return 0 ; } +static int hci_send_conn_frame (struct hci_dev *hdev,struct hci_conn *conn, +struct sk_buff *skb) +{ +hci_conn_tx_queue (conn, skb); +return hci_send_frame (hdev, skb); +} +/* Send HCI command */ int hci_send_cmd (struct hci_dev *hdev,__u16 opcode,__u32 plen,const void *param)@@ -3575,7 +3582,7 @@ static void hci_sched_sco(struct hci_dev *hdev, __u8 type)while (*cnt && (conn =hci_low_sent (hdev, type, "e))) {while (quote-- && (skb =skb_dequeue (&conn->data_q))) {BT_DBG ("skb %p len %d" , skb, skb->len); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, conn, skb); conn->sent++;if (conn->sent == ~0 )@@ -3618,7 +3625,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)hci_conn_enter_active_mode (chan->conn,bt_cb (skb)->force_active); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, chan->conn, skb); hdev->acl_last_tx = jiffies; hdev->acl_cnt--;@@ -3674,7 +3681,7 @@ static void hci_sched_le(struct hci_dev *hdev) skb =skb_dequeue (&chan->data_q); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, chan->conn, skb); hdev->le_last_tx = jiffies; (*cnt)--;@@ -3708,7 +3715,7 @@ static void hci_sched_iso(struct hci_dev *hdev)while (*cnt && (conn =hci_low_sent (hdev,ISO_LINK , "e))) {while (quote-- && (skb =skb_dequeue (&conn->data_q))) {BT_DBG ("skb %p len %d" , skb, skb->len); -hci_send_frame (hdev, skb); +hci_send_conn_frame (hdev, conn, skb); conn->sent++;if (conn->sent == ~0 )net/bluetooth/hci_event.c +1
-0@@ -4415,6 +4415,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,struct hci_comp_pkts_info *info = &ev->handles[i];struct hci_conn *conn;__u16 handle, count; +unsigned int i; handle =__le16_to_cpu (info->handle); count =__le16_to_cpu (info->count);@@ -4425,6 +4426,9 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, conn->sent -= count;Quoted 10 lines
Quoted 10 lines
net/bluetooth/hci_event.c +3
-1+for (i =0 ; i < count; ++i) +hci_conn_tx_dequeue (conn); +switch (conn->type) {case ACL_LINK : hdev->acl_cnt += count; --2.48.1
--
Pauli Virtanen
PATCH v5 3/5 Bluetooth: ISO: add TX timestamping
In reply to Pauli VirtanenAdd BT_SCM_ERROR socket CMSG type.
Support TX timestamping in ISO sockets.
Support MSG_ERRQUEUE in ISO recvmsg.
If a packet from sendmsg() is fragmented, only the first ACL fragment is timestamped.
---
Notes:
v5:
- use sockcm_init -> hci_sockcm_init
include/net/bluetooth/bluetooth.h | 1 + net/bluetooth/iso.c | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-)
include/net/bluetooth/bluetooth.h +1 -0
@@ -156,6 +156,7 @@ struct bt_voice {#define BT_PKT_STATUS 16#define BT_SCM_PKT_STATUS 0x03 +#define BT_SCM_ERROR 0x04#define BT_ISO_QOS 17
net/bluetooth/iso.c +20 -4
@@ -518,7 +518,8 @@ static struct bt_iso_qos *iso_sock_get_qos(struct sock *sk)return &iso_pi (sk)->qos; } -static int iso_send_frame (struct sock *sk,struct sk_buff *skb) +static int iso_send_frame (struct sock *sk,struct sk_buff *skb, +const struct sockcm_cookie *sockc) {struct iso_conn *conn =iso_pi (sk)->conn;struct bt_iso_qos *qos =iso_sock_get_qos (sk);
@@ -538,10 +539,12 @@ static int iso_send_frame(struct sock *sk, struct sk_buff *skb) hdr->slen =cpu_to_le16 (hci_iso_data_len_pack (len,HCI_ISO_STATUS_VALID )); -if (sk->sk_state ==BT_CONNECTED ) +if (sk->sk_state ==BT_CONNECTED ) { +hci_setup_tx_timestamp (skb,1 , sockc);hci_send_iso (conn->hcon, skb); -else + }else { len = -ENOTCONN ; + }return len; }
@@ -1348,6 +1351,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg, {struct sock *sk = sock->sk;struct sk_buff *skb, **frag; +struct sockcm_cookie sockc;size_t mtu;int err;
@@ -1360,6 +1364,14 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,if (msg->msg_flags &MSG_OOB )return -EOPNOTSUPP ; +hci_sockcm_init (&sockc, sk); + +if (msg->msg_controllen) { + err =sock_cmsg_send (sk, msg, &sockc); +if (err) +return err; + } +lock_sock (sk);if (sk->sk_state !=BT_CONNECTED ) {
@@ -1405,7 +1417,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,lock_sock (sk);if (sk->sk_state ==BT_CONNECTED ) - err =iso_send_frame (sk, skb); + err =iso_send_frame (sk, skb, &sockc);else err = -ENOTCONN ;
@@ -1474,6 +1486,10 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,BT_DBG ("sk %p" , sk); +if (unlikely (flags &MSG_ERRQUEUE )) +return sock_recv_errqueue (sk, msg, len,SOL_BLUETOOTH , +BT_SCM_ERROR ); +if (test_and_clear_bit (BT_SK_DEFER_SETUP , &bt_sk (sk)->flags)) {sock_hold (sk);lock_sock (sk);
Signature · 1 line
2.48.1
Willem de Bruijn
maintainerRe: [PATCH v5 3/5] Bluetooth: ISO: add TX timestamping
Quoted 71 lines · Pauli Virtanen
Add
BT_SCM_ERRORsocket CMSG type.Support TX timestamping in ISO sockets.
Support
MSG_ERRQUEUEin ISO recvmsg.If a packet from
sendmsg()is fragmented, only the first ACL fragment is timestamped.Signed-off-by Pauli Virtanen <[email protected]>---
Notes:
v5:
- usesockcm_init->hci_sockcm_initinclude/net/bluetooth/bluetooth.h | 1 + net/bluetooth/iso.c | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-)include/net/bluetooth/bluetooth.h +1
-0@@ -156,6 +156,7 @@ struct bt_voice {#define BT_PKT_STATUS 16#define BT_SCM_PKT_STATUS 0x03 +#define BT_SCM_ERROR 0x04#define BT_ISO_QOS 17net/bluetooth/iso.c +7
-3@@ -518,7 +518,8 @@ static struct bt_iso_qos *iso_sock_get_qos(struct sock *sk)return &iso_pi (sk)->qos; } -static int iso_send_frame (struct sock *sk,struct sk_buff *skb) +static int iso_send_frame (struct sock *sk,struct sk_buff *skb, +const struct sockcm_cookie *sockc) {struct iso_conn *conn =iso_pi (sk)->conn;struct bt_iso_qos *qos =iso_sock_get_qos (sk);@@ -538,10 +539,12 @@ static int iso_send_frame(struct sock *sk, struct sk_buff *skb) hdr->slen =cpu_to_le16 (hci_iso_data_len_pack (len,HCI_ISO_STATUS_VALID )); -if (sk->sk_state ==BT_CONNECTED ) +if (sk->sk_state ==BT_CONNECTED ) { +hci_setup_tx_timestamp (skb,1 , sockc);hci_send_iso (conn->hcon, skb); -else + }else { len = -ENOTCONN ; + }return len; }@@ -1348,6 +1351,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg, {struct sock *sk = sock->sk;struct sk_buff *skb, **frag; +struct sockcm_cookie sockc;size_t mtu;int err;@@ -1360,6 +1364,14 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,if (msg->msg_flags &MSG_OOB )
net/bluetooth/iso.c static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg, · line 1374
Quoted 10 lines
net/bluetooth/iso.c +8
-0return -EOPNOTSUPP ; +hci_sockcm_init (&sockc, sk); + +if (msg->msg_controllen) { + err =sock_cmsg_send (sk, msg, &sockc); +if (err) +return err; + } +
Minor: do you want to return an error if the process set unexpected sockc fields?
If allowing to set them now, but ignoring them, it will be harder to support them later. As then it will result in a kernel behavioral change for the same sendmsg() call.
Though I suppose that is already the case if all cmsg are ignored currently. So fine to keep if you don't care.
PATCH v5 4/5 Bluetooth: L2CAP: add TX timestamping
In reply to Pauli VirtanenSupport 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.
---
Notes:
v5:
- use sockcm_init -> hci_sockcm_init
include/net/bluetooth/l2cap.h | 3 ++- net/bluetooth/6lowpan.c | 2 +- net/bluetooth/l2cap_core.c | 41 ++++++++++++++++++++++++++++++++--- net/bluetooth/l2cap_sock.c | 15 ++++++++++++- net/bluetooth/smp.c | 2 +- 5 files changed, 56 insertions(+), 7 deletions(-)
include/net/bluetooth/l2cap.h +2 -1
@@ -955,7 +955,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason);int l2cap_chan_connect (struct l2cap_chan *chan,__le16 psm,u16 cid,bdaddr_t *dst,u8 dst_type,u16 timeout);int l2cap_chan_reconfigure (struct l2cap_chan *chan,__u16 mtu); -int l2cap_chan_send (struct l2cap_chan *chan,struct msghdr *msg,size_t len); +int l2cap_chan_send (struct l2cap_chan *chan,struct msghdr *msg,size_t len, +const struct sockcm_cookie *sockc);void l2cap_chan_busy (struct l2cap_chan *chan,int busy);void l2cap_chan_rx_avail (struct l2cap_chan *chan,ssize_t rx_avail);int l2cap_chan_check_security (struct l2cap_chan *chan,bool initiator);
net/bluetooth/6lowpan.c +1 -1
@@ -444,7 +444,7 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb,memset (&msg,0 ,sizeof (msg));iov_iter_kvec (&msg.msg_iter,ITER_SOURCE , &iv,1 , skb->len); - err =l2cap_chan_send (chan, &msg, skb->len); + err =l2cap_chan_send (chan, &msg, skb->len,NULL );if (err >0 ) { netdev->stats.tx_bytes += err; netdev->stats.tx_packets++;
net/bluetooth/l2cap_core.c +38 -3
73 lines not on this page · raw message
net/bluetooth/l2cap_sock.c +14 -1
@@ -1106,6 +1106,7 @@ static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg, {struct sock *sk = sock->sk;struct l2cap_chan *chan =l2cap_pi (sk)->chan; +struct sockcm_cookie sockc;int err;BT_DBG ("sock %p, sk %p" , sock, sk);
@@ -1120,6 +1121,14 @@ static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg,if (sk->sk_state !=BT_CONNECTED )return -ENOTCONN ; +hci_sockcm_init (&sockc, sk); + +if (msg->msg_controllen) { + err =sock_cmsg_send (sk, msg, &sockc); +if (err) +return err; + } +lock_sock (sk); err =bt_sock_wait_ready (sk, msg->msg_flags);release_sock (sk);
@@ -1127,7 +1136,7 @@ static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg,return err;l2cap_chan_lock (chan); - err =l2cap_chan_send (chan, msg, len); + err =l2cap_chan_send (chan, msg, len, &sockc);l2cap_chan_unlock (chan);return err;
@@ -1168,6 +1177,10 @@ static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg,struct l2cap_pinfo *pi =l2cap_pi (sk);int err; +if (unlikely (flags &MSG_ERRQUEUE )) +return sock_recv_errqueue (sk, msg, len,SOL_BLUETOOTH , +BT_SCM_ERROR ); +lock_sock (sk); if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP,
net/bluetooth/smp.c +1 -1
@@ -608,7 +608,7 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)iov_iter_kvec (&msg.msg_iter,ITER_SOURCE , iv,2 ,1 + len); -l2cap_chan_send (chan, &msg,1 + len); +l2cap_chan_send (chan, &msg,1 + len,NULL );if (!chan->data)return ;
Signature · 1 line
2.48.1
PATCH v5 5/5 Bluetooth: SCO: add TX timestamping
In reply to Pauli VirtanenSupport TX timestamping in SCO sockets.
Not available for hdevs without SCO_FLOWCTL.
Support MSG_ERRQUEUE in SCO recvmsg.
---
Notes:
v5:
- use sockcm_init -> hci_sockcm_init
net/bluetooth/sco.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
net/bluetooth/sco.c +17 -2
@@ -378,7 +378,8 @@ static int sco_connect(struct sock *sk)return err; } -static int sco_send_frame (struct sock *sk,struct sk_buff *skb) +static int sco_send_frame (struct sock *sk,struct sk_buff *skb, +const struct sockcm_cookie *sockc) {struct sco_conn *conn =sco_pi (sk)->conn;int len = skb->len;
@@ -389,6 +390,7 @@ static int sco_send_frame(struct sock *sk, struct sk_buff *skb)BT_DBG ("sk %p len %d" , sk, len); +hci_setup_tx_timestamp (skb,1 , sockc);hci_send_sco (conn->hcon, skb);return len;
@@ -784,6 +786,7 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg, {struct sock *sk = sock->sk;struct sk_buff *skb; +struct sockcm_cookie sockc;int err;BT_DBG ("sock %p, sk %p" , sock, sk);
@@ -795,6 +798,14 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,if (msg->msg_flags &MSG_OOB )return -EOPNOTSUPP ; +hci_sockcm_init (&sockc, sk); + +if (msg->msg_controllen) { + err =sock_cmsg_send (sk, msg, &sockc); +if (err) +return err; + } + skb =bt_skb_sendmsg (sk, msg, len, len,0 ,0 );if (IS_ERR (skb))return PTR_ERR (skb);
@@ -802,7 +813,7 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,lock_sock (sk);if (sk->sk_state ==BT_CONNECTED ) - err =sco_send_frame (sk, skb); + err =sco_send_frame (sk, skb, &sockc);else err = -ENOTCONN ;
@@ -868,6 +879,10 @@ static int sco_sock_recvmsg(struct socket *sock, struct msghdr *msg,struct sock *sk = sock->sk;struct sco_pinfo *pi =sco_pi (sk); +if (unlikely (flags &MSG_ERRQUEUE )) +return sock_recv_errqueue (sk, msg, len,SOL_BLUETOOTH , +BT_SCM_ERROR ); +lock_sock (sk); if (sk->sk_state == BT_CONNECT2 &&
Signature · 1 line
2.48.1
This series was applied to bluetooth/bluetooth-next.git (master) by Luiz Augusto von Dentz <[email protected]>:
Hello:
This series was applied to bluetooth/bluetooth-next.git (master) by Luiz Augusto von Dentz <[email protected]>:
Quoted 5 lines · On Tue, 18 Mar 2025 21:06:41 +0200 you wrote:
Add support for TX timestamping in Bluetooth ISO/L2CAP/SCO sockets.
Add new COMPLETION timestamp type, to report a software timestamp when the hardware reports a packet completed. (Cc netdev for this)
Quoted 7 lines
Previous discussions:
https://lore.kernel.org/linux-bluetooth/[email protected]/
https://lore.kernel.org/linux-bluetooth/[email protected]/
https://lore.kernel.org/all/[email protected]/
https://lore.kernel.org/all/[email protected]/[...]
Here is the summary with links:
- [v5,1/5] net-timestamp: COMPLETION timestamp on packet tx completion
https://git.kernel.org/bluetooth/bluetooth-next/c/de4f56cf6cfd
- [v5,2/5] Bluetooth: add support for skb TX SND/COMPLETION timestamping
https://git.kernel.org/bluetooth/bluetooth-next/c/2a1b83b8a4b2 - [v5,3/5] Bluetooth: ISO: add TX timestamping https://git.kernel.org/bluetooth/bluetooth-next/c/6a536085b5e1 - [v5,4/5] Bluetooth: L2CAP: add TX timestamping https://git.kernel.org/bluetooth/bluetooth-next/c/f698693b9664 - [v5,5/5] Bluetooth: SCO: add TX timestamping https://git.kernel.org/bluetooth/bluetooth-next/c/01172ed6ff82
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html