Merge branch 'fix/ble_mesh_micellaneous_fix' into 'master'

Fix/ble mesh micellaneous fix

Closes BLERP-2023 and BLERP-2024

See merge request espressif/esp-idf!40078
This commit is contained in:
Island
2025-07-29 14:29:53 +08:00
3 changed files with 45 additions and 22 deletions

View File

@@ -2,7 +2,7 @@
/* /*
* SPDX-FileCopyrightText: 2017 Intel Corporation * SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -34,6 +34,8 @@ struct bt_mesh_adv_queue relay_adv_queue;
#endif #endif
static bt_mesh_mutex_t adv_buf_alloc_lock;
#if CONFIG_BLE_MESH_FRIEND #if CONFIG_BLE_MESH_FRIEND
/* We reserve one extra buffer for each friendship, since we need to be able /* We reserve one extra buffer for each friendship, since we need to be able
* to resend the last sent PDU, which sits separately outside of the queue. * to resend the last sent PDU, which sits separately outside of the queue.
@@ -344,8 +346,10 @@ struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type,
return NULL; return NULL;
} }
bt_mesh_r_mutex_lock(&adv_buf_alloc_lock);
buf = net_buf_alloc(pool, timeout); buf = net_buf_alloc(pool, timeout);
if (!buf) { if (!buf) {
bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock);
BT_WARN("Buf alloc failed"); BT_WARN("Buf alloc failed");
return NULL; return NULL;
} }
@@ -359,7 +363,7 @@ struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type,
(void)memset(adv, 0, sizeof(*adv)); (void)memset(adv, 0, sizeof(*adv));
adv->type = type; adv->type = type;
bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock);
return buf; return buf;
} }
@@ -620,6 +624,7 @@ void bt_mesh_adv_task_init(void adv_thread(void *p))
void bt_mesh_adv_common_init(void) void bt_mesh_adv_common_init(void)
{ {
bt_mesh_r_mutex_create(&adv_buf_alloc_lock);
bt_mesh_adv_queue_init(&adv_queue, BLE_MESH_ADV_QUEUE_SIZE, bt_mesh_task_post); bt_mesh_adv_queue_init(&adv_queue, BLE_MESH_ADV_QUEUE_SIZE, bt_mesh_task_post);
bt_mesh_adv_type_init(BLE_MESH_ADV_PROV, &adv_queue, &adv_buf_pool, adv_alloc); bt_mesh_adv_type_init(BLE_MESH_ADV_PROV, &adv_queue, &adv_buf_pool, adv_alloc);
bt_mesh_adv_type_init(BLE_MESH_ADV_DATA, &adv_queue, &adv_buf_pool, adv_alloc); bt_mesh_adv_type_init(BLE_MESH_ADV_DATA, &adv_queue, &adv_buf_pool, adv_alloc);
@@ -679,5 +684,6 @@ void bt_mesh_adv_common_deinit(void)
bt_mesh_unref_buf_from_pool(&adv_buf_pool); bt_mesh_unref_buf_from_pool(&adv_buf_pool);
memset(adv_pool, 0, sizeof(adv_pool)); memset(adv_pool, 0, sizeof(adv_pool));
bt_mesh_r_mutex_free(&adv_buf_alloc_lock);
} }
#endif /* CONFIG_BLE_MESH_DEINIT */ #endif /* CONFIG_BLE_MESH_DEINIT */

View File

@@ -369,6 +369,10 @@ static void adv_thread(void *p)
continue; continue;
} }
if (recv_evts & ADV_TASK_PKT_SEND_EVT) {
recv_evts &= ~ADV_TASK_PKT_SEND_EVT;
}
recv_evts = received_adv_evts_handle(recv_evts); recv_evts = received_adv_evts_handle(recv_evts);
if (recv_evts) { if (recv_evts) {

View File

@@ -94,6 +94,7 @@ static struct seg_tx {
const struct bt_mesh_send_cb *cb; const struct bt_mesh_send_cb *cb;
void *cb_data; void *cb_data;
struct k_delayed_work rtx_timer; /* Segment Retransmission timer */ struct k_delayed_work rtx_timer; /* Segment Retransmission timer */
bt_mesh_mutex_t lock;
} seg_tx[CONFIG_BLE_MESH_TX_SEG_MSG_COUNT]; } seg_tx[CONFIG_BLE_MESH_TX_SEG_MSG_COUNT];
static struct seg_rx { static struct seg_rx {
@@ -120,17 +121,16 @@ static struct seg_rx {
static uint8_t seg_rx_buf_data[(CONFIG_BLE_MESH_RX_SEG_MSG_COUNT * static uint8_t seg_rx_buf_data[(CONFIG_BLE_MESH_RX_SEG_MSG_COUNT *
CONFIG_BLE_MESH_RX_SDU_MAX)]; CONFIG_BLE_MESH_RX_SDU_MAX)];
static bt_mesh_mutex_t seg_tx_lock;
static bt_mesh_mutex_t seg_rx_lock; static bt_mesh_mutex_t seg_rx_lock;
static inline void bt_mesh_seg_tx_lock(void) static inline void bt_mesh_seg_tx_lock(struct seg_tx *tx)
{ {
bt_mesh_mutex_lock(&seg_tx_lock); bt_mesh_r_mutex_lock(&tx->lock);
} }
static inline void bt_mesh_seg_tx_unlock(void) static inline void bt_mesh_seg_tx_unlock(struct seg_tx *tx)
{ {
bt_mesh_mutex_unlock(&seg_tx_lock); bt_mesh_r_mutex_unlock(&tx->lock);
} }
static inline void bt_mesh_seg_rx_lock(void) static inline void bt_mesh_seg_rx_lock(void)
@@ -331,7 +331,7 @@ static void seg_tx_reset(struct seg_tx *tx)
{ {
int i; int i;
bt_mesh_seg_tx_lock(); bt_mesh_seg_tx_lock(tx);
k_delayed_work_cancel(&tx->rtx_timer); k_delayed_work_cancel(&tx->rtx_timer);
@@ -351,7 +351,7 @@ static void seg_tx_reset(struct seg_tx *tx)
tx->nack_count = 0U; tx->nack_count = 0U;
bt_mesh_seg_tx_unlock(); bt_mesh_seg_tx_unlock(tx);
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_IVU_PENDING)) { if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_IVU_PENDING)) {
BT_DBG("Proceeding with pending IV Update"); BT_DBG("Proceeding with pending IV Update");
@@ -380,6 +380,7 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err)
static void schedule_retransmit(struct seg_tx *tx) static void schedule_retransmit(struct seg_tx *tx)
{ {
bt_mesh_seg_tx_lock(tx);
/* It's possible that a segment broadcast hasn't finished, /* It's possible that a segment broadcast hasn't finished,
* but the tx are already released. Only the seg_pending * but the tx are already released. Only the seg_pending
* of this segment remains unprocessed. So, here, we * of this segment remains unprocessed. So, here, we
@@ -391,20 +392,24 @@ static void schedule_retransmit(struct seg_tx *tx)
if (tx->seg_pending) { if (tx->seg_pending) {
tx->seg_pending--; tx->seg_pending--;
} }
bt_mesh_seg_tx_unlock(tx);
return; return;
} }
if (--tx->seg_pending) { if (--tx->seg_pending) {
bt_mesh_seg_tx_unlock(tx);
return; return;
} }
if (!BLE_MESH_ADDR_IS_UNICAST(tx->dst) && !tx->attempts) { if (!BLE_MESH_ADDR_IS_UNICAST(tx->dst) && !tx->attempts) {
BT_INFO("Complete tx sdu to group"); BT_INFO("Complete tx sdu to group");
seg_tx_complete(tx, 0); seg_tx_complete(tx, 0);
bt_mesh_seg_tx_unlock(tx);
return; return;
} }
k_delayed_work_submit(&tx->rtx_timer, SEG_RETRANSMIT_TIMEOUT(tx)); k_delayed_work_submit(&tx->rtx_timer, SEG_RETRANSMIT_TIMEOUT(tx));
bt_mesh_seg_tx_unlock(tx);
} }
static void seg_first_send_start(uint16_t duration, int err, void *user_data) static void seg_first_send_start(uint16_t duration, int err, void *user_data)
@@ -450,11 +455,11 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
{ {
int i, err = 0; int i, err = 0;
bt_mesh_seg_tx_lock(); bt_mesh_seg_tx_lock(tx);
if (!(tx->attempts--)) { if (!(tx->attempts--)) {
BT_WARN("Ran out of retransmit attempts"); BT_WARN("Ran out of retransmit attempts");
bt_mesh_seg_tx_unlock(); bt_mesh_seg_tx_unlock(tx);
seg_tx_complete(tx, -ETIMEDOUT); seg_tx_complete(tx, -ETIMEDOUT);
return; return;
} }
@@ -487,13 +492,13 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
&seg_sent_cb, tx); &seg_sent_cb, tx);
if (err) { if (err) {
BT_ERR("Sending segment failed"); BT_ERR("Sending segment failed");
bt_mesh_seg_tx_unlock(); bt_mesh_seg_tx_unlock(tx);
seg_tx_complete(tx, -EIO); seg_tx_complete(tx, -EIO);
return; return;
} }
} }
bt_mesh_seg_tx_unlock(); bt_mesh_seg_tx_unlock(tx);
} }
static void seg_retransmit(struct k_work *work) static void seg_retransmit(struct k_work *work)
@@ -511,6 +516,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
uint16_t seq_zero = 0U; uint16_t seq_zero = 0U;
uint8_t seg_hdr = 0U; uint8_t seg_hdr = 0U;
uint8_t seg_o = 0U; uint8_t seg_o = 0U;
int err = 0;
int i; int i;
BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u", BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u",
@@ -583,16 +589,17 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
return -ENOBUFS; return -ENOBUFS;
} }
bt_mesh_seg_tx_lock(tx);
for (seg_o = 0U; sdu->len; seg_o++) { for (seg_o = 0U; sdu->len; seg_o++) {
struct net_buf *seg = NULL; struct net_buf *seg = NULL;
uint16_t len = 0U; uint16_t len = 0U;
int err = 0;
seg = bt_mesh_adv_create(BLE_MESH_ADV_DATA, BUF_TIMEOUT); seg = bt_mesh_adv_create(BLE_MESH_ADV_DATA, BUF_TIMEOUT);
if (!seg) { if (!seg) {
BT_ERR("Out of segment buffers"); BT_ERR("Out of segment buffers");
seg_tx_reset(tx); err = -ENOBUFS;
return -ENOBUFS; break;
} }
net_buf_reserve(seg, BLE_MESH_NET_HDR_LEN); net_buf_reserve(seg, BLE_MESH_NET_HDR_LEN);
@@ -637,8 +644,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
tx); tx);
if (err) { if (err) {
BT_ERR("Sending segment failed (err %d)", err); BT_ERR("Sending segment failed (err %d)", err);
seg_tx_reset(tx); break;
return err;
} }
/* If security credentials is updated in the network layer, /* If security credentials is updated in the network layer,
@@ -650,6 +656,13 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
} }
} }
bt_mesh_seg_tx_unlock(tx);
if (err) {
seg_tx_reset(tx);
return err;
}
/* This can happen if segments only went into the Friend Queue */ /* This can happen if segments only went into the Friend Queue */
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !tx->seg[0]) { if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !tx->seg[0]) {
seg_tx_reset(tx); seg_tx_reset(tx);
@@ -984,9 +997,9 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
while ((bit = find_lsb_set(ack))) { while ((bit = find_lsb_set(ack))) {
if (tx->seg[bit - 1]) { if (tx->seg[bit - 1]) {
BT_INFO("Seg %u/%u acked", bit - 1, tx->seg_n); BT_INFO("Seg %u/%u acked", bit - 1, tx->seg_n);
bt_mesh_seg_tx_lock(); bt_mesh_seg_tx_lock(tx);
seg_tx_done(tx, bit - 1); seg_tx_done(tx, bit - 1);
bt_mesh_seg_tx_unlock(); bt_mesh_seg_tx_unlock(tx);
} }
ack &= ~BIT(bit - 1); ack &= ~BIT(bit - 1);
@@ -1786,6 +1799,7 @@ void bt_mesh_trans_init(void)
for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
k_delayed_work_init(&seg_tx[i].rtx_timer, seg_retransmit); k_delayed_work_init(&seg_tx[i].rtx_timer, seg_retransmit);
bt_mesh_r_mutex_create(&seg_tx[i].lock);
} }
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) { for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
@@ -1795,7 +1809,6 @@ void bt_mesh_trans_init(void)
seg_rx[i].buf.data = seg_rx[i].buf.__buf; seg_rx[i].buf.data = seg_rx[i].buf.__buf;
} }
bt_mesh_mutex_create(&seg_tx_lock);
bt_mesh_mutex_create(&seg_rx_lock); bt_mesh_mutex_create(&seg_rx_lock);
} }
@@ -1810,13 +1823,13 @@ void bt_mesh_trans_deinit(bool erase)
for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
k_delayed_work_free(&seg_tx[i].rtx_timer); k_delayed_work_free(&seg_tx[i].rtx_timer);
bt_mesh_r_mutex_free(&seg_tx[i].lock);
} }
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) { for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
k_delayed_work_free(&seg_rx[i].ack_timer); k_delayed_work_free(&seg_rx[i].ack_timer);
} }
bt_mesh_mutex_free(&seg_tx_lock);
bt_mesh_mutex_free(&seg_rx_lock); bt_mesh_mutex_free(&seg_rx_lock);
} }
#endif /* CONFIG_BLE_MESH_DEINIT */ #endif /* CONFIG_BLE_MESH_DEINIT */