From patchwork Wed Apr 3 16:43:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 13616489 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EB5713A88B for ; Wed, 3 Apr 2024 16:46:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=185.185.170.37 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162765; cv=pass; b=jHUrAUkDIXPRMDloH38jw2cxHzvaifVecJZkDccGwROhOw0vvfPS0a2KuzfI6vQQ4VDaOJ66Mb+zHOUmNnNw7/kxTO23+iwxJ9L34vq6bJsS/hBH16x4WHWa9ujJIDHCgr6F3x8oGP9enakGBnbr/ZSulDFZk272I/Fr/ZYagNM= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162765; c=relaxed/simple; bh=Rbylmd5Rutq4+i7hfKxure17mD3Xd1qpj1qB5aB12wg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p/GAIPJjNBEhLto33EfqKfe7AxMl9DrmsmoQ3dnjj82cEP0oH5Uz/6AOjyhgUK9lmHCUnSx0HiIM/k7t8Dpp8duLll5jTJHCVGP9Lr/yo9WSH3HfnkZTGAhf2l3Zqnez2cB+YRqWzw5h3zLiURdo7o/l7qb75+Zw7hS76T5+Qmg= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b=j84FpjV3; arc=pass smtp.client-ip=185.185.170.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b="j84FpjV3" Received: from monolith.lan (unknown [193.138.7.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4V8rGx4Jmbz49Q32; Wed, 3 Apr 2024 19:46:01 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162761; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DQHBUQvSEBJ4gmBHTLJ902z3SIHMiTvD4BQrU7DmKLU=; b=j84FpjV323eQ6hCs0/xAOoUYqROzJBp2ngj4aRXEaO6OmL5oFBBD+5Go907XGt9Cas6zyV rbHuEKqF7lVnccG6CtRGdOhk1kJMt0DYrc9SWBKQDcrVC+MOxbU3uJLkRKCmejuhIFX7NT 70SaFmxkHxqmmfZFKCtKoq85+SSHtEi6F620XFF1c13Ofno+fhMQJ+Kd11lfEHUfGcoYY5 bRWYuoDB1knHiGFxkIc3Xo3Vy/lQOW5JUR66v42Zw9xfaWRcv6wvhBUZYfmvO36tDn0BMp 43O+e0nJj/q6OFc7ZHyAQzT5CVXoX31Oqb7G8bT5J0Vh5UdEJPfaCYlE1cPHvQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162761; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DQHBUQvSEBJ4gmBHTLJ902z3SIHMiTvD4BQrU7DmKLU=; b=EmQNzLwEXdVpor9Oa9tTgHkT1n5iw3eV+eKhqP5KTXMUAyinhNr+I9CeEKuzReYYF53x9i xeiqfnUY4AFu0xP/QSeohXSeVO3uGKquavVym+ymcJj0IY4M53kw35wGvNnn11r2TRYDE/ as12ZXzB9jg3xAA/OXq0Y0d/XhymyFBtGctCLAvcllv6gUzUU2SXWwW/wGER8aBsIH8rod CmjsHkYFO6HyZoyWA1yv9aiG/SjG7T6npxt4CnI9CDBURLDbD4ZyzSUqaik52qQu7mDKKn l9UT1WDvJtJWlo4QjVTnazx9s+h6HObGfktsH0SABccR4ctkcXRlJJQbVXQCoQ== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1712162761; a=rsa-sha256; cv=none; b=TNlbmdAaT7I3LTbXJ4jxvSO2nP0zD9K2PTSFpoIj0ZH513GBE83xrOfJNNT1abY6xfpr23 iOnzBgO9RlkUpD56CPKAyHeby6VasH774QQKrwUbsbm2u+CrISJssD6oj/877gCBroRFMT 940cg4st02IxZsmJjaXuL7SS/PBPcgqxr7n84mCF2VEpjlITdkX7hTnFkO/M/+BfQvtTpO 01E8D4fSrjbJT9SkBOZ990iIxPDoPXKFD3pdw3k0Kse60hfm792/wXCN9GPAeP9U7QG6JZ bkApNRlNCCFi71JQmNR2+UJExDdpzKOBxeHHeAppQx1YCP1B9kL8ExhKMUytLQ== From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ v5 1/7] lib: add BT_SCM_ERROR Date: Wed, 3 Apr 2024 19:43:20 +0300 Message-ID: <1fd56079e4aa89aa1056a3cf185610a683ee02ba.1712161649.git.pav@iki.fi> X-Mailer: git-send-email 2.44.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add new CMSG type used in new kernel TX timestamping support. --- lib/bluetooth.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/bluetooth.h b/lib/bluetooth.h index 75dc960c8..a4ed65d0b 100644 --- a/lib/bluetooth.h +++ b/lib/bluetooth.h @@ -141,6 +141,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 From patchwork Wed Apr 3 16:43:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 13616493 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D82C314A62A for ; Wed, 3 Apr 2024 16:46:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=185.185.170.37 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162767; cv=pass; b=hawSCSgtUnghJEjwNGePQNCs0R3V2kKwh+Nx/geUoL2XV7p16z8lc9nxLqglJdl4+nF4XFS1zSrKh3yUyYQnHGTrTRKfnRZbDd+704BU1b8LBMQtLpXQz4BtnSZh81wxu06kGTv6S+2xpgE1V0aV745R1XQuyd1DjMTrYuqm7C4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162767; c=relaxed/simple; bh=StPEuiKAeiq82XBkYiuWhlDUKTkobFlfmXkJOPMvKmE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GOzbd5j0QzVHsS0SZ0Y4PZPJqiNp96iF/SGIjs0Saf8R13nbvxfSdPihxK26buXazE57EB0xPDz09SGaP4FDy3nAvu82GZPP87MXtcPdI55rg4OGC8UdGgswe5qtp6K8k7rab3hpmG0H+rcV4PMiUK/TCv4jGD+/CQGTb0oVF0Y= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b=hJju99DM; arc=pass smtp.client-ip=185.185.170.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b="hJju99DM" Received: from monolith.lan (unknown [193.138.7.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4V8rGx6PF1z49Q3T; Wed, 3 Apr 2024 19:46:01 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162762; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TDgcnUwgNYO1QAdjXUz+rX6ZwN/SF2lcJ3PIv/uFfOU=; b=hJju99DMDhE7IyHWVFVH+QTUr0ThM5HUAeNGpQvIefE4pJB3bUviCiOX2zhefIUCLaPJf0 H3y19KS/RdUK837sjiIGQ3AO4J0z6ZPxlQMnFpaCbTQu4yYLMziJlYhDrlCQ9TBg6N+882 usjb4NnXpDoJSGqwx2BYKhPTxVl475yZLALic/d8BiHzt43zuATbY6kiUakbpeATcneYXZ tzQ0lvQM8DejjXZXtnheI49xzKAEHPYB/Qz5VACn9Do5lfVgnaFCb5rMksihUU9YQCyRQU Tqq/O9DSyoOGqD8OpcrLTbhlQKZDUBQo28cGdGDtW8fv7eNd2hNF6Ic0bUWXeQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162762; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TDgcnUwgNYO1QAdjXUz+rX6ZwN/SF2lcJ3PIv/uFfOU=; b=ty+vix+ZzjU8mGQMZ33B7p11/h0YqY3mB+ytfjAyOMCSkSN/ZbNCYjTeRWTzM6faVWfwNp s8oZmm3awbAfSNAGO55lnlZk2O0vLBqv1hDAR7LctZlCZLI+sQoZ2/a0F6n5JDiPIJ2T/B hX//GvO6/4BI/ZnQ49jfD+Bse2QGBvnE5j7aiqDorq87X8fcoaTmi5zLuwd+4kyweIFSaR crSi08zL3PoGnsuG7SvLTCoX0+wnNho2MZNPB0HAMafAmMTNHbGgCvYJHmLtxO7KEurwdY dPEg6Qo2zTARPQLbwJ+/29h9UV+BpB0zRPenuaCScyclzFSqccD7skOi+5J9eg== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1712162762; a=rsa-sha256; cv=none; b=ManfpcjeIJ8iI5hqykyH8U5epy9+T5bL8fSRDQNj5kNqnmooYUg6E+mK6VDRoRnjbILg75 An3SU3L2hZsZVHOO+bUrTnm4Uf47KZLsLj5xi7px7RVLJcARlLTGmohW3f3U/gPQu8ND1D xzGv8kZqO8Kfirr/OqVAT3MZO2+F6qgQApNc8OtBAPnwJ3x9JJla43mVZLFNwXS9CNjBD2 LsBbxVUiIwRYcGeVrtWtxKlLG92JfuCSglU4ocBmfDSwT3dlsUe27EQkUtCDTcALlSdLrX i09BqFu0HlU8H9qxVle3jHlGHSYqs+mIcZHIgFTMaQUxGkylrvoO5rhu+LeUqg== From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ v5 2/7] iso-tester: Add tests for TX timestamping Date: Wed, 3 Apr 2024 19:43:21 +0300 Message-ID: X-Mailer: git-send-email 2.44.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add TX timestamping test utilities in new tools/tester.h, so that they can be shared between testers. Add tests: ISO Send - TX Timestamping ISO Send - TX Sched Timestamping ISO Send - TX Msg Timestamping --- tools/iso-tester.c | 182 ++++++++++++++++++++++++++++++++++++++++++--- tools/tester.h | 163 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 335 insertions(+), 10 deletions(-) create mode 100644 tools/tester.h diff --git a/tools/iso-tester.c b/tools/iso-tester.c index 60afef301..14a2e7d46 100644 --- a/tools/iso-tester.c +++ b/tools/iso-tester.c @@ -18,6 +18,9 @@ #include #include +#include +#include + #include #include "lib/bluetooth.h" @@ -34,6 +37,8 @@ #include "src/shared/util.h" #include "src/shared/queue.h" +#include "tester.h" + #define QOS_IO(_interval, _latency, _sdu, _phy, _rtn) \ { \ .interval = _interval, \ @@ -462,11 +467,12 @@ struct test_data { uint16_t handle; uint16_t acl_handle; struct queue *io_queue; - unsigned int io_id[2]; + unsigned int io_id[3]; uint8_t client_num; int step; bool reconnect; bool suspending; + struct tx_tstamp_data tx_ts; }; struct iso_client_data { @@ -487,6 +493,22 @@ struct iso_client_data { size_t base_len; bool listen_bind; bool pa_bind; + + /* Enable SO_TIMESTAMPING with these flags */ + uint32_t so_timestamping; + + /* Enable SO_TIMESTAMPING using CMSG instead of setsockopt() */ + bool cmsg_timestamping; + + /* Number of additional packets to send, before SO_TIMESTAMPING. + * Used to test kernel timestamp TX queue logic. + */ + unsigned int repeat_send_pre_ts; + + /* Number of additional packets to send, after SO_TIMESTAMPING. + * Used for testing TX timestamping OPT_ID. + */ + unsigned int repeat_send; }; typedef bool (*iso_defer_accept_t)(struct test_data *data, GIOChannel *io); @@ -677,15 +699,14 @@ static void io_free(void *data) static void test_data_free(void *test_data) { struct test_data *data = test_data; + unsigned int i; if (data->io_queue) queue_destroy(data->io_queue, io_free); - if (data->io_id[0] > 0) - g_source_remove(data->io_id[0]); - - if (data->io_id[1] > 0) - g_source_remove(data->io_id[1]); + for (i = 0; i < ARRAY_SIZE(data->io_id); ++i) + if (data->io_id[i] > 0) + g_source_remove(data->io_id[i]); free(data); } @@ -987,6 +1008,38 @@ static const struct iso_client_data connect_16_2_1_send = { .send = &send_16_2_1, }; +static const struct iso_client_data connect_send_tx_timestamping = { + .qos = QOS_16_2_1, + .expect_err = 0, + .send = &send_16_2_1, + .so_timestamping = (SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_OPT_ID | + SOF_TIMESTAMPING_TX_SOFTWARE), + .repeat_send = 1, + .repeat_send_pre_ts = 2, +}; + +static const struct iso_client_data connect_send_tx_sched_timestamping = { + .qos = QOS_16_2_1, + .expect_err = 0, + .send = &send_16_2_1, + .so_timestamping = (SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_OPT_TSONLY | + SOF_TIMESTAMPING_TX_SCHED), + .repeat_send = 1, +}; + +static const struct iso_client_data connect_send_tx_cmsg_timestamping = { + .qos = QOS_16_2_1, + .expect_err = 0, + .send = &send_16_2_1, + .so_timestamping = (SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_TX_SOFTWARE), + .repeat_send = 1, + .cmsg_timestamping = true, +}; + static const struct iso_client_data listen_16_2_1_recv = { .qos = QOS_16_2_1, .expect_err = 0, @@ -1410,14 +1463,17 @@ static void bthost_recv_data(const void *buf, uint16_t len, void *user_data) struct test_data *data = user_data; const struct iso_client_data *isodata = data->test_data; + --data->step; + tester_print("Client received %u bytes of data", len); if (isodata->send && (isodata->send->iov_len != len || memcmp(isodata->send->iov_base, buf, len))) { if (!isodata->recv->iov_base) tester_test_failed(); - } else + } else if (!data->step) { tester_test_passed(); + } } static void bthost_iso_disconnected(void *user_data) @@ -2058,17 +2114,93 @@ static void iso_recv(struct test_data *data, GIOChannel *io) data->io_id[0] = g_io_add_watch(io, G_IO_IN, iso_recv_data, data); } -static void iso_send(struct test_data *data, GIOChannel *io) +static gboolean iso_recv_errqueue(GIOChannel *io, GIOCondition cond, + gpointer user_data) { + struct test_data *data = user_data; const struct iso_client_data *isodata = data->test_data; - ssize_t ret; + int sk = g_io_channel_unix_get_fd(io); + int err; + + data->step--; + + err = tx_tstamp_recv(&data->tx_ts, sk, isodata->send->iov_len); + if (err > 0) + return TRUE; + else if (!err && !data->step) + tester_test_passed(); + else + tester_test_failed(); + + data->io_id[2] = 0; + return FALSE; +} + +static void iso_tx_timestamping(struct test_data *data, GIOChannel *io) +{ + const struct iso_client_data *isodata = data->test_data; + int so = isodata->so_timestamping; int sk; + int err; + unsigned int count; + + if (!(isodata->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK)) + return; + + tester_print("Enabling TX timestamping"); + + tx_tstamp_init(&data->tx_ts, isodata->so_timestamping); + + for (count = 0; count < isodata->repeat_send + 1; ++count) + data->step += tx_tstamp_expect(&data->tx_ts); sk = g_io_channel_unix_get_fd(io); + data->io_id[2] = g_io_add_watch(io, G_IO_ERR, iso_recv_errqueue, data); + + if (isodata->cmsg_timestamping) + so &= ~SOF_TIMESTAMPING_TX_RECORD_MASK; + + err = setsockopt(sk, SOL_SOCKET, SO_TIMESTAMPING, &so, sizeof(so)); + if (err < 0) { + tester_warn("setsockopt SO_TIMESTAMPING: %s (%d)", + strerror(errno), errno); + tester_test_failed(); + return; + } +} + +static void iso_send_data(struct test_data *data, GIOChannel *io) +{ + const struct iso_client_data *isodata = data->test_data; + char control[CMSG_SPACE(sizeof(uint32_t))]; + struct msghdr msg = { + .msg_iov = (struct iovec *)isodata->send, + .msg_iovlen = 1, + }; + struct cmsghdr *cmsg; + ssize_t ret; + int sk; + tester_print("Writing %zu bytes of data", isodata->send->iov_len); - ret = writev(sk, isodata->send, 1); + sk = g_io_channel_unix_get_fd(io); + + if (isodata->cmsg_timestamping) { + memset(control, 0, sizeof(control)); + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMPING; + cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); + + *((uint32_t *)CMSG_DATA(cmsg)) = (isodata->so_timestamping & + SOF_TIMESTAMPING_TX_RECORD_MASK); + } + + ret = sendmsg(sk, &msg, 0); if (ret < 0 || isodata->send->iov_len != (size_t) ret) { tester_warn("Failed to write %zu bytes: %s (%d)", isodata->send->iov_len, strerror(errno), errno); @@ -2076,6 +2208,22 @@ static void iso_send(struct test_data *data, GIOChannel *io) return; } + data->step++; +} + +static void iso_send(struct test_data *data, GIOChannel *io) +{ + const struct iso_client_data *isodata = data->test_data; + unsigned int count; + + for (count = 0; count < isodata->repeat_send_pre_ts; ++count) + iso_send_data(data, io); + + iso_tx_timestamping(data, io); + + for (count = 0; count < isodata->repeat_send + 1; ++count) + iso_send_data(data, io); + if (isodata->bcast) { tester_test_passed(); return; @@ -3197,6 +3345,20 @@ int main(int argc, char *argv[]) test_iso("ISO Send - Success", &connect_16_2_1_send, setup_powered, test_connect); + /* Test basic TX timestamping */ + test_iso("ISO Send - TX Timestamping", &connect_send_tx_timestamping, + setup_powered, test_connect); + + /* Test schedule-time TX timestamps are emitted */ + test_iso("ISO Send - TX Sched Timestamping", + &connect_send_tx_sched_timestamping, setup_powered, + test_connect); + + /* Test TX timestamping with flags set via per-packet CMSG */ + test_iso("ISO Send - TX CMSG Timestamping", + &connect_send_tx_cmsg_timestamping, setup_powered, + test_connect); + test_iso("ISO Receive - Success", &listen_16_2_1_recv, setup_powered, test_listen); diff --git a/tools/tester.h b/tools/tester.h new file mode 100644 index 000000000..617de842e --- /dev/null +++ b/tools/tester.h @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2022 Intel Corporation. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SEC_NSEC(_t) ((_t) * 1000000000LL) +#define TS_NSEC(_ts) (SEC_NSEC((_ts)->tv_sec) + (_ts)->tv_nsec) + +struct tx_tstamp_data { + struct { + uint32_t id; + uint32_t type; + } expect[16]; + unsigned int pos; + unsigned int count; + unsigned int sent; + uint32_t so_timestamping; +}; + +static inline void tx_tstamp_init(struct tx_tstamp_data *data, + uint32_t so_timestamping) +{ + memset(data, 0, sizeof(*data)); + memset(data->expect, 0xff, sizeof(data->expect)); + + data->so_timestamping = so_timestamping; +} + +static inline int tx_tstamp_expect(struct tx_tstamp_data *data) +{ + unsigned int pos = data->count; + int steps; + + if (data->so_timestamping & SOF_TIMESTAMPING_TX_SCHED) { + g_assert(pos < ARRAY_SIZE(data->expect)); + data->expect[pos].type = SCM_TSTAMP_SCHED; + data->expect[pos].id = data->sent; + pos++; + } + + if (data->so_timestamping & SOF_TIMESTAMPING_TX_SOFTWARE) { + g_assert(pos < ARRAY_SIZE(data->expect)); + data->expect[pos].type = SCM_TSTAMP_SND; + data->expect[pos].id = data->sent; + pos++; + } + + data->sent++; + + steps = pos - data->count; + data->count = pos; + return steps; +} + +static inline int tx_tstamp_recv(struct tx_tstamp_data *data, int sk, int len) +{ + unsigned char control[512]; + ssize_t ret; + char buf[1024]; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg; + struct scm_timestamping *tss = NULL; + struct sock_extended_err *serr = NULL; + struct timespec now; + + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + ret = recvmsg(sk, &msg, MSG_ERRQUEUE); + if (ret < 0) { + tester_warn("Failed to read from errqueue: %s (%d)", + strerror(errno), errno); + return -EINVAL; + } + + if (data->so_timestamping & SOF_TIMESTAMPING_OPT_TSONLY) { + if (ret != 0) { + tester_warn("Packet copied back to errqueue"); + return -EINVAL; + } + } else if (len > ret) { + tester_warn("Packet not copied back to errqueue: %zd", ret); + return -EINVAL; + } + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_TIMESTAMPING) { + tss = (void *)CMSG_DATA(cmsg); + } else if (cmsg->cmsg_level == SOL_BLUETOOTH && + cmsg->cmsg_type == BT_SCM_ERROR) { + serr = (void *)CMSG_DATA(cmsg); + } + } + + if (!tss) { + tester_warn("SCM_TIMESTAMPING not found"); + return -EINVAL; + } + + if (!serr) { + tester_warn("BT_SCM_ERROR not found"); + return -EINVAL; + } + + if (serr->ee_errno != ENOMSG || + serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) { + tester_warn("BT_SCM_ERROR wrong for timestamping"); + return -EINVAL; + } + + clock_gettime(CLOCK_REALTIME, &now); + + if (TS_NSEC(&now) < TS_NSEC(tss->ts) || + TS_NSEC(&now) > TS_NSEC(tss->ts) + SEC_NSEC(10)) { + tester_warn("nonsense in timestamp"); + return -EINVAL; + } + + if (data->pos >= data->count) { + tester_warn("Too many timestamps"); + return -EINVAL; + } + + if ((data->so_timestamping & SOF_TIMESTAMPING_OPT_ID) && + serr->ee_data != data->expect[data->pos].id) { + tester_warn("Bad timestamp id %u", serr->ee_data); + return -EINVAL; + } + + if (serr->ee_info != data->expect[data->pos].type) { + tester_warn("Bad timestamp type %u", serr->ee_info); + return -EINVAL; + } + + tester_print("Got valid TX timestamp %u", data->pos); + + ++data->pos; + + return data->count - data->pos; +} From patchwork Wed Apr 3 16:43:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 13616492 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A80B14C596 for ; Wed, 3 Apr 2024 16:46:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=185.185.170.37 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162767; cv=pass; b=OXgX8th/buiSpB3qFpo0y6M5iJeha/b244SRoJvNhQrdeCfJ4RjjJm5hh1NulalW4ntTXNi1tnJ9YC5qjeos1kiKBh0KtG4xn/NLkq9C+cW+BSl0i+6Czmp044kQ7zWaTrw/6ShuvHGPxWqXGOZIVV+lNN4lHdOfvkFK8EX/7cs= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162767; c=relaxed/simple; bh=TBTq1/pgDhwcGI4CajQNhPEXompuuII3oKojAvLbc/w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZDhCYOs20WYDz0jhQneGh0iV1v6SyJwYcfErMBp8VLSzpqQ05yCtHco4ojzXKQsGIVyUkrRBPL7rBhXi54XfD3DGaVLnKdDlfp9SVS2jqe1eb9uq61cU8+1Dg99bIOebPMvl50yKYqnT7nOyLzTqoc/qVo9k4mAq8jl+5kNLjIg= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b=HjYl4l4H; arc=pass smtp.client-ip=185.185.170.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b="HjYl4l4H" Received: from monolith.lan (unknown [193.138.7.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4V8rGy16Ygz49Q4X; Wed, 3 Apr 2024 19:46:02 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162762; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=v7TQLnR6F+9sRt9uphya0SMZPbennG+mfKO57PtPSb8=; b=HjYl4l4HQwyuym+eyJ3IIyhljuqWiXtbGb9dbAY/Sdt3qn0zVeltmh71e0WTOspnsIe0oE nM8YoqcVGNabU6+xDY4faVZk5QH48tYq+bd9R6Bp2e6QCvswdvENG47JD2svedn4zlWrmw L8IlwE+5zHTfdGsFBepfm0G47M63lfyD6X7OIN069ui4Ghbl3HTlh8QyU4BuQb3oy3cEW0 xt3UI/zfwiaZnuHssM0XoNKIZHxNCoS+TsXBBWtFy80rIobnbSis0K2CPaBs5dZ/fha+4B OVD9VCir6DCjQ0bmI3JtpUtWhAajk96CJh6W/9MKINBUkQfkUzUPKLk7dgHmOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162762; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=v7TQLnR6F+9sRt9uphya0SMZPbennG+mfKO57PtPSb8=; b=GYySNyDR0Eqv7sPJybUPdsPQCvo9Ys2lHQRUh9cmx14NNf/0JgXvB5ReUGBJxNSAAh8M3b XT5nTPA1m3DQY4GldeYqCpZcnLYqFAGcosiGLW/vghcLDc77DqyBtzcKuucchFTiu/gk5j 3xqTyPrx8a+DawQCHRMZL1pa9pM/y50NgoigIz2tha3sGhkvidI0hvoFCDW7lBerPaS5NK xze2FN+a99BCqup6C66kJSSrn6qLL7E852pLCrOGkPiJdAwwQljzE50Nr4S6JpdYlzYzyC ZX/TeCIn3L+wbI9csoXbEF2kOXvZJssqDKanrY1yyvgzFlESkXRAJlT56lSEIw== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1712162762; a=rsa-sha256; cv=none; b=kX1ZTea69uDUZ9GVr6XUDa8UFZdYsFMS35qYvFXiiwTRlhcdU0A/6COY17ivKLXIVjgKw5 xNv14Hv6XIeh9BBfgkJoCygxUusAjVZx6BX8lU+TBU/0W2NujVoyNTlJgP2AINt5PfIaM/ 7aSz9EuulOyMGggrY7IsSG/S9Q7eOIr5nWneC3E3pOHmQJsdFtTUwC+la4mz4nI2ZuXxWq ugDzBFe3GrKO1k7OqB/1zEwwhuyHnPvdlJet6uEb7FC6Tvz6MQ+S+Q7NU/4wwIAP1hv/o6 AVwri4ZOA3ylcXsSH8vBtb7K7tfemeFL+zyaCmCLrHNXKyznIim+2tWlt+2OlA== From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ v5 3/7] l2cap-tester: Add test for TX timestamping Date: Wed, 3 Apr 2024 19:43:22 +0300 Message-ID: X-Mailer: git-send-email 2.44.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add test L2CAP BR/EDR Client - TX Timestamping --- tools/l2cap-tester.c | 107 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 5 deletions(-) diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c index 461f2c27c..375ff767b 100644 --- a/tools/l2cap-tester.c +++ b/tools/l2cap-tester.c @@ -30,6 +30,9 @@ #include "src/shared/tester.h" #include "src/shared/mgmt.h" +#include "src/shared/util.h" + +#include "tester.h" struct test_data { const void *test_data; @@ -38,12 +41,15 @@ struct test_data { struct hciemu *hciemu; enum hciemu_type hciemu_type; unsigned int io_id; + unsigned int err_io_id; uint16_t handle; uint16_t scid; uint16_t dcid; int sk; int sk2; bool host_disconnected; + int step; + struct tx_tstamp_data tx_ts; }; struct l2cap_data { @@ -86,6 +92,12 @@ struct l2cap_data { bool defer; bool shut_sock_wr; + + /* Enable SO_TIMESTAMPING with these flags */ + uint32_t so_timestamping; + + /* Number of additional packets to send. */ + unsigned int repeat_send; }; static void print_debug(const char *str, void *user_data) @@ -226,6 +238,11 @@ static void test_post_teardown(const void *test_data) data->io_id = 0; } + if (data->err_io_id > 0) { + g_source_remove(data->err_io_id); + data->err_io_id = 0; + } + hciemu_unref(data->hciemu); data->hciemu = NULL; } @@ -245,6 +262,7 @@ static void test_data_free(void *test_data) break; \ user->hciemu_type = HCIEMU_TYPE_BREDR; \ user->io_id = 0; \ + user->err_io_id = 0; \ user->test_data = data; \ tester_add_full(name, data, \ test_pre_setup, setup, func, NULL, \ @@ -259,6 +277,7 @@ static void test_data_free(void *test_data) break; \ user->hciemu_type = HCIEMU_TYPE_LE; \ user->io_id = 0; \ + user->err_io_id = 0; \ user->test_data = data; \ tester_add_full(name, data, \ test_pre_setup, setup, func, NULL, \ @@ -321,6 +340,17 @@ static const struct l2cap_data client_connect_write_success_test = { .data_len = sizeof(l2_data), }; +static const struct l2cap_data client_connect_tx_timestamping_test = { + .client_psm = 0x1001, + .server_psm = 0x1001, + .write_data = l2_data, + .data_len = sizeof(l2_data), + .so_timestamping = (SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_OPT_ID | + SOF_TIMESTAMPING_TX_SOFTWARE), + .repeat_send = 2, +}; + static const struct l2cap_data client_connect_shut_wr_success_test = { .client_psm = 0x1001, .server_psm = 0x1001, @@ -1096,6 +1126,8 @@ static void bthost_received_data(const void *buf, uint16_t len, struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; + --data->step; + if (len != l2data->data_len) { tester_test_failed(); return; @@ -1103,7 +1135,7 @@ static void bthost_received_data(const void *buf, uint16_t len, if (memcmp(buf, l2data->write_data, l2data->data_len)) tester_test_failed(); - else + else if (!data->step) tester_test_passed(); } @@ -1207,6 +1239,59 @@ static bool check_mtu(struct test_data *data, int sk) return true; } +static gboolean recv_errqueue(GIOChannel *io, GIOCondition cond, + gpointer user_data) +{ + struct test_data *data = user_data; + const struct l2cap_data *l2data = data->test_data; + int sk = g_io_channel_unix_get_fd(io); + int err; + + data->step--; + + err = tx_tstamp_recv(&data->tx_ts, sk, l2data->data_len); + if (err > 0) + return TRUE; + else if (!err && !data->step) + tester_test_passed(); + else + tester_test_failed(); + + data->err_io_id = 0; + return FALSE; +} + +static void l2cap_tx_timestamping(struct test_data *data, GIOChannel *io) +{ + const struct l2cap_data *l2data = data->test_data; + int so = l2data->so_timestamping; + int sk; + int err; + unsigned int count; + + if (!(l2data->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK)) + return; + + sk = g_io_channel_unix_get_fd(io); + + tester_print("Enabling TX timestamping"); + + tx_tstamp_init(&data->tx_ts, l2data->so_timestamping); + + for (count = 0; count < l2data->repeat_send + 1; ++count) + data->step += tx_tstamp_expect(&data->tx_ts); + + err = setsockopt(sk, SOL_SOCKET, SO_TIMESTAMPING, &so, sizeof(so)); + if (err < 0) { + tester_warn("setsockopt SO_TIMESTAMPING: %s (%d)", + strerror(errno), errno); + tester_test_failed(); + return; + } + + data->err_io_id = g_io_add_watch(io, G_IO_ERR, recv_errqueue, data); +} + static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { @@ -1249,15 +1334,23 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond, } else if (l2data->write_data) { struct bthost *bthost; ssize_t ret; + unsigned int count; + + data->step = 0; bthost = hciemu_client_get_host(data->hciemu); bthost_add_cid_hook(bthost, data->handle, data->dcid, bthost_received_data, NULL); - ret = write(sk, l2data->write_data, l2data->data_len); - if (ret != l2data->data_len) { - tester_warn("Unable to write all data"); - tester_test_failed(); + l2cap_tx_timestamping(data, io); + + for (count = 0; count < l2data->repeat_send + 1; ++count) { + ret = write(sk, l2data->write_data, l2data->data_len); + if (ret != l2data->data_len) { + tester_warn("Unable to write all data"); + tester_test_failed(); + } + ++data->step; } return FALSE; @@ -2280,6 +2373,10 @@ int main(int argc, char *argv[]) &client_connect_write_success_test, setup_powered_client, test_connect); + test_l2cap_bredr("L2CAP BR/EDR Client - TX Timestamping", + &client_connect_tx_timestamping_test, + setup_powered_client, test_connect); + test_l2cap_bredr("L2CAP BR/EDR Client - Invalid PSM 1", &client_connect_nval_psm_test_1, setup_powered_client, test_connect); From patchwork Wed Apr 3 16:43:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 13616491 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A7CA1B7F4 for ; Wed, 3 Apr 2024 16:46:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=185.185.170.37 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162766; cv=pass; b=jf0f5NJL5L1o3EhzyKo148Y0EQo0nv2scV6KPrBec0Xf4Y4itFoYtfbD7PsGfjS0Iu+1SuyDgU0W173ka3OvWQTtz1MQ7NjH/Zpb+wvmWeZWHBh1EzZDJRZlMt7YZQtXxcPFBUfW5eWNXXzErMGG1z51jIPaxdwA1H4lfDsgGSA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162766; c=relaxed/simple; bh=TY2fqdnHm/1qXm5oAZeAZQByaO0VJhMajIR2AvaXsms=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WTFveZYkk3uqBlp/pk4w/4fx1LWM7FF9ofIHzzdOgpJhQfLLwaE82sbnuJsRgIpecBnTzTGFv58ATmOG1KsvA+KSxyZf11YE1Q6l0Bw0srC07XqXtyvKGcdEvNLLFc59EG2XO339CsUU45tiwVYW47r2/8KFh/ilA0o/a8pPnC0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b=YK5mZeAF; arc=pass smtp.client-ip=185.185.170.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b="YK5mZeAF" Received: from monolith.lan (unknown [193.138.7.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4V8rGy2vDxz49Q5c; Wed, 3 Apr 2024 19:46:02 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162762; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EMCfKk9RH++FCunQyWDEpkYQewc5l2UzI2FcSnTVpG4=; b=YK5mZeAFXdbTFf3ZH7oKYXUqwAjImQQoLX65JXUbMsQ2kpsBbKW4Q4FxgF1PSr1YSPXFnh yCtSihbv31LsU0SV0czyC1PpNxwuGMRlOuN/GIBtTV7EfMlIsZnysEfRPbOdR6+HykBrcE dEhKK6mxdu2kFKjV1Av4loqVhUmta2THwTUJK0ByYNVodlj6YnDdyutLzmoLXQeuKYFWe4 5aRpC3Yc+x+ZwXbAKo1v2LmIDEK3RBA8ODtPgaSxAzXWbUkT2wqdZdzvw1PutFqqIIU4Rd jjOos1JTRJKGa0UOC9VUjp0Pn00gcabCx0Jvvuxr+ILBRVZJLsxTKxbUOAHHrw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162762; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EMCfKk9RH++FCunQyWDEpkYQewc5l2UzI2FcSnTVpG4=; b=gbCtSUTT1pfC+1KappVuMqghQsw6TXqI+EcR2Ye0czGcFeafz0tsniTdNm7vb38gCY0NiL PYSn/aBqyksY11PTQ502Z8ohhqIyomtvJVCq+/D5O2A3ER23+nz6aRImc1JmHgaFdSdtb8 M70hMh1rXMG8PpPOFllJYHM5SYbuGVUg/N1WLSYmHyohs2Ugk8onlYGzVjWeAlnXhiF+Z5 7WeAELweFPEzA/RgP/P3A6vZkcLpGvK365N1Us/IsiLCmxlWNH6JZl8M1z1WvO9TvhztPY ti1zJYD3Ro7EemuhoKgBrO0hn/9FG/RknLmwHYxgbWVqQcNsooSmcNkkOz+dCw== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1712162762; a=rsa-sha256; cv=none; b=OHU9zhDkAMdrTaOY8XtwuNuv47v8T0WTfRUn3xOPuDI3TVI2FpxUJ5dD1yrcgkfJjLmzKI +2zxgyEAa85xsbUwjP8uxmaAzmFpDYCmVWi610aWDAzvhLMBtl7OAVR0XngwQqnBXB8zeG Svqe312LnlFFDCC9si28RGRpCStWhueN1sTLLJm3VwuzcWCVWzrCJLnsJOO3hai2x41XS7 qyS3b/WYuFoEECrcDAxwKmeXI7ThrJl6TY6Bo6Eo46sOcEQJyooSrheTXKv4hktI8fXHeM nq9rhSsLUHe01xLKmpwZX8XkXW+Da7sV2Wgw/5Kurx2ydaA1sBP/7ryWRNLsow== From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ v5 4/7] btdev: set nonzero SCO mtu & max pkt Date: Wed, 3 Apr 2024 19:43:23 +0300 Message-ID: <6ade1b15ba0eb97a8cf8a06ce8830ed031e8e271.1712161649.git.pav@iki.fi> X-Mailer: git-send-email 2.44.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Set nonzero max pkt count, so that kernel can transmit data. The request & accept/reject flow is not emulated yet. --- emulator/btdev.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/emulator/btdev.c b/emulator/btdev.c index 0ad6b2793..a63136fad 100644 --- a/emulator/btdev.c +++ b/emulator/btdev.c @@ -148,6 +148,8 @@ struct btdev { uint8_t feat_page_2[8]; uint16_t acl_mtu; uint16_t acl_max_pkt; + uint16_t sco_mtu; + uint16_t sco_max_pkt; uint16_t iso_mtu; uint16_t iso_max_pkt; uint8_t country_code; @@ -653,9 +655,9 @@ static int cmd_read_buffer_size(struct btdev *dev, const void *data, rsp.status = BT_HCI_ERR_SUCCESS; rsp.acl_mtu = cpu_to_le16(dev->acl_mtu); - rsp.sco_mtu = 0; + rsp.sco_mtu = cpu_to_le16(dev->sco_mtu); rsp.acl_max_pkt = cpu_to_le16(dev->acl_max_pkt); - rsp.sco_max_pkt = cpu_to_le16(0); + rsp.sco_max_pkt = cpu_to_le16(dev->sco_max_pkt); cmd_complete(dev, BT_HCI_CMD_READ_BUFFER_SIZE, &rsp, sizeof(rsp)); @@ -2764,6 +2766,8 @@ static int cmd_enhanced_setup_sync_conn_complete(struct btdev *dev, goto done; } + /* TODO: HCI_Connection_Request connection flow */ + cc.status = BT_HCI_ERR_SUCCESS; memcpy(cc.bdaddr, conn->link->dev->bdaddr, 6); @@ -7173,6 +7177,9 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id) btdev->acl_mtu = 192; btdev->acl_max_pkt = 1; + btdev->sco_mtu = 72; + btdev->sco_max_pkt = 1; + btdev->iso_mtu = 251; btdev->iso_max_pkt = 1; btdev->big_handle = 0xff; From patchwork Wed Apr 3 16:43:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 13616495 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C572152162 for ; Wed, 3 Apr 2024 16:46:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=185.185.170.37 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162769; cv=pass; b=Mpr81AZU49QQV6zRF6LVfX02y6FM5+JTiEUnzLV1vmd4jAzMuVT0Gg+gbo2eKm7d2KepN/GdVOaI2QcJKU7VteH4yCd2VTRiR/dy4uKY4X3vkiAMRq70ORX76cHudNWGHIoSmrvPeeizBhtfRCt2ZA5TeH04BHvfJOJPzk8d8jo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162769; c=relaxed/simple; bh=u6xsCkRPNfUcWaIJHgTg3Mwi6O1l001DBY5GqLvIrZU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i16zVt5lilHf1BCKZjBBfeTOEoXcHakLGF2xcJQYYFjcGnZl3laJVCfbDDvTknyI+NY5tWWAmJgQim6wYazcg1tJt7oli3eJfks4jmNDmcNvD7hDW3457Gt8bOorGW6cXT0ewR0gPVa5XN7nQ0H5ZX+oUqNzs95vED4ArfvBNj0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b=SGVYHsHX; arc=pass smtp.client-ip=185.185.170.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b="SGVYHsHX" Received: from monolith.lan (unknown [193.138.7.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4V8rGy4dnmz49Q6X; Wed, 3 Apr 2024 19:46:02 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162762; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HFqLwmQ/R+8dGLxGdjyFoT4oz92Vy0HCxdyYD/UED34=; b=SGVYHsHXWwVYE83/BzuMqHR3AqXRcO64QGNGtpt3rUc5lfjMFLhBOyvrTX2CgdAWp6i6Br SxASjDb7R0kIZ2Ood9trj23rvmMXTNYIMUkp8jqtzxoUVFPA7F3F3LSUdkxALrXW9PKWWl IGK9ibDD2/M1s8uet4a7fqAbiIdoOmBKYEvQIxx67T/caVbfK4MTnjD7lCmQEeCdsEdwVc FeTkmHlulovNx9gDM+w+K+2QdrI3wlfjK/tU/q0YUTrsxJGeApr7GHLNRJM77O0SDzBqZ1 W63EdQMkTIhNdK2ai3JFEkGz8MMrrmr94kKmG+6gAyT6YgG3kiioJFwMih5kng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162762; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HFqLwmQ/R+8dGLxGdjyFoT4oz92Vy0HCxdyYD/UED34=; b=I/w+o0Et6bGBaTkMmYl4Er6ZiNwxJsZzYWXys9IcaWdxCjapp75Bc4S1zEnimKuyOLoCGy sdygvYAb0VVDurL+akeE3qhXXF9CBR/78o0rNS7SE75bi10PuKLdyiblrJwYgdOyHky3b3 veGrRU3sIfWjqdclVwK5VoHKPq3B1NLwTYa+ItXUw+C9sULz/exGqNiyYElBj5u80NXP1F 0ypVAkMY2Kd3LbDTtvA/nD3yRjsYLBUTKQJaLR+5NE8TwWq0u2Kiao0mFQbS6zRFcoKj12 RGsyYAyAApuTPgJgWe56V6wtW7L87TpAiAl/gxjuIIHL9W7zOAplaD3i3O+4tg== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1712162762; a=rsa-sha256; cv=none; b=pxg10K9njXQk7NLjhsLBXmeZCPfVYtXL0qGtp/qemN/biM1ukCHs9fdPkUP+VSl8hJ7XyX IOdcLSOoP7rYcRyWqZJFJNPq71nJx/yksojltFyG4YouAJ3rajgrkqXrk8jfTRq4X4Yeb1 wiW4Gc7+xkv5c6fiiUCJR9L9A18PKfcu4qIQSxw22FM+V88KcX/uUvDAnqCKgjqSsnuDml dPl1/SsXJWfCmkVCBF6Ed1AR31Gp2Sb/Vo6r/hz87JtmfJ24zB6Ss7SHKeWVE4gclMS0/M wF2pJM5mho8KfXJdIT1sVrM6YLCwx+dKV16RLdfGDTg1s575K4N2e/Qbt+HFWw== From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ v5 5/7] sco-tester: add TX timestamping test Date: Wed, 3 Apr 2024 19:43:24 +0300 Message-ID: <161ee7ceb7f314ce4be9bbcbbb2898d8baea956e.1712161649.git.pav@iki.fi> X-Mailer: git-send-email 2.44.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add test: SCO CVSD Send - TX Timestamping --- tools/sco-tester.c | 96 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/tools/sco-tester.c b/tools/sco-tester.c index ecc65e092..d146a6937 100644 --- a/tools/sco-tester.c +++ b/tools/sco-tester.c @@ -31,6 +31,8 @@ #include "src/shared/mgmt.h" #include "src/shared/util.h" +#include "tester.h" + struct test_data { const void *test_data; struct mgmt *mgmt; @@ -38,15 +40,24 @@ struct test_data { struct hciemu *hciemu; enum hciemu_type hciemu_type; unsigned int io_id; + unsigned int err_io_id; int sk; bool disable_esco; bool enable_codecs; + int step; + struct tx_tstamp_data tx_ts; }; struct sco_client_data { int expect_err; const uint8_t *send_data; uint16_t data_len; + + /* Enable SO_TIMESTAMPING with these flags */ + uint32_t so_timestamping; + + /* Number of additional packets to send. */ + unsigned int repeat_send; }; static void print_debug(const char *str, void *user_data) @@ -227,8 +238,10 @@ static void test_data_free(void *test_data) break; \ user->hciemu_type = HCIEMU_TYPE_BREDRLE; \ user->io_id = 0; \ + user->err_io_id = 0; \ user->sk = -1; \ user->test_data = data; \ + user->step = 0; \ user->disable_esco = _disable_esco; \ user->enable_codecs = _enable_codecs; \ tester_add_full(name, data, \ @@ -265,6 +278,16 @@ static const struct sco_client_data connect_send_success = { .send_data = data }; +static const struct sco_client_data connect_send_tx_timestamping = { + .expect_err = 0, + .data_len = sizeof(data), + .send_data = data, + .so_timestamping = (SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_OPT_ID | + SOF_TIMESTAMPING_TX_SOFTWARE), + .repeat_send = 2, +}; + static void client_connectable_complete(uint16_t opcode, uint8_t status, const void *param, uint8_t len, void *user_data) @@ -595,6 +618,59 @@ static int connect_sco_sock(struct test_data *data, int sk) return 0; } +static gboolean recv_errqueue(GIOChannel *io, GIOCondition cond, + gpointer user_data) +{ + struct test_data *data = user_data; + const struct sco_client_data *scodata = data->test_data; + int sk = g_io_channel_unix_get_fd(io); + int err; + + data->step--; + + err = tx_tstamp_recv(&data->tx_ts, sk, scodata->data_len); + if (err > 0) + return TRUE; + else if (!err && !data->step) + tester_test_passed(); + else + tester_test_failed(); + + data->err_io_id = 0; + return FALSE; +} + +static void sco_tx_timestamping(struct test_data *data, GIOChannel *io) +{ + const struct sco_client_data *scodata = data->test_data; + int so = scodata->so_timestamping; + int sk; + int err; + unsigned int count; + + if (!(scodata->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK)) + return; + + sk = g_io_channel_unix_get_fd(io); + + tester_print("Enabling TX timestamping"); + + tx_tstamp_init(&data->tx_ts, scodata->so_timestamping); + + for (count = 0; count < scodata->repeat_send + 1; ++count) + data->step += tx_tstamp_expect(&data->tx_ts); + + err = setsockopt(sk, SOL_SOCKET, SO_TIMESTAMPING, &so, sizeof(so)); + if (err < 0) { + tester_warn("setsockopt SO_TIMESTAMPING: %s (%d)", + strerror(errno), errno); + tester_test_failed(); + return; + } + + data->err_io_id = g_io_add_watch(io, G_IO_ERR, recv_errqueue, data); +} + static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { @@ -619,10 +695,20 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond, if (scodata->send_data) { ssize_t ret; + unsigned int count; + + data->step = 0; - tester_print("Writing %u bytes of data", scodata->data_len); + sco_tx_timestamping(data, io); - ret = write(sk, scodata->send_data, scodata->data_len); + tester_print("Writing %u*%u bytes of data", + scodata->repeat_send + 1, scodata->data_len); + + for (count = 0; count < scodata->repeat_send + 1; ++count) { + ret = write(sk, scodata->send_data, scodata->data_len); + if (scodata->data_len != ret) + break; + } if (scodata->data_len != ret) { tester_warn("Failed to write %u bytes: %zu %s (%d)", scodata->data_len, ret, strerror(errno), @@ -633,7 +719,7 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond, if (-err != scodata->expect_err) tester_test_failed(); - else + else if (!data->step) tester_test_passed(); return FALSE; @@ -869,6 +955,10 @@ int main(int argc, char *argv[]) test_sco("SCO CVSD Send - Success", &connect_send_success, setup_powered, test_connect); + test_sco("SCO CVSD Send - TX Timestamping", + &connect_send_tx_timestamping, + setup_powered, test_connect); + test_offload_sco("Basic SCO Get Socket Option - Offload - Success", NULL, setup_powered, test_codecs_getsockopt); From patchwork Wed Apr 3 16:43:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 13616494 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C5B4152163 for ; Wed, 3 Apr 2024 16:46:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=185.185.170.37 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162769; cv=pass; b=QHCdurZuYI+4tLDhxXBSB1AznmHgHmmO+D7RyyUzJ4EUoBjEETIlhzTN15o0JFrWsXjrXYlP1N+51QbJjXsjL4es70vF37PoMUrNA8AoN/Go1ryGkXk4fqycXzqxeqznjC/V58651cha+1C2XD1Pk2b8S905Id4IeCL7iXbGzYI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162769; c=relaxed/simple; bh=R1O/ht1ocoXEyVTEdAgk2S2D/NajFcKMc1FubLogsP4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OH9uQ9IkIXkFTBCHC2pKTw2nPU4SbAsa9b199Lmt8vhvvqG5LpsDrjggiHFZWB49LOajnDEMeejOn1Z/5hvRo2qzTd6LK4e/s6BHoPt0UuVRD/jYJ5d7ZBKHvZ2xzcivup3/I039qMXYZzRi4Mxc8s+72ZL5dricIsBizxn+DGg= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b=aYjy+qmB; arc=pass smtp.client-ip=185.185.170.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b="aYjy+qmB" Received: from monolith.lan (unknown [193.138.7.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4V8rGy6RSLz49Q3H; Wed, 3 Apr 2024 19:46:02 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162763; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5JzT69tOdpsUYsIOroGvf9htTZN0rV5ZdKs7wA0E/5Y=; b=aYjy+qmBmE1XnLkEIkkicucPxa971RvSH1J7c5xngQRPuOoh0+4rCqP76cnzOt22w0y/yx /KUAUf1Jr0veoFVAhcNyJCtrGIi3Efdb473orMNzmDhgNT9NKVM03YcAPMehGx+9HWrr/l MvPo3mfiMNrSOr5ZxCvr1DHoNrtET83KZvqn9qecmW9qWdLw+5OsPaUgCohZ9yfxm2aBp9 pJXtrXOEgJ/QMbFNPYwYrwLEOsCczHJ4zheZq2tRZB67I3hfCL/LXIXQC6VMkjf35ejwQ2 h+jYs24FWN42wYs9q9l03HnjWGpeNJbu/ORHp+r7WY+30lxTYy+qij/qB3Ad3g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162763; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5JzT69tOdpsUYsIOroGvf9htTZN0rV5ZdKs7wA0E/5Y=; b=Iz3z2O013T1eMw72BpO2xzt08pTtiExcipWUBDa5R+XXi6X+UJlLgjOR80+1NUJ3sEZ3QV p02jqhj/h7+rTvm4H+KlwRqxYI8HzaBVYGYKIuiZspaQTNpG52sfrLH2Szi66R9x1pkryK ADk744guop/xCLmgn1E3nBjV0yg7ydnDZjZIdHWo2FWqKRUygYoQ7MZLhQiYW5BMjvd/81 5bSI6HDf4rderhJQbn9OvW+tgYJsVhD0cTdinkKddgsi8s1UHJdEgW2P24PY+UwDkEvSxY JE5EV7Un8+CPt9T5oKfb6uMHxzGiRNHh90K1qgDsJ2UT+nDMtfuTpkmevy7J/g== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1712162763; a=rsa-sha256; cv=none; b=n7tCAlj5qGJAKbpM8B3PYo4H3Cwcg3wVNDG7IYgKVJzc1NETAj9HuNYxLWHcpdKblwLS0J dLaanMBAjV4RIg02tFAeecJbui2oHQV8tp24S4Mtzu9xN3GbexGACc+T5ueQ2xklB6fWIF 7cp4y4EzUzKFTlOW/TX6XpSnF/QEtS6YEXYBBA1X+OPlkkH3DY9JVge6Q5MYrtfeterXEk wgiC4IV9lwPvu1lVkDvcJEh0nGxXmV3lPZVFr0IOCZFDsRzQ0RY4caOH8nXr9K2B/6GKq2 OXh8r9lbYnvkX0/Kymdtp+xbsBWxwENnllbhKhEBz6iIF6SOEMKTIIK1ic/Lmw== From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ v5 6/7] bthost: handle client L2CAP conn in LE credit based mode Date: Wed, 3 Apr 2024 19:43:25 +0300 Message-ID: <3c8ff0aa2e7f0b1d72c9c221329be12a2412d1fb.1712161649.git.pav@iki.fi> X-Mailer: git-send-email 2.44.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Allow bthost hooks to receive data from L2CAP LE credit based connections. Handle LE credit header when receiving, and reassemble received SDU. Handle L2CAP LE credit header also in bthost_send_cid. --- emulator/bthost.c | 205 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 180 insertions(+), 25 deletions(-) diff --git a/emulator/bthost.c b/emulator/bthost.c index 8c40fce90..8616bf715 100644 --- a/emulator/bthost.c +++ b/emulator/bthost.c @@ -162,11 +162,21 @@ struct btconn { void *recv_data; }; +enum l2cap_mode { + L2CAP_MODE_OTHER, + L2CAP_MODE_LE_CRED, + L2CAP_MODE_LE_ENH_CRED, +}; + struct l2conn { + struct l2conn *next; uint16_t scid; uint16_t dcid; uint16_t psm; - struct l2conn *next; + enum l2cap_mode mode; + uint16_t data_len; + uint16_t recv_len; + void *recv_data; }; struct rcconn { @@ -275,6 +285,7 @@ struct bthost *bthost_create(void) static void l2conn_free(struct l2conn *conn) { + free(conn->recv_data); free(conn); } @@ -360,6 +371,7 @@ static struct l2conn *bthost_add_l2cap_conn(struct bthost *bthost, l2conn->psm = psm; l2conn->scid = scid; l2conn->dcid = dcid; + l2conn->mode = L2CAP_MODE_OTHER; l2conn->next = conn->l2conns; conn->l2conns = l2conn; @@ -415,6 +427,19 @@ static struct l2conn *btconn_find_l2cap_conn_by_scid(struct btconn *conn, return NULL; } +static struct l2conn *btconn_find_l2cap_conn_by_dcid(struct btconn *conn, + uint16_t dcid) +{ + struct l2conn *l2conn; + + for (l2conn = conn->l2conns; l2conn != NULL; l2conn = l2conn->next) { + if (l2conn->dcid == dcid) + return l2conn; + } + + return NULL; +} + static struct l2cap_conn_cb_data *bthost_find_l2cap_cb_by_psm( struct bthost *bthost, uint16_t psm) { @@ -609,14 +634,24 @@ static void send_iov(struct bthost *bthost, uint16_t handle, uint16_t cid, } static void send_acl(struct bthost *bthost, uint16_t handle, uint16_t cid, - const void *data, uint16_t len) + bool sdu_hdr, const void *data, uint16_t len) { - struct iovec iov; + struct iovec iov[2]; + uint16_t sdu; + int num = 0; + + if (sdu_hdr) { + sdu = cpu_to_le16(len); + iov[num].iov_base = &sdu; + iov[num].iov_len = sizeof(sdu); + num++; + } - iov.iov_base = (void *) data; - iov.iov_len = len; + iov[num].iov_base = (void *) data; + iov[num].iov_len = len; + num++; - send_iov(bthost, handle, cid, &iov, 1); + send_iov(bthost, handle, cid, iov, num); } static uint8_t l2cap_sig_send(struct bthost *bthost, struct btconn *conn, @@ -711,12 +746,19 @@ void bthost_send_cid(struct bthost *bthost, uint16_t handle, uint16_t cid, const void *data, uint16_t len) { struct btconn *conn; + struct l2conn *l2conn; + bool sdu_hdr = false; conn = bthost_find_conn(bthost, handle); if (!conn) return; - send_acl(bthost, handle, cid, data, len); + l2conn = btconn_find_l2cap_conn_by_dcid(conn, cid); + if (l2conn && (l2conn->mode == L2CAP_MODE_LE_CRED || + l2conn->mode == L2CAP_MODE_LE_ENH_CRED)) + sdu_hdr = true; + + send_acl(bthost, handle, cid, sdu_hdr, data, len); } void bthost_send_cid_v(struct bthost *bthost, uint16_t handle, uint16_t cid, @@ -1779,7 +1821,7 @@ static void rfcomm_sabm_send(struct bthost *bthost, struct btconn *conn, cmd.length = RFCOMM_LEN8(0); cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd); - send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd)); + send_acl(bthost, conn->handle, l2conn->dcid, false, &cmd, sizeof(cmd)); } static bool l2cap_conn_rsp(struct bthost *bthost, struct btconn *conn, @@ -2110,6 +2152,7 @@ static bool l2cap_le_conn_req(struct bthost *bthost, struct btconn *conn, uint8_t ident, const void *data, uint16_t len) { const struct bt_l2cap_pdu_le_conn_req *req = data; + struct l2cap_conn_cb_data *cb_data; struct bt_l2cap_pdu_le_conn_rsp rsp; uint16_t psm; @@ -2124,7 +2167,8 @@ static bool l2cap_le_conn_req(struct bthost *bthost, struct btconn *conn, rsp.mps = 23; rsp.credits = 1; - if (bthost_find_l2cap_cb_by_psm(bthost, psm)) + cb_data = bthost_find_l2cap_cb_by_psm(bthost, psm); + if (cb_data) rsp.dcid = cpu_to_le16(conn->next_cid++); else rsp.result = cpu_to_le16(0x0002); /* PSM Not Supported */ @@ -2132,6 +2176,20 @@ static bool l2cap_le_conn_req(struct bthost *bthost, struct btconn *conn, l2cap_sig_send(bthost, conn, BT_L2CAP_PDU_LE_CONN_RSP, ident, &rsp, sizeof(rsp)); + if (!rsp.result) { + struct l2conn *l2conn; + + l2conn = bthost_add_l2cap_conn(bthost, conn, + le16_to_cpu(rsp.dcid), + le16_to_cpu(req->scid), + le16_to_cpu(psm)); + l2conn->mode = L2CAP_MODE_LE_CRED; + + if (cb_data && l2conn->psm == cb_data->psm && cb_data->func) + cb_data->func(conn->handle, l2conn->dcid, + cb_data->user_data); + } + return true; } @@ -2139,11 +2197,14 @@ static bool l2cap_le_conn_rsp(struct bthost *bthost, struct btconn *conn, uint8_t ident, const void *data, uint16_t len) { const struct bt_l2cap_pdu_le_conn_rsp *rsp = data; + struct l2conn *l2conn; if (len < sizeof(*rsp)) return false; /* TODO add L2CAP connection before with proper PSM */ - bthost_add_l2cap_conn(bthost, conn, 0, le16_to_cpu(rsp->dcid), 0); + l2conn = bthost_add_l2cap_conn(bthost, conn, 0, + le16_to_cpu(rsp->dcid), 0); + l2conn->mode = L2CAP_MODE_LE_CRED; return true; } @@ -2196,16 +2257,19 @@ static bool l2cap_ecred_conn_rsp(struct bthost *bthost, struct btconn *conn, uint16_t scid[5]; } __attribute__ ((packed)) *rsp = data; int num_scid, i; + struct l2conn *l2conn; if (len < sizeof(*rsp)) return false; num_scid = len / sizeof(*rsp->scid); - for (i = 0; i < num_scid; i++) + for (i = 0; i < num_scid; i++) { /* TODO add L2CAP connection before with proper PSM */ - bthost_add_l2cap_conn(bthost, conn, 0, + l2conn = bthost_add_l2cap_conn(bthost, conn, 0, le16_to_cpu(rsp->scid[i]), 0); + l2conn->mode = L2CAP_MODE_LE_ENH_CRED; + } return true; @@ -2333,7 +2397,7 @@ static void rfcomm_ua_send(struct bthost *bthost, struct btconn *conn, cmd.length = RFCOMM_LEN8(0); cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd); - send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd)); + send_acl(bthost, conn->handle, l2conn->dcid, false, &cmd, sizeof(cmd)); } static void rfcomm_dm_send(struct bthost *bthost, struct btconn *conn, @@ -2347,7 +2411,7 @@ static void rfcomm_dm_send(struct bthost *bthost, struct btconn *conn, cmd.length = RFCOMM_LEN8(0); cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd); - send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd)); + send_acl(bthost, conn->handle, l2conn->dcid, false, &cmd, sizeof(cmd)); } static void rfcomm_sabm_recv(struct bthost *bthost, struct btconn *conn, @@ -2636,12 +2700,97 @@ static void process_rfcomm(struct bthost *bthost, struct btconn *conn, } } +static void append_l2conn_data(struct bthost *bthost, struct l2conn *conn, + const void *data, uint16_t len) +{ + if (!conn->recv_data) { + bthost_debug(bthost, "Unexpected L2CAP SDU data: sCID 0x%4.4x ", + conn->scid); + return; + } + + if (conn->recv_len + len > conn->data_len) { + bthost_debug(bthost, "Unexpected L2CAP SDU data: sCID 0x%4.4x ", + conn->scid); + return; + } + + memcpy(conn->recv_data + conn->recv_len, data, len); + conn->recv_len += len; + + bthost_debug(bthost, "L2CAP SDU data: %u/%u bytes", conn->recv_len, + conn->data_len); +} + +static void free_l2conn_data(struct l2conn *conn) +{ + free(conn->recv_data); + conn->recv_data = NULL; + conn->recv_len = 0; + conn->data_len = 0; +} + +static void new_l2conn_data(struct bthost *bthost, struct l2conn *conn, + uint16_t len) +{ + free(conn->recv_data); + conn->recv_data = malloc(len); + conn->recv_len = 0; + conn->data_len = len; +} + +static bool process_l2cap_conn(struct bthost *bthost, struct btconn *conn, + struct l2conn *l2conn, struct iovec *data) +{ + struct bt_l2cap_pdu_le_flowctl_creds creds; + uint16_t sdu; + + if (!l2conn) + return true; + + switch (l2conn->mode) { + case L2CAP_MODE_LE_CRED: + case L2CAP_MODE_LE_ENH_CRED: + break; + case L2CAP_MODE_OTHER: + return true; + } + + /* Credit-based flow control */ + + creds.cid = cpu_to_le16(l2conn->scid); + creds.credits = cpu_to_le16(1); + l2cap_sig_send(bthost, conn, BT_L2CAP_PDU_LE_FLOWCTL_CREDS, 0, + &creds, sizeof(creds)); + + if (!l2conn->data_len) { + if (!util_iov_pull_le16(data, &sdu)) { + free_l2conn_data(l2conn); + bthost_debug(bthost, "L2CAP invalid SDU"); + return false; + } + new_l2conn_data(bthost, l2conn, sdu); + } + + append_l2conn_data(bthost, l2conn, data->iov_base, data->iov_len); + + if (l2conn->recv_len < l2conn->data_len) + return false; /* SDU incomplete */ + + l2conn->data_len = 0; + data->iov_base = l2conn->recv_data; + data->iov_len = l2conn->recv_len; + + return true; +} + static void process_l2cap(struct bthost *bthost, struct btconn *conn, - const void *data, uint16_t len) + const void *buf, uint16_t len) { - const struct bt_l2cap_hdr *l2_hdr = data; + const struct bt_l2cap_hdr *l2_hdr = buf; struct cid_hook *hook; struct l2conn *l2conn; + struct iovec data; uint16_t cid, l2_len; l2_len = le16_to_cpu(l2_hdr->len); @@ -2654,31 +2803,37 @@ static void process_l2cap(struct bthost *bthost, struct btconn *conn, bthost_debug(bthost, "L2CAP data: %u bytes", l2_len); cid = le16_to_cpu(l2_hdr->cid); + l2conn = btconn_find_l2cap_conn_by_scid(conn, cid); + + data.iov_base = (void *)l2_hdr->data; + data.iov_len = l2_len; + + if (!process_l2cap_conn(bthost, conn, l2conn, &data)) + return; hook = find_cid_hook(conn, cid); if (hook) { - hook->func(l2_hdr->data, l2_len, hook->user_data); + hook->func(data.iov_base, data.iov_len, hook->user_data); return; } switch (cid) { case 0x0001: - l2cap_sig(bthost, conn, l2_hdr->data, l2_len); + l2cap_sig(bthost, conn, data.iov_base, data.iov_len); break; case 0x0005: - l2cap_le_sig(bthost, conn, l2_hdr->data, l2_len); + l2cap_le_sig(bthost, conn, data.iov_base, data.iov_len); break; case 0x0006: - smp_data(conn->smp_data, l2_hdr->data, l2_len); + smp_data(conn->smp_data, data.iov_base, data.iov_len); break; case 0x0007: - smp_bredr_data(conn->smp_data, l2_hdr->data, l2_len); + smp_bredr_data(conn->smp_data, data.iov_base, data.iov_len); break; default: - l2conn = btconn_find_l2cap_conn_by_scid(conn, cid); if (l2conn && l2conn->psm == 0x0003) - process_rfcomm(bthost, conn, l2conn, l2_hdr->data, - l2_len); + process_rfcomm(bthost, conn, l2conn, data.iov_base, + data.iov_len); else bthost_debug(bthost, "Packet for unknown CID 0x%04x (%u)", @@ -3494,7 +3649,7 @@ void bthost_send_rfcomm_data(struct bthost *bthost, uint16_t handle, } uih_frame[uih_len - 1] = rfcomm_fcs((void *)hdr); - send_acl(bthost, handle, rcconn->scid, uih_frame, uih_len); + send_acl(bthost, handle, rcconn->scid, false, uih_frame, uih_len); free(uih_frame); } From patchwork Wed Apr 3 16:43:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 13616496 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4BC43152189 for ; Wed, 3 Apr 2024 16:46:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=185.185.170.37 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162770; cv=pass; b=ks4HkcqKE8FmGQFxeb51QUxF3igLJp31owGT5REIAj3o27ZIPMxdUltshriaT+lurHVtHCORRomY30vxlCu3wkyfjXJ9ms7W3vXll00iX0H/KACR5FEkv8ARTJBUvrioho1OdoaRIAGeNEzWf+lRrjyVcZ60iyy4Lw9ITRZTW0k= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712162770; c=relaxed/simple; bh=CrXNap1pfijvwwb1PYCA8Mn9xNcPGXye6UaGzidWKcs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kQOp5U49uSNwmYpnUUz9gxIU3ZfvyVj9g5pYVr7+XGAJLaFyasCWfj1iqU9tn/nwEjQ6LAyWKx4DUAv42yjkxmPoqCeO0Fo4R0D+eypncM6MC23+8wP9pVSEvivDi37ZVrazrnYLltanXjCDZ3JIy+VNJIQ1aZJPUrmUiLGFssc= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b=NfOvfNxW; arc=pass smtp.client-ip=185.185.170.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=iki.fi header.i=@iki.fi header.b="NfOvfNxW" Received: from monolith.lan (unknown [193.138.7.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4V8rGz18Xrz49Q4P; Wed, 3 Apr 2024 19:46:03 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162763; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dptXVj4bIU0PiLtrHZKTYLF2BmJUfMRxzrJx8J2qiDU=; b=NfOvfNxWW+UeSHcNGvGPHQ9a84csSLRqAg0xPogAAPIYjL/ANlNq0nHp9Riur1scLYSJzO 2pVT+UsLVg6gMwBL3n3i/CWVtZYzCu0oZnpy9tpv+GGX5CCZK1E9GZIqi7yzVrvfhBV3IX Ecq4jNEV4M0PrUWp0lkK8A9c8q1WqGEdQVBJ7HLxvJdxuDWNvgKKAvDkKCk5DMeX3nyjm6 IFWvULnfzgLTpvJ6mcrwnX2/60/fXNLkW4Eefg/wvC/gSEV8XrBFlk1A0slQUGL4WfhkPh +O5Kr+QZfokU2k2uMF4yVEpE/7uWW3hfkmnTrbASKpi3df14PhZFOxouB0hrtg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1712162763; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dptXVj4bIU0PiLtrHZKTYLF2BmJUfMRxzrJx8J2qiDU=; b=DyJtVNcoMpRXIfBmMHoZdLm8NN45TZBg19cPDLruPQoy0yL4z2+KDC4iZvLqZd4OmyBa/R Pgm0OZ+AcTy2PV4NR8zdog11/QLU0Osg9bvzV1kpqaLFJJBtVNssybqvJ/XwEYQOjFb+RH Yfqz1/1sVDtX6R/ulBPcNn3vJezRziIIw18IH41KFrB4Cup8wXtgDBA4tGDOgmvCYJtxFi uAw4dNpwKd0GQWcZNQp9XFxhHos0kvczkEvpO4IwdGvXvZrVkSefkISfVD9Yeyd4IFNFRv J/66SKQmsNd++A/CT7wDlHemm0ZDTnnN5tGOSP1hilFM6l5ClvY3Q/hFTY4LaQ== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1712162763; a=rsa-sha256; cv=none; b=KHQYihqDM6ohpPMDMHHh+IZrPK754K8I/jXVEhaPnN8n6gHXvEdyv3DLW0l3LlAalIsKGp 9hBCXhkzy5RYEjBg0IlKLc6IkCnw22FZc4Zuu4msvGyAa7DNjdTAhcLz5+8k7yL53NEcUg ISiotm0neC3eUeWWC9zXQITLTrDRoEMGeKwwi3NqQ2lZFiZ9f23MOgPhzvkSVht3L/V0ut FQl5XTih6uxOlrejv2UiPmm/U97iozis/+DCFtKp48I3Pv5vWwkGqBTmjfqR2sQpTzD4Jl detR6yCseeLrRDVY5NIgsZcEKn3XuxEiOakyCFiffCAcYBWaTwhBAajhcNi/6Q== From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ v5 7/7] l2cap-tester: add tests for LE Client read/write/tx-timestamping Date: Wed, 3 Apr 2024 19:43:26 +0300 Message-ID: <5b8e511bfd245e3dc46a6ddbd850e0a6fc716d53.1712161649.git.pav@iki.fi> X-Mailer: git-send-email 2.44.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add tests: L2CAP LE Client - Read Success L2CAP LE Client - Write Success L2CAP LE Client - TX Timestamping --- tools/l2cap-tester.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c index 375ff767b..02d1571d2 100644 --- a/tools/l2cap-tester.c +++ b/tools/l2cap-tester.c @@ -487,6 +487,30 @@ static const struct l2cap_data le_client_connect_timeout_test_1 = { .timeout = 1, }; +static const struct l2cap_data le_client_connect_read_success_test = { + .client_psm = 0x0080, + .server_psm = 0x0080, + .read_data = l2_data, + .data_len = sizeof(l2_data), +}; + +static const struct l2cap_data le_client_connect_write_success_test = { + .client_psm = 0x0080, + .server_psm = 0x0080, + .write_data = l2_data, + .data_len = sizeof(l2_data), +}; + +static const struct l2cap_data le_client_connect_tx_timestamping_test = { + .client_psm = 0x0080, + .server_psm = 0x0080, + .write_data = l2_data, + .data_len = sizeof(l2_data), + .so_timestamping = (SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_OPT_ID | + SOF_TIMESTAMPING_TX_SOFTWARE), +}; + static const struct l2cap_data le_client_connect_adv_success_test_1 = { .client_psm = 0x0080, .server_psm = 0x0080, @@ -1082,6 +1106,8 @@ static gboolean client_received_data(GIOChannel *io, GIOCondition cond, char buf[1024]; int sk; + tester_debug("Client received data"); + sk = g_io_channel_unix_get_fd(io); if (read(sk, buf, l2data->data_len) != l2data->data_len) { tester_warn("Unable to read %u bytes", l2data->data_len); @@ -1126,6 +1152,8 @@ static void bthost_received_data(const void *buf, uint16_t len, struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; + tester_debug("BTHost received data: %u bytes", len); + --data->step; if (len != l2data->data_len) { @@ -1314,7 +1342,7 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond, goto failed; } - tester_print("Successfully connected"); + tester_print("Successfully connected to CID 0x%04x", data->dcid); if (!check_mtu(data, sk)) { tester_test_failed(); @@ -1506,6 +1534,8 @@ static void client_l2cap_connect_cb(uint16_t handle, uint16_t cid, { struct test_data *data = user_data; + tester_debug("Client connect CID 0x%04x handle 0x%04x", cid, handle); + data->dcid = cid; data->handle = handle; } @@ -2431,6 +2461,15 @@ int main(int argc, char *argv[]) test_l2cap_le("L2CAP LE Client - Timeout", &le_client_connect_timeout_test_1, setup_powered_client, test_connect_timeout); + test_l2cap_le("L2CAP LE Client - Read Success", + &le_client_connect_read_success_test, + setup_powered_client, test_connect); + test_l2cap_le("L2CAP LE Client - Write Success", + &le_client_connect_write_success_test, + setup_powered_client, test_connect); + test_l2cap_le("L2CAP LE Client - TX Timestamping", + &le_client_connect_tx_timestamping_test, + setup_powered_client, test_connect); test_l2cap_le("L2CAP LE Client, Direct Advertising - Success", &le_client_connect_adv_success_test_1, setup_powered_client, test_connect);