From 21d1bc79121511cab451d2b63b45466d15631b5e Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 1 Aug 2024 14:25:51 +0200 Subject: [PATCH 1/5] Bluetooth: Host: Fix `bt_l2cap_chan_ops.recv` `-EINPROGRESS` Fix discrepancy in reference management between calls to `bt_l2cap_chan_ops.recv` when the application returns `-EINPROGRESS`. There are two call sites, `l2cap_chan_le_recv_sdu` and `l2cap_chan_le_recv`, that were inconsistent. `l2cap_chan_le_recv_sdu` moves the reference, and this patch updates `l2cap_chan_le_recv` to do the same. This behavior is also now documented. This bug has existed since the introduction of this feature in 3151d265726fb528d31d8e1ee8b35004e901cfc4. Signed-off-by: Aleksander Wasaznik --- include/zephyr/bluetooth/l2cap.h | 5 +++++ subsys/bluetooth/host/l2cap.c | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index 0117da5ebb963..cdd162f9889d7 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -349,6 +349,11 @@ struct bt_l2cap_chan_ops { * @kconfig{CONFIG_BT_L2CAP_SEG_RECV} is enabled and seg_recv is * supplied. * + * If the application returns @c -EINPROGRESS, the application takes + * ownership of the reference in @p buf. (I.e. This pointer value can + * simply be given to @ref bt_l2cap_chan_recv_complete without any + * calls @ref net_buf_ref or @ref net_buf_unref.) + * * @return 0 in case of success or negative value in case of error. * @return -EINPROGRESS in case where user has to confirm once the data * has been processed by calling diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 3b5cfe8286497..8012706bc4560 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -2566,6 +2567,7 @@ static void l2cap_chan_le_recv_seg_direct(struct bt_l2cap_le_chan *chan, struct static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan, struct net_buf *buf) { + struct net_buf *owned_ref; uint16_t sdu_len; int err; @@ -2639,7 +2641,13 @@ static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan, return; } - err = chan->chan.ops->recv(&chan->chan, buf); + owned_ref = net_buf_ref(buf); + err = chan->chan.ops->recv(&chan->chan, owned_ref); + if (err != -EINPROGRESS) { + net_buf_unref(owned_ref); + owned_ref = NULL; + } + if (err < 0) { if (err != -EINPROGRESS) { LOG_ERR("err %d", err); From 185c5f289f8298d0f9af237cef384725845ed3df Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 22 Aug 2024 10:14:02 +0200 Subject: [PATCH 2/5] Bluetooth: Host: Upgrade log severity for L2CAP user error For ease of development, we should log the event as an error. Signed-off-by: Aleksander Wasaznik --- subsys/bluetooth/host/l2cap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 8012706bc4560..d280db5363cd0 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -3147,7 +3147,7 @@ static int bt_l2cap_dyn_chan_send(struct bt_l2cap_le_chan *le_chan, struct net_b /* Call `net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE)` * when allocating buffers intended for bt_l2cap_chan_send(). */ - LOG_DBG("Not enough headroom in buf %p", buf); + LOG_ERR("Not enough headroom in buf %p", buf); return -EINVAL; } @@ -3195,7 +3195,7 @@ int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf) LOG_DBG("chan %p buf %p len %zu", chan, buf, buf->len); if (buf->ref != 1) { - LOG_DBG("Expecting 1 ref, got %d", buf->ref); + LOG_WRN("Expecting 1 ref, got %d", buf->ref); return -EINVAL; } From 82231e57833e31e728770ed9ee8003c7880e6257 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 22 Aug 2024 10:17:39 +0200 Subject: [PATCH 3/5] Bluetooth: Host: Add BT_TESTING trace event for ACL pool destroy This is needed for a test to catch a double-free. Signed-off-by: Aleksander Wasaznik --- include/zephyr/bluetooth/testing.h | 27 +++++++++++++++++++++++++++ subsys/bluetooth/host/hci_core.c | 12 ++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 include/zephyr/bluetooth/testing.h diff --git a/include/zephyr/bluetooth/testing.h b/include/zephyr/bluetooth/testing.h new file mode 100644 index 0000000000000..3ac48c7b36e11 --- /dev/null +++ b/include/zephyr/bluetooth/testing.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @brief Internal testing interfaces for Bluetooth + * @file + * @internal + * + * The interfaces in this file are internal and not stable. + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_TESTING_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_TESTING_H_ + +#include + +/** @brief Hook for `acl_in_pool.destroy` + * + * Weak-function interface. The user can simply define this + * function, and it will automatically become the event + * listener. + * + * @kconfig_dep{CONFIG_BT_TESTING} + */ +void bt_testing_trace_event_acl_pool_destroy(struct net_buf *buf); + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_TESTING_H_ */ diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 14b48ed0e797a..c01453e7e3932 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #if DT_HAS_CHOSEN(zephyr_bt_hci) #include #else @@ -263,6 +265,12 @@ void bt_send_one_host_num_completed_packets(uint16_t handle) BT_ASSERT_MSG(err == 0, "Unable to send Host NCP (err %d)", err); } +#if defined(CONFIG_BT_TESTING) +__weak void bt_testing_trace_event_acl_pool_destroy(struct net_buf *buf) +{ +} +#endif + #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) void bt_hci_host_num_completed_packets(struct net_buf *buf) { @@ -270,6 +278,10 @@ void bt_hci_host_num_completed_packets(struct net_buf *buf) struct bt_conn *conn; uint8_t index = acl(buf)->index; + if (IS_ENABLED(CONFIG_BT_TESTING)) { + bt_testing_trace_event_acl_pool_destroy(buf); + } + net_buf_destroy(buf); if (acl(buf)->host_ncp_sent) { From 31fc3a4000145efdd6bc65b3e74b80d58a396b05 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 22 Aug 2024 10:19:08 +0200 Subject: [PATCH 4/5] Bluetooth: testlib: Add `BT_TESTLIB_ADDR_LE_RANDOM_C0_00_00_00_00_` This is shorthand for random static addresses. It's similar to `bt_addr_le_from_str`, but is a macro that results in an object literal, making it more versatile and less verbose. This macro only gives access to the first 255 random static addresses, but this ought to be enough addresses for testing. Signed-off-by: Aleksander Wasaznik --- .../common/testlib/include/testlib/addr.h | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/bluetooth/common/testlib/include/testlib/addr.h diff --git a/tests/bluetooth/common/testlib/include/testlib/addr.h b/tests/bluetooth/common/testlib/include/testlib/addr.h new file mode 100644 index 0000000000000..2f9e49488b7a5 --- /dev/null +++ b/tests/bluetooth/common/testlib/include/testlib/addr.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ADDR_H_ +#define ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ADDR_H_ + +#include + +#include +#include + +/** Bluetooth LE static random address */ +#define BT_TESTLIB_ADDR_LE_RANDOM_C0_00_00_00_00_(last) \ + ((bt_addr_le_t){ \ + .type = BT_ADDR_LE_RANDOM, \ + .a = {{last, 0x00, 0x00, 0x00, 0x00, 0xc0}}, \ + }) + +#endif /* ZEPHYR_TESTS_BLUETOOTH_COMMON_TESTLIB_INCLUDE_TESTLIB_ADDR_H_ */ From e8b9c00d72f898f70a1717b1551214193b443f2e Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 1 Aug 2024 14:25:51 +0200 Subject: [PATCH 5/5] Bluetooth: Host: Test L2CAP -EINPROGRESS feature The test implementation is based on a copy of the HFC multilink test. The test verifies that the stack respects the reference counting of SDU buffers when the L2CAP -EINPROGRESS feature is used. Signed-off-by: Aleksander Wasaznik --- tests/bsim/bluetooth/host/l2cap/compile.sh | 1 + .../host/l2cap/einprogress/CMakeLists.txt | 24 ++++ .../host/l2cap/einprogress/compile.sh | 13 ++ .../bluetooth/host/l2cap/einprogress/prj.conf | 25 ++++ .../host/l2cap/einprogress/src/data.h | 11 ++ .../host/l2cap/einprogress/src/dut.c | 124 ++++++++++++++++++ .../host/l2cap/einprogress/src/main.c | 47 +++++++ .../host/l2cap/einprogress/src/tester.c | 72 ++++++++++ .../l2cap/einprogress/test_scripts/run.sh | 26 ++++ 9 files changed, 343 insertions(+) create mode 100644 tests/bsim/bluetooth/host/l2cap/einprogress/CMakeLists.txt create mode 100755 tests/bsim/bluetooth/host/l2cap/einprogress/compile.sh create mode 100644 tests/bsim/bluetooth/host/l2cap/einprogress/prj.conf create mode 100644 tests/bsim/bluetooth/host/l2cap/einprogress/src/data.h create mode 100644 tests/bsim/bluetooth/host/l2cap/einprogress/src/dut.c create mode 100644 tests/bsim/bluetooth/host/l2cap/einprogress/src/main.c create mode 100644 tests/bsim/bluetooth/host/l2cap/einprogress/src/tester.c create mode 100755 tests/bsim/bluetooth/host/l2cap/einprogress/test_scripts/run.sh diff --git a/tests/bsim/bluetooth/host/l2cap/compile.sh b/tests/bsim/bluetooth/host/l2cap/compile.sh index 71d41a7f2e75c..ddb7f5d14bcf8 100755 --- a/tests/bsim/bluetooth/host/l2cap/compile.sh +++ b/tests/bsim/bluetooth/host/l2cap/compile.sh @@ -19,6 +19,7 @@ app=tests/bsim/bluetooth/host/l2cap/stress conf_file=prj_nofrag.conf compile app=tests/bsim/bluetooth/host/l2cap/stress conf_file=prj_syswq.conf compile run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/split/compile.sh run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/reassembly/compile.sh +run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/einprogress/compile.sh run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/ecred/compile.sh app=tests/bsim/bluetooth/host/l2cap/credits compile app=tests/bsim/bluetooth/host/l2cap/credits conf_file=prj_ecred.conf compile diff --git a/tests/bsim/bluetooth/host/l2cap/einprogress/CMakeLists.txt b/tests/bsim/bluetooth/host/l2cap/einprogress/CMakeLists.txt new file mode 100644 index 0000000000000..b6d0135f93609 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/einprogress/CMakeLists.txt @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(test_l2cap_einprogress) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib) +target_link_libraries(app PRIVATE testlib) + +add_subdirectory(${ZEPHYR_BASE}/tests/bsim/babblekit babblekit) +target_link_libraries(app PRIVATE babblekit) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ +) + +target_sources(app PRIVATE + src/main.c + src/dut.c + src/tester.c +) diff --git a/tests/bsim/bluetooth/host/l2cap/einprogress/compile.sh b/tests/bsim/bluetooth/host/l2cap/einprogress/compile.sh new file mode 100755 index 0000000000000..e717a4b2bbef0 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/einprogress/compile.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +set -eu +: "${ZEPHYR_BASE:?ZEPHYR_BASE must be defined}" + +INCR_BUILD=1 + +source ${ZEPHYR_BASE}/tests/bsim/compile.source + +app="$(guess_test_relpath)" compile + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/l2cap/einprogress/prj.conf b/tests/bsim/bluetooth/host/l2cap/einprogress/prj.conf new file mode 100644 index 0000000000000..e2540cd6f6a88 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/einprogress/prj.conf @@ -0,0 +1,25 @@ +CONFIG_LOG=y +CONFIG_ASSERT=y +CONFIG_THREAD_NAME=y +CONFIG_LOG_THREAD_ID_PREFIX=y +CONFIG_ARCH_POSIX_TRAP_ON_FATAL=y +CONFIG_BT_TESTING=y + +CONFIG_BT_HCI_ACL_FLOW_CONTROL=y + +CONFIG_BT=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y + +# Dependency of testlib/adv and testlib/scan. +CONFIG_BT_EXT_ADV=y + +# Dynamic channel depends on SMP +CONFIG_BT_SMP=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y + +# Disable auto-initiated procedures so they don't +# mess with the test's execution. +CONFIG_BT_AUTO_PHY_UPDATE=n +CONFIG_BT_AUTO_DATA_LEN_UPDATE=n +CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n diff --git a/tests/bsim/bluetooth/host/l2cap/einprogress/src/data.h b/tests/bsim/bluetooth/host/l2cap/einprogress/src/data.h new file mode 100644 index 0000000000000..4920d909d089f --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/einprogress/src/data.h @@ -0,0 +1,11 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_TESTS_BSIM_BLUETOOTH_HOST_L2CAP_EINPROGRESS_SRC_DATA_H_ +#define ZEPHYR_TESTS_BSIM_BLUETOOTH_HOST_L2CAP_EINPROGRESS_SRC_DATA_H_ + +#define TEST_DATA_L2CAP_PSM 0x0080 +#define TEST_DATA_DUT_ADDR BT_TESTLIB_ADDR_LE_RANDOM_C0_00_00_00_00_(0x01) + +#endif /* ZEPHYR_TESTS_BSIM_BLUETOOTH_HOST_L2CAP_EINPROGRESS_SRC_DATA_H_ */ diff --git a/tests/bsim/bluetooth/host/l2cap/einprogress/src/dut.c b/tests/bsim/bluetooth/host/l2cap/einprogress/src/dut.c new file mode 100644 index 0000000000000..2c026befd203d --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/einprogress/src/dut.c @@ -0,0 +1,124 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "data.h" + +LOG_MODULE_REGISTER(dut, LOG_LEVEL_INF); + +/** Here we keep track of the reference count in the test + * application. This allows us to notice if the stack has freed + * references that were ours. + */ +static atomic_t acl_pool_refs_held[CONFIG_BT_BUF_ACL_RX_COUNT]; + +BUILD_ASSERT(IS_ENABLED(CONFIG_BT_TESTING)); +BUILD_ASSERT(IS_ENABLED(CONFIG_BT_HCI_ACL_FLOW_CONTROL)); +void bt_testing_trace_event_acl_pool_destroy(struct net_buf *destroyed_buf) +{ + int buf_id = net_buf_id(destroyed_buf); + + __ASSERT_NO_MSG(0 <= buf_id && buf_id < ARRAY_SIZE(acl_pool_refs_held)); + TEST_ASSERT(acl_pool_refs_held[buf_id] == 0, + "ACL buf was destroyed while tester still held a reference"); +} + +static void acl_pool_refs_held_add(struct net_buf *buf) +{ + int buf_id = net_buf_id(buf); + + __ASSERT_NO_MSG(0 <= buf_id && buf_id < CONFIG_BT_BUF_ACL_RX_COUNT); + atomic_inc(&acl_pool_refs_held[buf_id]); +} + +static void acl_pool_refs_held_remove(struct net_buf *buf) +{ + int buf_id = net_buf_id(buf); + + __ASSERT_NO_MSG(0 <= buf_id && buf_id < ARRAY_SIZE(acl_pool_refs_held)); + atomic_val_t old = atomic_dec(&acl_pool_refs_held[buf_id]); + + __ASSERT(old != 0, "Tester error: releasing a reference that was not held"); +} + +struct k_fifo ack_todo; + +static int dut_chan_recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf) +{ + /* Move buf. Ownership is ours if we return -EINPROGRESS. */ + acl_pool_refs_held_add(buf); + k_fifo_put(&ack_todo, buf); + + return -EINPROGRESS; +} + +static const struct bt_l2cap_chan_ops ops = { + .recv = dut_chan_recv_cb, +}; + +static struct bt_l2cap_le_chan le_chan = { + .chan.ops = &ops, +}; + +static int dut_server_accept_cb(struct bt_conn *conn, struct bt_l2cap_server *server, + struct bt_l2cap_chan **chan) +{ + *chan = &le_chan.chan; + return 0; +} + +static struct bt_l2cap_server test_l2cap_server = { + .accept = dut_server_accept_cb, + .psm = TEST_DATA_L2CAP_PSM, +}; + +void entrypoint_dut(void) +{ + struct net_buf *ack_buf; + struct bt_conn *conn = NULL; + int err; + + TEST_START("dut"); + + k_fifo_init(&ack_todo); + + err = bt_id_create(&TEST_DATA_DUT_ADDR, NULL); + __ASSERT_NO_MSG(!err); + + err = bt_enable(NULL); + __ASSERT_NO_MSG(!err); + + err = bt_l2cap_server_register(&test_l2cap_server); + __ASSERT_NO_MSG(!err); + + err = bt_testlib_adv_conn(&conn, BT_ID_DEFAULT, NULL); + __ASSERT_NO_MSG(!err); + + ack_buf = k_fifo_get(&ack_todo, K_FOREVER); + __ASSERT_NO_MSG(ack_buf); + + acl_pool_refs_held_remove(ack_buf); + err = bt_l2cap_chan_recv_complete(&le_chan.chan, ack_buf); + TEST_ASSERT(!err); + + TEST_PASS_AND_EXIT("dut"); +} diff --git a/tests/bsim/bluetooth/host/l2cap/einprogress/src/main.c b/tests/bsim/bluetooth/host/l2cap/einprogress/src/main.c new file mode 100644 index 0000000000000..d6611e8f8dd14 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/einprogress/src/main.c @@ -0,0 +1,47 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "bstests.h" +#include "babblekit/testcase.h" + +extern void entrypoint_dut(void); +extern void entrypoint_tester(void); +extern enum bst_result_t bst_result; + +static void test_end_cb(void) +{ + if (bst_result != Passed) { + TEST_PRINT("Test has not passed."); + } +} + +static const struct bst_test_instance entrypoints[] = { + { + .test_id = "l2cap/einprogress/dut", + .test_delete_f = test_end_cb, + .test_main_f = entrypoint_dut, + }, + { + .test_id = "l2cap/einprogress/tester", + .test_delete_f = test_end_cb, + .test_main_f = entrypoint_tester, + }, + BSTEST_END_MARKER, +}; + +static struct bst_test_list *install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, entrypoints); +}; + +bst_test_install_t test_installers[] = {install, NULL}; + +int main(void) +{ + bst_main(); + + return 0; +} diff --git a/tests/bsim/bluetooth/host/l2cap/einprogress/src/tester.c b/tests/bsim/bluetooth/host/l2cap/einprogress/src/tester.c new file mode 100644 index 0000000000000..2e2d000aa9c43 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/einprogress/src/tester.c @@ -0,0 +1,72 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "data.h" + +LOG_MODULE_REGISTER(tester, LOG_LEVEL_INF); + +static int tester_chan_recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf) +{ + __ASSERT(false, "Unexpected recv in tester"); + return 0; +}; + +static struct bt_l2cap_le_chan le_chan = { + .chan.ops = + &(const struct bt_l2cap_chan_ops){ + .recv = tester_chan_recv_cb, + }, +}; + +NET_BUF_POOL_DEFINE(test_pool, 1, BT_L2CAP_SDU_BUF_SIZE(0), CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +void entrypoint_tester(void) +{ + struct net_buf *sdu; + struct bt_conn *conn = NULL; + int err; + + TEST_START("tester"); + + err = bt_enable(NULL); + __ASSERT_NO_MSG(!err); + + err = bt_testlib_connect(&TEST_DATA_DUT_ADDR, &conn); + __ASSERT_NO_MSG(!err); + + err = bt_l2cap_chan_connect(conn, &le_chan.chan, TEST_DATA_L2CAP_PSM); + __ASSERT_NO_MSG(!err); + + /* Wait for async L2CAP connect */ + while (!atomic_test_bit(le_chan.chan.status, BT_L2CAP_STATUS_OUT)) { + k_sleep(K_MSEC(100)); + } + + sdu = net_buf_alloc(&test_pool, K_NO_WAIT); + __ASSERT_NO_MSG(sdu); + net_buf_reserve(sdu, BT_L2CAP_SDU_CHAN_SEND_RESERVE); + + err = bt_l2cap_chan_send(&le_chan.chan, sdu); + __ASSERT(!err, "err: %d", err); + + TEST_PASS("tester"); +} diff --git a/tests/bsim/bluetooth/host/l2cap/einprogress/test_scripts/run.sh b/tests/bsim/bluetooth/host/l2cap/einprogress/test_scripts/run.sh new file mode 100755 index 0000000000000..b86db52d9dfc0 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/einprogress/test_scripts/run.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +set -eu + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +test_name="$(guess_test_long_name)" +simulation_id=${test_name} +verbosity_level=2 +EXECUTE_TIMEOUT=120 +SIM_LEN_US=$((2 * 1000 * 1000)) + +test_exe="${BSIM_OUT_PATH}/bin/bs_${BOARD_TS}_${test_name}_prj_conf" + +cd ${BSIM_OUT_PATH}/bin + +Execute "${test_exe}" -v=${verbosity_level} -s=${simulation_id} -d=0 \ + -testid=l2cap/einprogress/dut +Execute "${test_exe}" -v=${verbosity_level} -s=${simulation_id} -d=1 \ + -testid=l2cap/einprogress/tester + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} -D=2 -sim_length=${SIM_LEN_US} $@ + +wait_for_background_jobs