Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/releases/release-notes-4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ Bluetooth

* HCI Drivers

* Mesh

* Introduced a mesh-specific workqueue to increase reliability of the mesh messages
transmission. To get the old behavior enable :kconfig:option:`CONFIG_BT_MESH_WORKQ_SYS`.

Boards & SoC Support
********************

Expand Down
58 changes: 58 additions & 0 deletions subsys/bluetooth/mesh/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,64 @@ menuconfig BT_MESH_ADV_EXT

if BT_MESH_ADV_EXT

choice BT_MESH_WORKQ_CONTEXT
prompt "Advertising thread selection"
default BT_MESH_WORKQ_MESH
help
Defines a context for mesh messages transmission.

config BT_MESH_WORKQ_MESH
bool "Mesh-specific workqueue"
help
When this option is selected, the mesh sends messages from the
mesh-specific workqueue. This will ensure that messages are always sent.
The application needs to ensure the mesh-specific workqueue size is large
enough. Refer to BT_MESH_ADV_STACK_SIZE for the recommended minimum.

config BT_MESH_WORKQ_SYS
bool "System workqueue"
help
When this option is selected, the mesh sends messages from
the system work queue. The application needs to ensure the system
workqueue stack size (SYSTEM_WORKQUEUE_STACK_SIZE) is large enough,
refer to BT_MESH_ADV_STACK_SIZE for the recommended minimum.

When this option is enabled and the mesh tries to send a message,
and the host ran out the HCI command buffers controlled by
CONFIG_BT_BUF_CMD_TX_COUNT, the host returns -ENOBUFS immediately
and the mesh drops the message transmission. To mitigate this
issue, make sure to have sufficient number of HCI command buffers.
When this option is enabled, the latency of sending mesh messages
will be affected by other users on the system work queue, resulting in
reduced reliability for sending mesh messages.

endchoice

if BT_MESH_WORKQ_MESH

config BT_MESH_ADV_STACK_SIZE
int "Mesh extended advertiser thread stack size"
default 1536 if BT_MESH_PROXY
default 1024 if BT_HOST_CRYPTO
default 776 if BT_MESH_PRIV_BEACONS
default 768
help
Size of bt mesh adv thread stack.

NOTE: This is an advanced setting and should not be changed unless
absolutely necessary

config BT_MESH_ADV_PRIO
int "Mesh advertiser thread priority"
default 7
help
Priority of bt mesh adv thread.

NOTE: This is an advanced setting and should not be changed unless
absolutely necessary

endif # BT_MESH_WORKQ_MESH

config BT_MESH_RELAY_ADV_SETS
int "Maximum of simultaneous relay message support"
default 0
Expand Down
2 changes: 2 additions & 0 deletions subsys/bluetooth/mesh/adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,6 @@ int bt_mesh_scan_active_set(bool active);
int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_interval,
const struct bt_data *ad, size_t ad_len);

int bt_mesh_wq_submit(struct k_work *work);

#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_ADV_H_ */
39 changes: 34 additions & 5 deletions subsys/bluetooth/mesh/adv_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ LOG_MODULE_REGISTER(bt_mesh_adv_ext);
#define CONFIG_BT_MESH_RELAY_ADV_SETS 0
#endif

#ifdef CONFIG_BT_MESH_ADV_STACK_SIZE
#define MESH_WORKQ_PRIORITY CONFIG_BT_MESH_ADV_PRIO
#define MESH_WORKQ_STACK_SIZE CONFIG_BT_MESH_ADV_STACK_SIZE
#else
#define MESH_WORKQ_PRIORITY 0
#define MESH_WORKQ_STACK_SIZE 0
#endif

enum {
/** Controller is currently advertising */
ADV_FLAG_ACTIVE,
Expand Down Expand Up @@ -72,6 +80,15 @@ struct bt_mesh_ext_adv {
static void send_pending_adv(struct k_work *work);
static bool schedule_send(struct bt_mesh_ext_adv *ext_adv);

static struct k_work_q bt_mesh_workq;
static K_KERNEL_STACK_DEFINE(thread_stack, MESH_WORKQ_STACK_SIZE);

#if defined(CONFIG_BT_MESH_WORKQ_MESH)
#define MESH_WORKQ &bt_mesh_workq
#else /* CONFIG_BT_MESH_WORKQ_SYS */
#define MESH_WORKQ &k_sys_work_q
#endif /* CONFIG_BT_MESH_WORKQ_MESH */

static struct bt_mesh_ext_adv advs[] = {
[0] = {
.tags = (
Expand Down Expand Up @@ -283,7 +300,7 @@ static bool schedule_send_with_mask(struct bt_mesh_ext_adv *ext_adv, int ignore_
}

atomic_clear_bit(ext_adv->flags, ADV_FLAG_SCHEDULE_PENDING);
k_work_submit(&ext_adv->work);
bt_mesh_wq_submit(&ext_adv->work);

return true;
}
Expand Down Expand Up @@ -432,7 +449,7 @@ int bt_mesh_adv_terminate(struct bt_mesh_adv *adv)

atomic_set_bit(ext_adv->flags, ADV_FLAG_SENT);

k_work_submit(&ext_adv->work);
bt_mesh_wq_submit(&ext_adv->work);

return 0;
}
Expand All @@ -455,6 +472,13 @@ void bt_mesh_adv_init(void)
(void)memcpy(&advs[i].adv_param, &adv_param, sizeof(adv_param));
}

if (IS_ENABLED(CONFIG_BT_MESH_WORKQ_MESH)) {
k_work_queue_init(&bt_mesh_workq);
k_work_queue_start(&bt_mesh_workq, thread_stack, MESH_WORKQ_STACK_SIZE,
K_PRIO_COOP(MESH_WORKQ_PRIORITY), NULL);
k_thread_name_set(&bt_mesh_workq.thread, "BT MESH WQ");
}

#if defined(CONFIG_BT_LL_SOFTDEVICE)
const sdc_hci_cmd_vs_scan_accept_ext_adv_packets_set_t cmd_params = {
.accept_ext_adv_packets = IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_ACCEPT_EXT_ADV_PACKETS),
Expand Down Expand Up @@ -495,7 +519,7 @@ static void adv_sent(struct bt_le_ext_adv *instance,

atomic_set_bit(ext_adv->flags, ADV_FLAG_SENT);

k_work_submit(&ext_adv->work);
bt_mesh_wq_submit(&ext_adv->work);
}

#if defined(CONFIG_BT_MESH_GATT_SERVER)
Expand Down Expand Up @@ -549,13 +573,13 @@ int bt_mesh_adv_enable(void)

int bt_mesh_adv_disable(void)
{
int err;
struct k_work_sync sync;
int err;

for (int i = 0; i < ARRAY_SIZE(advs); i++) {
atomic_set_bit(advs[i].flags, ADV_FLAG_SUSPENDING);

if (k_current_get() != &k_sys_work_q.thread ||
if (k_current_get() != k_work_queue_thread_get(MESH_WORKQ) ||
(k_work_busy_get(&advs[i].work) & K_WORK_RUNNING) == 0) {
k_work_flush(&advs[i].work, &sync);
}
Expand Down Expand Up @@ -608,3 +632,8 @@ int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_interval,
{
return bt_data_send(advs, num_events, adv_interval, ad, ad_len);
}

int bt_mesh_wq_submit(struct k_work *work)
{
return k_work_submit_to_queue(MESH_WORKQ, work);
}
5 changes: 5 additions & 0 deletions subsys/bluetooth/mesh/adv_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,8 @@ int bt_mesh_adv_gatt_start(const struct bt_le_adv_param *param, int32_t duration
adv_timeout = duration;
return bt_le_adv_start(param, ad, ad_len, sd, sd_len);
}

int bt_mesh_wq_submit(struct k_work *work)
{
return k_work_submit(work);
}
49 changes: 48 additions & 1 deletion subsys/bluetooth/mesh/proxy_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ static void proxy_sar_timeout(struct k_work *work)
LOG_WRN("Proxy SAR timeout");

role = CONTAINER_OF(dwork, struct bt_mesh_proxy_role, sar_timer);

while (!k_fifo_is_empty(&role->pending)) {
struct bt_mesh_adv *adv = k_fifo_get(&role->pending, K_NO_WAIT);

__ASSERT_NO_MSG(adv);

bt_mesh_adv_unref(adv);
}

if (role->conn) {
bt_conn_disconnect(role->conn,
BT_HCI_ERR_REMOTE_USER_TERM_CONN);
Expand Down Expand Up @@ -200,7 +209,7 @@ static void buf_send_end(struct bt_conn *conn, void *user_data)
bt_mesh_adv_unref(adv);
}

int bt_mesh_proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
static int proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
{
int err;

Expand Down Expand Up @@ -230,6 +239,41 @@ int bt_mesh_proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
return err;
}

int bt_mesh_proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
{
struct bt_mesh_proxy_role *role = &roles[bt_conn_index(conn)];

k_fifo_put(&role->pending, bt_mesh_adv_ref(adv));

bt_mesh_wq_submit(&role->work);

return 0;
}

static void proxy_msg_send_pending(struct k_work *work)
{
struct bt_mesh_proxy_role *role;
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
struct bt_mesh_adv *adv;

role = CONTAINER_OF(dwork, struct bt_mesh_proxy_role, sar_timer);
if (!role->conn) {
return;
}

adv = k_fifo_get(&role->pending, K_NO_WAIT);
if (!adv) {
return;
}

(void)proxy_relay_send(role->conn, adv);
bt_mesh_adv_unref(adv);

if (!k_fifo_is_empty(&role->pending)) {
bt_mesh_wq_submit(&role->work);
}
}

static void proxy_msg_init(struct bt_mesh_proxy_role *role)
{
/* Check if buf has been allocated, in this way, we no longer need
Expand All @@ -247,6 +291,9 @@ static void proxy_msg_init(struct bt_mesh_proxy_role *role)

net_buf_simple_reset(&role->buf);

k_fifo_init(&role->pending);
k_work_init(&role->work, proxy_msg_send_pending);

k_work_init_delayable(&role->sar_timer, proxy_sar_timeout);
}

Expand Down
3 changes: 3 additions & 0 deletions subsys/bluetooth/mesh/proxy_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ struct bt_mesh_proxy_role {
struct bt_conn *conn;
uint8_t msg_type;

struct k_fifo pending;
struct k_work work;

struct {
proxy_send_cb_t send;
proxy_recv_cb_t recv;
Expand Down
2 changes: 1 addition & 1 deletion subsys/bluetooth/mesh/proxy_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ static ssize_t proxy_ccc_write(struct bt_conn *conn,
client = find_client(conn);
if (client->filter_type == NONE) {
client->filter_type = ACCEPT;
k_work_submit(&client->send_beacons);
bt_mesh_wq_submit(&client->send_beacons);
}

return sizeof(value);
Expand Down
5 changes: 4 additions & 1 deletion tests/bsim/bluetooth/mesh/compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ app=tests/bsim/bluetooth/mesh conf_overlay=overlay_pst.conf compile
app=tests/bsim/bluetooth/mesh conf_overlay=overlay_gatt.conf compile
app=tests/bsim/bluetooth/mesh conf_overlay=overlay_low_lat.conf compile
app=tests/bsim/bluetooth/mesh conf_overlay=overlay_psa.conf compile
app=tests/bsim/bluetooth/mesh conf_overlay=overlay_workq_sys.conf compile
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_pst.conf;overlay_psa.conf" compile
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_gatt.conf;overlay_psa.conf" compile
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_gatt.conf;overlay_workq_sys.conf" compile
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_low_lat.conf;overlay_psa.conf" compile
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_gatt.conf;overlay_low_lat.conf" compile
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_pst.conf;overlay_gatt.conf" compile
app=tests/bsim/bluetooth/mesh \
conf_overlay="overlay_pst.conf;overlay_gatt.conf;overlay_psa.conf" compile

app=tests/bsim/bluetooth/mesh \
conf_overlay="overlay_pst.conf;overlay_gatt.conf;overlay_workq_sys.conf" compile
wait_for_background_jobs
1 change: 1 addition & 0 deletions tests/bsim/bluetooth/mesh/overlay_workq_sys.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_BT_MESH_WORKQ_SYS=y
3 changes: 3 additions & 0 deletions tests/bsim/bluetooth/mesh/src/test_suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ static void dut_pub_common(bool disable_bt)
ASSERT_OK_MSG(k_sem_take(&publish_sem, K_SECONDS(30)), "Pub timed out");
}

/* Allow publishing to finish before suspending. */
k_sleep(K_MSEC(100));

ASSERT_OK_MSG(bt_mesh_suspend(), "Failed to suspend Mesh.");

if (disable_bt) {
Expand Down
3 changes: 3 additions & 0 deletions tests/bsim/bluetooth/mesh/tests_scripts/advertiser/disable.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ RunTest mesh_adv_disable adv_tx_disable adv_rx_disable
# Low latency overlay uses legacy advertiser
overlay=overlay_low_lat_conf
RunTest mesh_adv_disable adv_tx_disable adv_rx_disable

overlay=overlay_workq_sys_conf
RunTest mesh_adv_disable_workq adv_tx_disable adv_rx_disable
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh
overlay=overlay_gatt_conf
RunTest mesh_adv_proxy_mixin adv_tx_proxy_mixin adv_rx_proxy_mixin

overlay=overlay_gatt_conf_overlay_workq_sys_conf
RunTest mesh_adv_proxy_mixin_workq adv_tx_proxy_mixin adv_rx_proxy_mixin

overlay="overlay_gatt_conf_overlay_psa_conf"
RunTest mesh_adv_proxy_mixin_psa adv_tx_proxy_mixin adv_rx_proxy_mixin
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh
# test buffer management by filling buffers and sending them in random order.
RunTest mesh_adv_random_order adv_tx_random_order adv_rx_random_order

overlay=overlay_workq_sys_conf
RunTest mesh_adv_random_order_workq adv_tx_random_order adv_rx_random_order

overlay=overlay_psa_conf
RunTest mesh_adv_random_order_psa adv_tx_random_order adv_rx_random_order
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh
# test buffer management by filling all the buffer and sending them in reversed order.
RunTest mesh_adv_reverse_order adv_tx_reverse_order adv_rx_receive_order

overlay=overlay_workq_sys_conf
RunTest mesh_adv_reverse_order_workq adv_tx_reverse_order adv_rx_receive_order

overlay=overlay_psa_conf
RunTest mesh_adv_reverse_order_psa adv_tx_reverse_order adv_rx_receive_order
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh
# test buffer management by filling all the buffer and sending them all in order.
RunTest mesh_adv_send_order adv_tx_send_order adv_rx_receive_order

overlay=overlay_workq_sys_conf
RunTest mesh_adv_send_order_workq adv_tx_send_order adv_rx_receive_order

overlay=overlay_psa_conf
RunTest mesh_adv_send_order_psa adv_tx_send_order adv_rx_receive_order
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh
# test tx callbacks sequence for multiple advs
RunTest mesh_adv_tx_cb_multi adv_tx_cb_multi

overlay=overlay_workq_sys_conf
RunTest mesh_adv_tx_cb_multi_workq adv_tx_cb_multi

overlay=overlay_psa_conf
RunTest mesh_adv_tx_cb_multi_psa adv_tx_cb_multi
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh
# test tx callbacks parameters and xmit sequence for single adv
RunTest mesh_adv_tx_cb_single adv_tx_cb_single adv_rx_xmit

overlay=overlay_workq_sys_conf
RunTest mesh_adv_tx_cb_single_workq adv_tx_cb_single adv_rx_xmit

overlay=overlay_psa_conf
RunTest mesh_adv_tx_cb_single_psa adv_tx_cb_single adv_rx_xmit
12 changes: 12 additions & 0 deletions tests/bsim/bluetooth/mesh/tests_scripts/proxy_sol/sol_replay.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ RunTest mesh_srpl_replay_attack \
proxy_sol_iut_power_replay_attack \
-flash=../results/mesh_srpl_replay_attack/flash.bin -flash_rm

overlay="overlay_pst_conf_overlay_gatt_conf_overlay_workq_sys_conf"
RunTest mesh_srpl_replay_attack_workq \
proxy_sol_tester_immediate_replay_attack \
proxy_sol_iut_immediate_replay_attack \
-flash=../results/mesh_srpl_replay_attack/flash.bin -flash_erase

overlay="overlay_pst_conf_overlay_gatt_conf_overlay_workq_sys_conf"
RunTest mesh_srpl_replay_attack_workq \
proxy_sol_tester_power_replay_attack \
proxy_sol_iut_power_replay_attack \
-flash=../results/mesh_srpl_replay_attack/flash.bin -flash_rm

overlay="overlay_pst_conf_overlay_gatt_conf_overlay_psa_conf"
RunTest mesh_srpl_replay_attack_psa \
proxy_sol_tester_immediate_replay_attack \
Expand Down
Loading