Skip to content

Commit 6f29b25

Browse files
ardo-nordicjhedberg
authored andcommitted
tests: bsim: bluetooth: host: robust subscription proc
GATT subscription in conn_stress test was failing and stalling the test due to lack of TX buffers. Retry mechanism added as a workaround. Removing this workaround would make the test fail due to deadlocks, and require allocating more buffers with CONFIG_BT_L2CAP_TX_BUF_COUNT set to 10 as a workaround. Signed-off-by: Artur Dobrynin <[email protected]>
1 parent bb7463f commit 6f29b25

File tree

4 files changed

+52
-29
lines changed

4 files changed

+52
-29
lines changed

tests/bsim/bluetooth/host/misc/conn_stress/central/prj.conf

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ CONFIG_ASSERT_LEVEL=2
2222
CONFIG_ASSERT_VERBOSE=y
2323
CONFIG_ASSERT_ON_ERRORS=y
2424

25-
# TODO: use default 3
26-
# we get an ATT timeout if 3 or SMP timeout if 10
27-
CONFIG_BT_L2CAP_TX_BUF_COUNT=10
28-
2925
# deadlock on central with the default.
3026
# the problem is that `tx_free` is called from both syswq and btwq in that case.
3127
CONFIG_BT_RECV_WORKQ_BT=y

tests/bsim/bluetooth/host/misc/conn_stress/central/src/main.c

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023 Nordic Semiconductor ASA
2+
* Copyright (c) 2023-2025 Nordic Semiconductor ASA
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -22,7 +22,7 @@
2222
#include <zephyr/types.h>
2323

2424
#include <zephyr/logging/log.h>
25-
LOG_MODULE_REGISTER(central, LOG_LEVEL_DBG);
25+
LOG_MODULE_REGISTER(central, LOG_LEVEL_INF);
2626

2727
#include "bstests.h"
2828
#include "bs_types.h"
@@ -73,6 +73,7 @@ enum {
7373
CONN_INFO_MTU_EXCHANGED,
7474
CONN_INFO_DISCOVERING,
7575
CONN_INFO_DISCOVER_PAUSED,
76+
CONN_INFO_SUBSCRIPTION_FAILED,
7677
CONN_INFO_SUBSCRIBED,
7778

7879
/* Total number of flags - must be at the end of the enum */
@@ -213,6 +214,24 @@ static uint8_t notify_func(struct bt_conn *conn, struct bt_gatt_subscribe_params
213214
return BT_GATT_ITER_CONTINUE;
214215
}
215216

217+
static void subscribe_func(struct bt_conn *conn, uint8_t err,
218+
struct bt_gatt_subscribe_params *params)
219+
{
220+
struct conn_info *conn_info_ref;
221+
char addr[BT_ADDR_LE_STR_LEN];
222+
223+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
224+
__ASSERT(!err, "Subscribe failed for addr %s (err %d)", addr, err);
225+
226+
conn_info_ref = get_conn_info_ref(conn);
227+
__ASSERT_NO_MSG(conn_info_ref);
228+
229+
atomic_clear_bit(conn_info_ref->flags, CONN_INFO_SUBSCRIPTION_FAILED);
230+
atomic_set_bit(conn_info_ref->flags, CONN_INFO_SUBSCRIBED);
231+
232+
LOG_DBG("[SUBSCRIBED] addr %s", addr);
233+
}
234+
216235
static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
217236
struct bt_gatt_discover_params *params)
218237
{
@@ -248,6 +267,7 @@ static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *at
248267

249268
err = bt_gatt_discover(conn, &conn_info_ref->discover_params);
250269
if (err == -ENOMEM || err == -ENOTCONN) {
270+
atomic_set_bit(conn_info_ref->flags, CONN_INFO_DISCOVER_PAUSED);
251271
goto retry;
252272
}
253273

@@ -263,33 +283,27 @@ static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *at
263283

264284
err = bt_gatt_discover(conn, &conn_info_ref->discover_params);
265285
if (err == -ENOMEM || err == -ENOTCONN) {
286+
atomic_set_bit(conn_info_ref->flags, CONN_INFO_DISCOVER_PAUSED);
266287
goto retry;
267288
}
268289

269290
__ASSERT(!err, "Discover failed (err %d)", err);
270291

271292
} else {
272293
conn_info_ref->subscribe_params.notify = notify_func;
294+
conn_info_ref->subscribe_params.subscribe = subscribe_func;
273295
conn_info_ref->subscribe_params.value = BT_GATT_CCC_NOTIFY;
274296
conn_info_ref->subscribe_params.ccc_handle = attr->handle;
275297

276298
err = bt_gatt_subscribe(conn, &conn_info_ref->subscribe_params);
277-
if (err == -ENOMEM || err == -ENOTCONN) {
299+
if (err == -ENOMEM || err == -ENOTCONN || err == -EALREADY) {
300+
LOG_DBG("Subcription failed (err %d)", err);
301+
atomic_set_bit(conn_info_ref->flags, CONN_INFO_SUBSCRIPTION_FAILED);
278302
goto retry;
279303
}
280304

281-
if (err != -EALREADY) {
282-
__ASSERT(!err, "Subscribe failed (err %d)", err);
283-
}
284-
285305
__ASSERT_NO_MSG(atomic_test_bit(conn_info_ref->flags, CONN_INFO_DISCOVERING));
286306
__ASSERT_NO_MSG(!atomic_test_bit(conn_info_ref->flags, CONN_INFO_SUBSCRIBED));
287-
atomic_set_bit(conn_info_ref->flags, CONN_INFO_SUBSCRIBED);
288-
289-
char addr[BT_ADDR_LE_STR_LEN];
290-
291-
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
292-
LOG_INF("[SUBSCRIBED] addr %s", addr);
293307
}
294308

295309
return BT_GATT_ITER_STOP;
@@ -299,7 +313,6 @@ static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *at
299313
* later.
300314
*/
301315
LOG_INF("out of memory/not connected, continuing sub later (err %d)", err);
302-
atomic_set_bit(conn_info_ref->flags, CONN_INFO_DISCOVER_PAUSED);
303316

304317
return BT_GATT_ITER_STOP;
305318
}
@@ -579,6 +592,18 @@ static void subscribe_to_service(struct bt_conn *conn, void *data)
579592
return;
580593
}
581594

595+
/* If subcription attempt failed before (due to most likely lack of TX buffers),
596+
* make a new attempt here.
597+
*/
598+
if (atomic_test_bit(conn_info_ref->flags, CONN_INFO_SUBSCRIPTION_FAILED)) {
599+
err = bt_gatt_subscribe(conn, &conn_info_ref->subscribe_params);
600+
if (err != -ENOMEM) {
601+
__ASSERT(!err, "Subcription failed");
602+
} else {
603+
return;
604+
}
605+
}
606+
582607
/* start subscription procedure if:
583608
* - we haven't started it yet for this conn
584609
* - it was suspended due to a lack of resources
@@ -724,7 +749,7 @@ void test_init(void)
724749
extern enum bst_result_t bst_result;
725750

726751
LOG_INF("Initializing Test");
727-
bst_ticker_set_next_tick_absolute(600*1e6);
752+
bst_ticker_set_next_tick_absolute(100*1e6);
728753
/* The peripherals determines whether the test passed. */
729754
bst_result = Passed;
730755
}

tests/bsim/bluetooth/host/misc/conn_stress/peripheral/src/main.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023 Nordic Semiconductor ASA
2+
* Copyright (c) 2023-2025 Nordic Semiconductor ASA
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -24,7 +24,7 @@
2424
#include <zephyr/types.h>
2525

2626
#include <zephyr/logging/log.h>
27-
LOG_MODULE_REGISTER(peripheral, LOG_LEVEL_DBG);
27+
LOG_MODULE_REGISTER(peripheral, LOG_LEVEL_INF);
2828

2929
#include "bstests.h"
3030
#include "bs_types.h"
@@ -424,7 +424,7 @@ void test_peripheral_main(void)
424424
LOG_ERR("Advertising failed to start (err %d)", err);
425425
__ASSERT_NO_MSG(err);
426426
}
427-
LOG_DBG("Started advertising");
427+
LOG_INF("Started advertising");
428428

429429
bt_gatt_cb_register(&gatt_callbacks);
430430

@@ -449,7 +449,7 @@ void test_peripheral_main(void)
449449
k_sleep(K_MSEC(10));
450450
}
451451

452-
LOG_DBG("Begin sending notifications to central..");
452+
LOG_INF("Begin sending notifications to central..");
453453
while (central_subscription &&
454454
atomic_test_bit(conn_info.flags, CONN_INFO_CONNECTED)) {
455455

@@ -468,7 +468,7 @@ void test_peripheral_main(void)
468468

469469
if (atomic_get(&conn_info.tx_notify_counter) > MIN_NOTIFICATIONS &&
470470
atomic_get(&conn_info.notify_counter) > MIN_NOTIFICATIONS) {
471-
LOG_DBG("Disconnecting..");
471+
LOG_INF("Disconnecting..");
472472
disconnect();
473473
}
474474
}
@@ -482,7 +482,7 @@ void test_init(void)
482482
extern enum bst_result_t bst_result;
483483

484484
LOG_INF("Initializing Test");
485-
bst_ticker_set_next_tick_absolute(600*1e6);
485+
bst_ticker_set_next_tick_absolute(100*1e6);
486486
bst_result = Failed;
487487
}
488488

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
# Copyright (c) 2023 Nordic Semiconductor
2+
# Copyright (c) 2023-2025 Nordic Semiconductor
33
# SPDX-License-Identifier: Apache-2.0
44

55
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
@@ -9,9 +9,11 @@ simulation_id="conn_stress"
99
test_path="tests_bsim_bluetooth_host_misc_conn_stress"
1010
bsim_central_exe_name="bs_${BOARD_TS}_${test_path}_central_prj_conf"
1111
bsim_peripheral_exe_name="bs_${BOARD_TS}_${test_path}_peripheral_prj_conf"
12-
bsim_args="-RealEncryption=1 -v=5 -s=${simulation_id}"
12+
bsim_args="-RealEncryption=1 -v=2 -s=${simulation_id}"
1313
test_args="-argstest notify_size=220 conn_interval=32"
1414

15+
EXECUTE_TIMEOUT=120
16+
1517
cd ${BSIM_OUT_PATH}/bin
1618

1719
for device in `seq 1 12`; do
@@ -21,8 +23,8 @@ for device in `seq 1 12`; do
2123
-d=$device -rs=$rs -testid=peripheral ${test_args}
2224
done
2325

24-
Execute "./${bsim_central_exe_name}" ${bsim_args} -d=0 -rs=001 -testid=central ${test_args}
26+
Execute "./${bsim_central_exe_name}" ${bsim_args} -d=0 -rs=1 -testid=central ${test_args}
2527

26-
Execute ./bs_2G4_phy_v1 -dump -v=2 -s=${simulation_id} -D=13 -sim_length=10000e6 &
28+
Execute ./bs_2G4_phy_v1 -dump -v=2 -s=${simulation_id} -D=13 -sim_length=100e6
2729

2830
wait_for_background_jobs

0 commit comments

Comments
 (0)