Skip to content

Commit edbbea5

Browse files
alwa-nordicPavelVPV
authored andcommitted
[nrf fromtree] 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 <[email protected]> (cherry picked from commit 47325f8)
1 parent 36a828c commit edbbea5

File tree

9 files changed

+343
-0
lines changed

9 files changed

+343
-0
lines changed

tests/bsim/bluetooth/host/l2cap/compile.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ app=tests/bsim/bluetooth/host/l2cap/stress conf_file=prj_nofrag.conf compile
1919
app=tests/bsim/bluetooth/host/l2cap/stress conf_file=prj_syswq.conf compile
2020
run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/split/compile.sh
2121
run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/reassembly/compile.sh
22+
run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/einprogress/compile.sh
2223
run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/ecred/compile.sh
2324
app=tests/bsim/bluetooth/host/l2cap/credits compile
2425
app=tests/bsim/bluetooth/host/l2cap/credits conf_file=prj_ecred.conf compile
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
7+
project(test_l2cap_einprogress)
8+
9+
add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib)
10+
target_link_libraries(app PRIVATE testlib)
11+
12+
add_subdirectory(${ZEPHYR_BASE}/tests/bsim/babblekit babblekit)
13+
target_link_libraries(app PRIVATE babblekit)
14+
15+
zephyr_include_directories(
16+
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
17+
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
18+
)
19+
20+
target_sources(app PRIVATE
21+
src/main.c
22+
src/dut.c
23+
src/tester.c
24+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env bash
2+
# Copyright 2023 Nordic Semiconductor ASA
3+
# SPDX-License-Identifier: Apache-2.0
4+
set -eu
5+
: "${ZEPHYR_BASE:?ZEPHYR_BASE must be defined}"
6+
7+
INCR_BUILD=1
8+
9+
source ${ZEPHYR_BASE}/tests/bsim/compile.source
10+
11+
app="$(guess_test_relpath)" compile
12+
13+
wait_for_background_jobs
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
CONFIG_LOG=y
2+
CONFIG_ASSERT=y
3+
CONFIG_THREAD_NAME=y
4+
CONFIG_LOG_THREAD_ID_PREFIX=y
5+
CONFIG_ARCH_POSIX_TRAP_ON_FATAL=y
6+
CONFIG_BT_TESTING=y
7+
8+
CONFIG_BT_HCI_ACL_FLOW_CONTROL=y
9+
10+
CONFIG_BT=y
11+
CONFIG_BT_CENTRAL=y
12+
CONFIG_BT_PERIPHERAL=y
13+
14+
# Dependency of testlib/adv and testlib/scan.
15+
CONFIG_BT_EXT_ADV=y
16+
17+
# Dynamic channel depends on SMP
18+
CONFIG_BT_SMP=y
19+
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
20+
21+
# Disable auto-initiated procedures so they don't
22+
# mess with the test's execution.
23+
CONFIG_BT_AUTO_PHY_UPDATE=n
24+
CONFIG_BT_AUTO_DATA_LEN_UPDATE=n
25+
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* Copyright (c) 2024 Nordic Semiconductor ASA
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
5+
#ifndef ZEPHYR_TESTS_BSIM_BLUETOOTH_HOST_L2CAP_EINPROGRESS_SRC_DATA_H_
6+
#define ZEPHYR_TESTS_BSIM_BLUETOOTH_HOST_L2CAP_EINPROGRESS_SRC_DATA_H_
7+
8+
#define TEST_DATA_L2CAP_PSM 0x0080
9+
#define TEST_DATA_DUT_ADDR BT_TESTLIB_ADDR_LE_RANDOM_C0_00_00_00_00_(0x01)
10+
11+
#endif /* ZEPHYR_TESTS_BSIM_BLUETOOTH_HOST_L2CAP_EINPROGRESS_SRC_DATA_H_ */
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/* Copyright (c) 2024 Nordic Semiconductor ASA
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
5+
#include <zephyr/kernel.h>
6+
#include <zephyr/bluetooth/bluetooth.h>
7+
#include <zephyr/bluetooth/conn.h>
8+
#include <zephyr/bluetooth/l2cap.h>
9+
#include <zephyr/bluetooth/testing.h>
10+
#include <zephyr/logging/log.h>
11+
#include <zephyr/net_buf.h>
12+
#include <zephyr/sys/__assert.h>
13+
#include <zephyr/sys/atomic.h>
14+
#include <zephyr/sys/util_macro.h>
15+
16+
#include <testlib/addr.h>
17+
#include <testlib/adv.h>
18+
#include <testlib/conn.h>
19+
#include <testlib/scan.h>
20+
21+
#include <babblekit/flags.h>
22+
#include <babblekit/testcase.h>
23+
24+
#include "data.h"
25+
26+
LOG_MODULE_REGISTER(dut, LOG_LEVEL_INF);
27+
28+
/** Here we keep track of the reference count in the test
29+
* application. This allows us to notice if the stack has freed
30+
* references that were ours.
31+
*/
32+
static atomic_t acl_pool_refs_held[CONFIG_BT_BUF_ACL_RX_COUNT];
33+
34+
BUILD_ASSERT(IS_ENABLED(CONFIG_BT_TESTING));
35+
BUILD_ASSERT(IS_ENABLED(CONFIG_BT_HCI_ACL_FLOW_CONTROL));
36+
void bt_testing_trace_event_acl_pool_destroy(struct net_buf *destroyed_buf)
37+
{
38+
int buf_id = net_buf_id(destroyed_buf);
39+
40+
__ASSERT_NO_MSG(0 <= buf_id && buf_id < ARRAY_SIZE(acl_pool_refs_held));
41+
TEST_ASSERT(acl_pool_refs_held[buf_id] == 0,
42+
"ACL buf was destroyed while tester still held a reference");
43+
}
44+
45+
static void acl_pool_refs_held_add(struct net_buf *buf)
46+
{
47+
int buf_id = net_buf_id(buf);
48+
49+
__ASSERT_NO_MSG(0 <= buf_id && buf_id < CONFIG_BT_BUF_ACL_RX_COUNT);
50+
atomic_inc(&acl_pool_refs_held[buf_id]);
51+
}
52+
53+
static void acl_pool_refs_held_remove(struct net_buf *buf)
54+
{
55+
int buf_id = net_buf_id(buf);
56+
57+
__ASSERT_NO_MSG(0 <= buf_id && buf_id < ARRAY_SIZE(acl_pool_refs_held));
58+
atomic_val_t old = atomic_dec(&acl_pool_refs_held[buf_id]);
59+
60+
__ASSERT(old != 0, "Tester error: releasing a reference that was not held");
61+
}
62+
63+
struct k_fifo ack_todo;
64+
65+
static int dut_chan_recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf)
66+
{
67+
/* Move buf. Ownership is ours if we return -EINPROGRESS. */
68+
acl_pool_refs_held_add(buf);
69+
k_fifo_put(&ack_todo, buf);
70+
71+
return -EINPROGRESS;
72+
}
73+
74+
static const struct bt_l2cap_chan_ops ops = {
75+
.recv = dut_chan_recv_cb,
76+
};
77+
78+
static struct bt_l2cap_le_chan le_chan = {
79+
.chan.ops = &ops,
80+
};
81+
82+
static int dut_server_accept_cb(struct bt_conn *conn, struct bt_l2cap_server *server,
83+
struct bt_l2cap_chan **chan)
84+
{
85+
*chan = &le_chan.chan;
86+
return 0;
87+
}
88+
89+
static struct bt_l2cap_server test_l2cap_server = {
90+
.accept = dut_server_accept_cb,
91+
.psm = TEST_DATA_L2CAP_PSM,
92+
};
93+
94+
void entrypoint_dut(void)
95+
{
96+
struct net_buf *ack_buf;
97+
struct bt_conn *conn = NULL;
98+
int err;
99+
100+
TEST_START("dut");
101+
102+
k_fifo_init(&ack_todo);
103+
104+
err = bt_id_create(&TEST_DATA_DUT_ADDR, NULL);
105+
__ASSERT_NO_MSG(!err);
106+
107+
err = bt_enable(NULL);
108+
__ASSERT_NO_MSG(!err);
109+
110+
err = bt_l2cap_server_register(&test_l2cap_server);
111+
__ASSERT_NO_MSG(!err);
112+
113+
err = bt_testlib_adv_conn(&conn, BT_ID_DEFAULT, NULL);
114+
__ASSERT_NO_MSG(!err);
115+
116+
ack_buf = k_fifo_get(&ack_todo, K_FOREVER);
117+
__ASSERT_NO_MSG(ack_buf);
118+
119+
acl_pool_refs_held_remove(ack_buf);
120+
err = bt_l2cap_chan_recv_complete(&le_chan.chan, ack_buf);
121+
TEST_ASSERT(!err);
122+
123+
TEST_PASS_AND_EXIT("dut");
124+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* Copyright (c) 2024 Nordic Semiconductor ASA
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
5+
#include <zephyr/kernel.h>
6+
7+
#include "bstests.h"
8+
#include "babblekit/testcase.h"
9+
10+
extern void entrypoint_dut(void);
11+
extern void entrypoint_tester(void);
12+
extern enum bst_result_t bst_result;
13+
14+
static void test_end_cb(void)
15+
{
16+
if (bst_result != Passed) {
17+
TEST_PRINT("Test has not passed.");
18+
}
19+
}
20+
21+
static const struct bst_test_instance entrypoints[] = {
22+
{
23+
.test_id = "l2cap/einprogress/dut",
24+
.test_delete_f = test_end_cb,
25+
.test_main_f = entrypoint_dut,
26+
},
27+
{
28+
.test_id = "l2cap/einprogress/tester",
29+
.test_delete_f = test_end_cb,
30+
.test_main_f = entrypoint_tester,
31+
},
32+
BSTEST_END_MARKER,
33+
};
34+
35+
static struct bst_test_list *install(struct bst_test_list *tests)
36+
{
37+
return bst_add_tests(tests, entrypoints);
38+
};
39+
40+
bst_test_install_t test_installers[] = {install, NULL};
41+
42+
int main(void)
43+
{
44+
bst_main();
45+
46+
return 0;
47+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* Copyright (c) 2024 Nordic Semiconductor ASA
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
5+
#include <zephyr/kernel.h>
6+
#include <zephyr/bluetooth/bluetooth.h>
7+
#include <zephyr/bluetooth/conn.h>
8+
#include <zephyr/bluetooth/l2cap.h>
9+
#include <zephyr/logging/log.h>
10+
#include <zephyr/net_buf.h>
11+
#include <zephyr/sys/__assert.h>
12+
#include <zephyr/sys/atomic.h>
13+
#include <zephyr/sys/util_macro.h>
14+
15+
#include <testlib/addr.h>
16+
#include <testlib/adv.h>
17+
#include <testlib/conn.h>
18+
#include <testlib/scan.h>
19+
20+
#include <babblekit/flags.h>
21+
#include <babblekit/testcase.h>
22+
23+
#include "data.h"
24+
25+
LOG_MODULE_REGISTER(tester, LOG_LEVEL_INF);
26+
27+
static int tester_chan_recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf)
28+
{
29+
__ASSERT(false, "Unexpected recv in tester");
30+
return 0;
31+
};
32+
33+
static struct bt_l2cap_le_chan le_chan = {
34+
.chan.ops =
35+
&(const struct bt_l2cap_chan_ops){
36+
.recv = tester_chan_recv_cb,
37+
},
38+
};
39+
40+
NET_BUF_POOL_DEFINE(test_pool, 1, BT_L2CAP_SDU_BUF_SIZE(0), CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
41+
42+
void entrypoint_tester(void)
43+
{
44+
struct net_buf *sdu;
45+
struct bt_conn *conn = NULL;
46+
int err;
47+
48+
TEST_START("tester");
49+
50+
err = bt_enable(NULL);
51+
__ASSERT_NO_MSG(!err);
52+
53+
err = bt_testlib_connect(&TEST_DATA_DUT_ADDR, &conn);
54+
__ASSERT_NO_MSG(!err);
55+
56+
err = bt_l2cap_chan_connect(conn, &le_chan.chan, TEST_DATA_L2CAP_PSM);
57+
__ASSERT_NO_MSG(!err);
58+
59+
/* Wait for async L2CAP connect */
60+
while (!atomic_test_bit(le_chan.chan.status, BT_L2CAP_STATUS_OUT)) {
61+
k_sleep(K_MSEC(100));
62+
}
63+
64+
sdu = net_buf_alloc(&test_pool, K_NO_WAIT);
65+
__ASSERT_NO_MSG(sdu);
66+
net_buf_reserve(sdu, BT_L2CAP_SDU_CHAN_SEND_RESERVE);
67+
68+
err = bt_l2cap_chan_send(&le_chan.chan, sdu);
69+
__ASSERT(!err, "err: %d", err);
70+
71+
TEST_PASS("tester");
72+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env bash
2+
# Copyright (c) 2024 Nordic Semiconductor
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
set -eu
6+
7+
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
8+
9+
test_name="$(guess_test_long_name)"
10+
simulation_id=${test_name}
11+
verbosity_level=2
12+
EXECUTE_TIMEOUT=120
13+
SIM_LEN_US=$((2 * 1000 * 1000))
14+
15+
test_exe="${BSIM_OUT_PATH}/bin/bs_${BOARD_TS}_${test_name}_prj_conf"
16+
17+
cd ${BSIM_OUT_PATH}/bin
18+
19+
Execute "${test_exe}" -v=${verbosity_level} -s=${simulation_id} -d=0 \
20+
-testid=l2cap/einprogress/dut
21+
Execute "${test_exe}" -v=${verbosity_level} -s=${simulation_id} -d=1 \
22+
-testid=l2cap/einprogress/tester
23+
24+
Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} -D=2 -sim_length=${SIM_LEN_US} $@
25+
26+
wait_for_background_jobs

0 commit comments

Comments
 (0)