* [PATCH BlueZ 1/2] bthost: fragment when sending ISO packets
@ 2025-07-23 18:33 Pauli Virtanen
2025-07-23 18:33 ` [PATCH BlueZ 2/2] iso-tester: add tests for hardware RX timestamps Pauli Virtanen
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Pauli Virtanen @ 2025-07-23 18:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Support fragmentation to controller MTU when sending ISO packets.
By default, fragment when exceeding btdev iso_mtu.
---
emulator/bthost.c | 102 +++++++++++++++++++++++++++++++---------------
emulator/bthost.h | 1 +
emulator/hciemu.c | 7 ++--
3 files changed, 75 insertions(+), 35 deletions(-)
diff --git a/emulator/bthost.c b/emulator/bthost.c
index 7ab4533d1..52c5b0bed 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -257,6 +257,7 @@ struct bthost {
bthost_new_conn_cb new_iso_cb;
void *new_iso_data;
uint16_t acl_mtu;
+ uint16_t iso_mtu;
struct rfcomm_connection_data *rfcomm_conn_data;
struct l2cap_conn_cb_data *new_l2cap_conn_data;
struct rfcomm_conn_cb_data *new_rfcomm_conn_data;
@@ -297,6 +298,7 @@ struct bthost *bthost_create(void)
/* Set defaults */
bthost->io_capability = 0x03;
bthost->acl_mtu = UINT16_MAX;
+ bthost->iso_mtu = UINT16_MAX;
return bthost;
}
@@ -583,6 +585,14 @@ void bthost_set_acl_mtu(struct bthost *bthost, uint16_t mtu)
bthost->acl_mtu = mtu;
}
+void bthost_set_iso_mtu(struct bthost *bthost, uint16_t mtu)
+{
+ if (!bthost)
+ return;
+
+ bthost->iso_mtu = mtu;
+}
+
static void queue_command(struct bthost *bthost, const struct iovec *iov,
int iovlen)
{
@@ -912,52 +922,80 @@ void bthost_send_sco(struct bthost *bthost, uint16_t handle, uint8_t pkt_status,
static void send_iso(struct bthost *bthost, uint16_t handle, bool ts,
uint16_t sn, uint32_t timestamp, uint8_t pkt_status,
- const struct iovec *iov, int iovcnt)
+ const struct iovec *iov, unsigned int iovcnt)
{
struct bt_hci_iso_hdr iso_hdr;
struct bt_hci_iso_data_start data_hdr;
uint8_t pkt = BT_H4_ISO_PKT;
struct iovec pdu[4 + iovcnt];
- uint16_t flags, dlen;
- int i, len = 0;
+ struct iovec payload[2 + iovcnt];
+ uint16_t payload_mtu = bthost->iso_mtu - sizeof(iso_hdr);
+ int len = 0, packet = 0;
+ unsigned int i;
for (i = 0; i < iovcnt; i++) {
- pdu[4 + i].iov_base = iov[i].iov_base;
- pdu[4 + i].iov_len = iov[i].iov_len;
+ payload[2 + i].iov_base = iov[i].iov_base;
+ payload[2 + i].iov_len = iov[i].iov_len;
len += iov[i].iov_len;
}
- pdu[0].iov_base = &pkt;
- pdu[0].iov_len = sizeof(pkt);
-
- flags = iso_flags_pack(0x02, ts);
- dlen = len + sizeof(data_hdr);
- if (ts)
- dlen += sizeof(timestamp);
-
- iso_hdr.handle = acl_handle_pack(handle, flags);
- iso_hdr.dlen = cpu_to_le16(dlen);
-
- pdu[1].iov_base = &iso_hdr;
- pdu[1].iov_len = sizeof(iso_hdr);
-
- if (ts) {
- timestamp = cpu_to_le32(timestamp);
-
- pdu[2].iov_base = ×tamp;
- pdu[2].iov_len = sizeof(timestamp);
- } else {
- pdu[2].iov_base = NULL;
- pdu[2].iov_len = 0;
- }
-
data_hdr.sn = cpu_to_le16(sn);
data_hdr.slen = cpu_to_le16(iso_data_len_pack(len, pkt_status));
- pdu[3].iov_base = &data_hdr;
- pdu[3].iov_len = sizeof(data_hdr);
+ if (ts) {
+ timestamp = cpu_to_le32(timestamp);
- send_packet(bthost, pdu, 4 + iovcnt);
+ payload[0].iov_base = ×tamp;
+ payload[0].iov_len = sizeof(timestamp);
+ len += sizeof(timestamp);
+ } else {
+ payload[0].iov_base = NULL;
+ payload[0].iov_len = 0;
+ }
+ iovcnt++;
+
+ payload[1].iov_base = &data_hdr;
+ payload[1].iov_len = sizeof(data_hdr);
+ len += sizeof(data_hdr);
+ iovcnt++;
+
+ /* ISO fragmentation */
+
+ do {
+ unsigned int pdu_iovcnt;
+ uint16_t iso_len, pb, flags;
+
+ if (packet == 0 && len <= payload_mtu)
+ pb = 0x02;
+ else if (packet == 0)
+ pb = 0x00;
+ else if (len <= payload_mtu)
+ pb = 0x03;
+ else
+ pb = 0x01;
+
+ flags = iso_flags_pack(pb, ts);
+ iso_len = len <= payload_mtu ? len : payload_mtu;
+
+ iso_hdr.handle = acl_handle_pack(handle, flags);
+ iso_hdr.dlen = cpu_to_le16(iso_len);
+
+ pdu[0].iov_base = &pkt;
+ pdu[0].iov_len = sizeof(pkt);
+
+ pdu[1].iov_base = &iso_hdr;
+ pdu[1].iov_len = sizeof(iso_hdr);
+
+ iov_pull_n(payload, &iovcnt, &pdu[2], &pdu_iovcnt,
+ ARRAY_SIZE(pdu) - 2, iso_len);
+ pdu_iovcnt += 2;
+
+ send_packet(bthost, pdu, pdu_iovcnt);
+
+ packet++;
+ ts = false;
+ len -= iso_len;
+ } while (len);
}
void bthost_send_iso(struct bthost *bthost, uint16_t handle, bool ts,
diff --git a/emulator/bthost.h b/emulator/bthost.h
index 456f631d5..0d8eca530 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -37,6 +37,7 @@ void bthost_set_send_handler(struct bthost *bthost, bthost_send_func handler,
void *user_data);
void bthost_set_acl_mtu(struct bthost *bthost, uint16_t mtu);
+void bthost_set_iso_mtu(struct bthost *bthost, uint16_t mtu);
void bthost_receive_h4(struct bthost *bthost, const void *data, uint16_t len);
diff --git a/emulator/hciemu.c b/emulator/hciemu.c
index 8529caae8..a59773618 100644
--- a/emulator/hciemu.c
+++ b/emulator/hciemu.c
@@ -308,7 +308,7 @@ static struct hciemu_client *hciemu_client_new(struct hciemu *hciemu,
{
struct hciemu_client *client;
int sv[2];
- uint16_t mtu;
+ uint16_t acl_mtu, iso_mtu;
client = new0(struct hciemu_client, 1);
if (!client)
@@ -343,8 +343,9 @@ static struct hciemu_client *hciemu_client_new(struct hciemu *hciemu,
client->host_source = create_source_bthost(sv[1], client->host);
client->start_source = g_idle_add(start_host, client);
- btdev_get_mtu(client->dev, &mtu, NULL, NULL);
- bthost_set_acl_mtu(client->host, mtu);
+ btdev_get_mtu(client->dev, &acl_mtu, NULL, &iso_mtu);
+ bthost_set_acl_mtu(client->host, acl_mtu);
+ bthost_set_iso_mtu(client->host, iso_mtu);
return client;
}
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH BlueZ 2/2] iso-tester: add tests for hardware RX timestamps
2025-07-23 18:33 [PATCH BlueZ 1/2] bthost: fragment when sending ISO packets Pauli Virtanen
@ 2025-07-23 18:33 ` Pauli Virtanen
2025-07-23 20:04 ` [BlueZ,1/2] bthost: fragment when sending ISO packets bluez.test.bot
2025-07-28 19:20 ` [PATCH BlueZ 1/2] " patchwork-bot+bluetooth
2 siblings, 0 replies; 4+ messages in thread
From: Pauli Virtanen @ 2025-07-23 18:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Add tests for HW RX timestamping. Also add test that sends large
packets to test ISO fragmentation.
Add tests:
ISO Receive - HW Timestamping
ISO Receive Fragmented - Success
ISO Receive Fragmented - HW Timestamping
---
tools/iso-tester.c | 53 +++++++++++++++++++++++++++++++++++++++++++---
tools/tester.h | 45 +++++++++++++++++++++++++++++----------
2 files changed, 84 insertions(+), 14 deletions(-)
diff --git a/tools/iso-tester.c b/tools/iso-tester.c
index 6aefb5196..40465a5f7 100644
--- a/tools/iso-tester.c
+++ b/tools/iso-tester.c
@@ -1013,6 +1013,12 @@ static const struct iovec send_48_2_1 = {
.iov_len = sizeof(data_48_2_1),
};
+static const uint8_t data_large[512] = { [0 ... 511] = 0xff };
+static const struct iovec send_large = {
+ .iov_base = (void *)data_large,
+ .iov_len = sizeof(data_large),
+};
+
static const struct iso_client_data connect_16_2_1_send = {
.qos = QOS_16_2_1,
.expect_err = 0,
@@ -1049,6 +1055,13 @@ static const struct iso_client_data listen_16_2_1_recv = {
.server = true,
};
+static const struct iso_client_data listen_16_2_1_recv_frag = {
+ .qos = QOS_16_2_1,
+ .expect_err = 0,
+ .recv = &send_large,
+ .server = true,
+};
+
static const struct iso_client_data listen_16_2_1_recv_ts = {
.qos = QOS_16_2_1,
.expect_err = 0,
@@ -1082,6 +1095,26 @@ static const struct iso_client_data listen_16_2_1_recv_rx_timestamping = {
SOF_TIMESTAMPING_RX_SOFTWARE),
};
+static const struct iso_client_data listen_16_2_1_recv_hw_timestamping = {
+ .qos = QOS_16_2_1,
+ .expect_err = 0,
+ .recv = &send_16_2_1,
+ .server = true,
+ .ts = true,
+ .so_timestamping = (SOF_TIMESTAMPING_RAW_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE),
+};
+
+static const struct iso_client_data listen_16_2_1_recv_frag_hw_timestamping = {
+ .qos = QOS_16_2_1,
+ .expect_err = 0,
+ .recv = &send_large,
+ .server = true,
+ .ts = true,
+ .so_timestamping = (SOF_TIMESTAMPING_RAW_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE),
+};
+
static const struct iso_client_data defer_16_2_1 = {
.qos = QOS_16_2_1,
.expect_err = 0,
@@ -2247,8 +2280,10 @@ static gboolean iso_recv_data(GIOChannel *io, GIOCondition cond,
}
}
- if (isodata->so_timestamping & SOF_TIMESTAMPING_RX_SOFTWARE)
- rx_timestamp_check(&msg);
+ if (rx_timestamp_check(&msg, isodata->so_timestamping, 1000) < 0) {
+ tester_test_failed();
+ return FALSE;
+ }
if (data->step) {
data->step--;
@@ -2290,7 +2325,7 @@ static void iso_recv(struct test_data *data, GIOChannel *io)
count = isodata->pkt_seqnum ? 2 : 1;
for (j = 0; j < count; ++j) {
- bthost_send_iso(host, data->handle, isodata->ts, sn++, 0,
+ bthost_send_iso(host, data->handle, isodata->ts, sn++, j + 1,
isodata->pkt_status, isodata->recv, 1);
data->step++;
}
@@ -3718,6 +3753,10 @@ int main(int argc, char *argv[])
test_iso("ISO Receive - Success", &listen_16_2_1_recv, setup_powered,
test_listen);
+ test_iso("ISO Receive Fragmented - Success", &listen_16_2_1_recv_frag,
+ setup_powered,
+ test_listen);
+
test_iso("ISO Receive Timestamped - Success", &listen_16_2_1_recv_ts,
setup_powered,
test_listen);
@@ -3734,6 +3773,14 @@ int main(int argc, char *argv[])
&listen_16_2_1_recv_rx_timestamping,
setup_powered, test_listen);
+ test_iso("ISO Receive - HW Timestamping",
+ &listen_16_2_1_recv_hw_timestamping,
+ setup_powered, test_listen);
+
+ test_iso("ISO Receive Fragmented - HW Timestamping",
+ &listen_16_2_1_recv_frag_hw_timestamping,
+ setup_powered, test_listen);
+
test_iso("ISO Defer - Success", &defer_16_2_1, setup_powered,
test_defer);
diff --git a/tools/tester.h b/tools/tester.h
index 647c35485..896475110 100644
--- a/tools/tester.h
+++ b/tools/tester.h
@@ -204,11 +204,14 @@ static inline int tx_tstamp_recv(struct tx_tstamp_data *data, int sk, int len)
return data->count - data->pos;
}
-static inline int rx_timestamp_check(struct msghdr *msg)
+static inline int rx_timestamp_check(struct msghdr *msg, uint32_t flags,
+ int64_t expect_t_hw)
{
+ bool soft_tstamp = flags & SOF_TIMESTAMPING_RX_SOFTWARE;
+ bool hw_tstamp = flags & SOF_TIMESTAMPING_RX_HARDWARE;
struct cmsghdr *cmsg;
struct timespec now;
- int64_t t = 0;
+ int64_t t = 0, t_hw = 0;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
struct scm_timestamping *tss;
@@ -220,21 +223,40 @@ static inline int rx_timestamp_check(struct msghdr *msg)
tss = (struct scm_timestamping *)CMSG_DATA(cmsg);
t = TS_NSEC(&tss->ts[0]);
+ t_hw = TS_NSEC(&tss->ts[2]);
break;
}
+
if (!cmsg) {
+ if (!soft_tstamp && !hw_tstamp)
+ return 0;
tester_warn("RX timestamp missing");
return -EINVAL;
- }
-
- clock_gettime(CLOCK_REALTIME, &now);
-
- if (TS_NSEC(&now) < t || TS_NSEC(&now) > t + SEC_NSEC(10)) {
- tester_warn("RX timestamp bad time");
+ } else if (!soft_tstamp && !hw_tstamp) {
+ tester_warn("Spurious RX timestamp");
return -EINVAL;
}
- tester_print("Got valid RX timestamp");
+ if (soft_tstamp) {
+ clock_gettime(CLOCK_REALTIME, &now);
+
+ if (TS_NSEC(&now) < t || TS_NSEC(&now) > t + SEC_NSEC(10)) {
+ tester_warn("Software RX timestamp bad time");
+ return -EINVAL;
+ }
+
+ tester_print("Got valid RX software timestamp");
+ }
+
+ if (hw_tstamp) {
+ if (t_hw != expect_t_hw) {
+ tester_warn("Bad hardware RX timestamp: %d != %d",
+ (int)t_hw, (int)expect_t_hw);
+ return -EINVAL;
+ }
+ tester_print("Got valid hardware RX timestamp");
+ }
+
return 0;
}
@@ -260,7 +282,7 @@ static inline ssize_t recv_tstamp(int sk, void *buf, size_t size, bool tstamp)
if (ret < 0 || !tstamp)
return ret;
- if (rx_timestamp_check(&msg)) {
+ if (rx_timestamp_check(&msg, SOF_TIMESTAMPING_RX_SOFTWARE, 0)) {
errno = EIO;
return -1;
}
@@ -272,7 +294,8 @@ static inline int rx_timestamping_init(int fd, int flags)
{
socklen_t len = sizeof(flags);
- if (!(flags & SOF_TIMESTAMPING_RX_SOFTWARE))
+ if (!(flags & (SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE)))
return 0;
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &flags, len) < 0) {
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: [BlueZ,1/2] bthost: fragment when sending ISO packets
2025-07-23 18:33 [PATCH BlueZ 1/2] bthost: fragment when sending ISO packets Pauli Virtanen
2025-07-23 18:33 ` [PATCH BlueZ 2/2] iso-tester: add tests for hardware RX timestamps Pauli Virtanen
@ 2025-07-23 20:04 ` bluez.test.bot
2025-07-28 19:20 ` [PATCH BlueZ 1/2] " patchwork-bot+bluetooth
2 siblings, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2025-07-23 20:04 UTC (permalink / raw)
To: linux-bluetooth, pav
[-- Attachment #1: Type: text/plain, Size: 1688 bytes --]
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=985227
---Test result---
Test Summary:
CheckPatch PENDING 0.28 seconds
GitLint PENDING 0.28 seconds
BuildEll PASS 20.77 seconds
BluezMake PASS 2595.69 seconds
MakeCheck PASS 20.45 seconds
MakeDistcheck PASS 184.68 seconds
CheckValgrind PASS 234.71 seconds
CheckSmatch WARNING 307.26 seconds
bluezmakeextell PASS 127.60 seconds
IncrementalBuild PENDING 0.25 seconds
ScanBuild PASS 914.16 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
emulator/bthost.c:678:28: warning: Variable length array is used.emulator/bthost.c:679:32: warning: Variable length array is used.emulator/bthost.c:896:28: warning: Variable length array is used.emulator/bthost.c:930:28: warning: Variable length array is used.emulator/bthost.c:931:32: warning: Variable length array is used.
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH BlueZ 1/2] bthost: fragment when sending ISO packets
2025-07-23 18:33 [PATCH BlueZ 1/2] bthost: fragment when sending ISO packets Pauli Virtanen
2025-07-23 18:33 ` [PATCH BlueZ 2/2] iso-tester: add tests for hardware RX timestamps Pauli Virtanen
2025-07-23 20:04 ` [BlueZ,1/2] bthost: fragment when sending ISO packets bluez.test.bot
@ 2025-07-28 19:20 ` patchwork-bot+bluetooth
2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+bluetooth @ 2025-07-28 19:20 UTC (permalink / raw)
To: Pauli Virtanen; +Cc: linux-bluetooth
Hello:
This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Wed, 23 Jul 2025 21:33:33 +0300 you wrote:
> Support fragmentation to controller MTU when sending ISO packets.
> By default, fragment when exceeding btdev iso_mtu.
> ---
> emulator/bthost.c | 102 +++++++++++++++++++++++++++++++---------------
> emulator/bthost.h | 1 +
> emulator/hciemu.c | 7 ++--
> 3 files changed, 75 insertions(+), 35 deletions(-)
Here is the summary with links:
- [BlueZ,1/2] bthost: fragment when sending ISO packets
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=fd80f2354ead
- [BlueZ,2/2] iso-tester: add tests for hardware RX timestamps
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=0084cfe5634b
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-07-28 19:19 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-23 18:33 [PATCH BlueZ 1/2] bthost: fragment when sending ISO packets Pauli Virtanen
2025-07-23 18:33 ` [PATCH BlueZ 2/2] iso-tester: add tests for hardware RX timestamps Pauli Virtanen
2025-07-23 20:04 ` [BlueZ,1/2] bthost: fragment when sending ISO packets bluez.test.bot
2025-07-28 19:20 ` [PATCH BlueZ 1/2] " patchwork-bot+bluetooth
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox