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 <aleksander.wasaznik@nordicsemi.no>
This commit is contained in:
parent
abeca24702
commit
47325f8df5
9 changed files with 343 additions and 0 deletions
|
@ -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
|
||||
|
|
24
tests/bsim/bluetooth/host/l2cap/einprogress/CMakeLists.txt
Normal file
24
tests/bsim/bluetooth/host/l2cap/einprogress/CMakeLists.txt
Normal file
|
@ -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
|
||||
)
|
13
tests/bsim/bluetooth/host/l2cap/einprogress/compile.sh
Executable file
13
tests/bsim/bluetooth/host/l2cap/einprogress/compile.sh
Executable file
|
@ -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
|
25
tests/bsim/bluetooth/host/l2cap/einprogress/prj.conf
Normal file
25
tests/bsim/bluetooth/host/l2cap/einprogress/prj.conf
Normal file
|
@ -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
|
11
tests/bsim/bluetooth/host/l2cap/einprogress/src/data.h
Normal file
11
tests/bsim/bluetooth/host/l2cap/einprogress/src/data.h
Normal file
|
@ -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_ */
|
124
tests/bsim/bluetooth/host/l2cap/einprogress/src/dut.c
Normal file
124
tests/bsim/bluetooth/host/l2cap/einprogress/src/dut.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/l2cap.h>
|
||||
#include <zephyr/bluetooth/testing.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/net_buf.h>
|
||||
#include <zephyr/sys/__assert.h>
|
||||
#include <zephyr/sys/atomic.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
|
||||
#include <testlib/addr.h>
|
||||
#include <testlib/adv.h>
|
||||
#include <testlib/conn.h>
|
||||
#include <testlib/scan.h>
|
||||
|
||||
#include <babblekit/flags.h>
|
||||
#include <babblekit/testcase.h>
|
||||
|
||||
#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");
|
||||
}
|
47
tests/bsim/bluetooth/host/l2cap/einprogress/src/main.c
Normal file
47
tests/bsim/bluetooth/host/l2cap/einprogress/src/main.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#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;
|
||||
}
|
72
tests/bsim/bluetooth/host/l2cap/einprogress/src/tester.c
Normal file
72
tests/bsim/bluetooth/host/l2cap/einprogress/src/tester.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/l2cap.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/net_buf.h>
|
||||
#include <zephyr/sys/__assert.h>
|
||||
#include <zephyr/sys/atomic.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
|
||||
#include <testlib/addr.h>
|
||||
#include <testlib/adv.h>
|
||||
#include <testlib/conn.h>
|
||||
#include <testlib/scan.h>
|
||||
|
||||
#include <babblekit/flags.h>
|
||||
#include <babblekit/testcase.h>
|
||||
|
||||
#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");
|
||||
}
|
26
tests/bsim/bluetooth/host/l2cap/einprogress/test_scripts/run.sh
Executable file
26
tests/bsim/bluetooth/host/l2cap/einprogress/test_scripts/run.sh
Executable file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue