ble_mesh: Fix adv buf unref and link_id in exceptional list
This commit is contained in:
parent
4100f2e84f
commit
c354b0993d
7 changed files with 57 additions and 38 deletions
|
@ -142,6 +142,8 @@ static inline int adv_send(struct net_buf *buf)
|
||||||
param.interval_min = ADV_SCAN_UNIT(adv_int);
|
param.interval_min = ADV_SCAN_UNIT(adv_int);
|
||||||
param.interval_max = param.interval_min;
|
param.interval_max = param.interval_min;
|
||||||
|
|
||||||
|
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||||
|
|
||||||
err = bt_le_adv_start(¶m, &ad, 1, NULL, 0);
|
err = bt_le_adv_start(¶m, &ad, 1, NULL, 0);
|
||||||
net_buf_unref(buf);
|
net_buf_unref(buf);
|
||||||
adv_send_start(duration, err, cb, cb_data);
|
adv_send_start(duration, err, cb, cb_data);
|
||||||
|
@ -273,6 +275,7 @@ static void adv_thread(void *p)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
bt_mesh_adv_buf_ref_debug(__func__, *buf, 1U, BLE_MESH_BUF_REF_EQUAL);
|
||||||
net_buf_unref(*buf);
|
net_buf_unref(*buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,6 +323,30 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
|
||||||
xmit, timeout);
|
xmit, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf,
|
||||||
|
u8_t ref_cmp, bt_mesh_buf_ref_flag_t flag)
|
||||||
|
{
|
||||||
|
if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) {
|
||||||
|
BT_ERR("%s, Invalid parameter", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (flag) {
|
||||||
|
case BLE_MESH_BUF_REF_EQUAL:
|
||||||
|
if (buf->ref != ref_cmp) {
|
||||||
|
BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BLE_MESH_BUF_REF_SMALL:
|
||||||
|
if (buf->ref >= ref_cmp) {
|
||||||
|
BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void bt_mesh_unref_buf(bt_mesh_msg_t *msg)
|
static void bt_mesh_unref_buf(bt_mesh_msg_t *msg)
|
||||||
{
|
{
|
||||||
struct net_buf *buf;
|
struct net_buf *buf;
|
||||||
|
@ -356,6 +383,8 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
|
||||||
BLE_MESH_ADV(buf)->cb_data = cb_data;
|
BLE_MESH_ADV(buf)->cb_data = cb_data;
|
||||||
BLE_MESH_ADV(buf)->busy = 1U;
|
BLE_MESH_ADV(buf)->busy = 1U;
|
||||||
|
|
||||||
|
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||||
|
|
||||||
msg.arg = (void *)net_buf_ref(buf);
|
msg.arg = (void *)net_buf_ref(buf);
|
||||||
bt_mesh_task_post(&msg, portMAX_DELAY);
|
bt_mesh_task_post(&msg, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,15 @@ typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
|
||||||
struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
|
struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
|
||||||
s32_t timeout);
|
s32_t timeout);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BLE_MESH_BUF_REF_EQUAL,
|
||||||
|
BLE_MESH_BUF_REF_SMALL,
|
||||||
|
BLE_MESH_BUF_REF_MAX,
|
||||||
|
} bt_mesh_buf_ref_flag_t;
|
||||||
|
|
||||||
|
void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf,
|
||||||
|
u8_t ref_cmp, bt_mesh_buf_ref_flag_t flag);
|
||||||
|
|
||||||
struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
|
struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
|
||||||
bt_mesh_adv_alloc_t get_id,
|
bt_mesh_adv_alloc_t get_id,
|
||||||
enum bt_mesh_adv_type type,
|
enum bt_mesh_adv_type type,
|
||||||
|
|
|
@ -1894,7 +1894,7 @@ int bt_mesh_update_exceptional_list(u8_t sub_code, u8_t type, void *info)
|
||||||
BT_ERR("%s, NULL Provisioning Link ID", __func__);
|
BT_ERR("%s, NULL Provisioning Link ID", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
memcpy(value, info, sizeof(u32_t));
|
sys_memcpy_swap(value, info, sizeof(u32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
BT_DBG("%s, %s type 0x%x", __func__, sub_code ? "Remove" : "Add", type);
|
BT_DBG("%s, %s type 0x%x", __func__, sub_code ? "Remove" : "Add", type);
|
||||||
|
|
|
@ -168,7 +168,10 @@ static void friend_clear(struct bt_mesh_friend *frnd, u8_t reason)
|
||||||
if (frnd->last) {
|
if (frnd->last) {
|
||||||
/* Cancel the sending if necessary */
|
/* Cancel the sending if necessary */
|
||||||
if (frnd->pending_buf) {
|
if (frnd->pending_buf) {
|
||||||
|
bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 2U, BLE_MESH_BUF_REF_EQUAL);
|
||||||
BLE_MESH_ADV(frnd->last)->busy = 0U;
|
BLE_MESH_ADV(frnd->last)->busy = 0U;
|
||||||
|
} else {
|
||||||
|
bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 1U, BLE_MESH_BUF_REF_EQUAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
net_buf_unref(frnd->last);
|
net_buf_unref(frnd->last);
|
||||||
|
|
|
@ -260,14 +260,9 @@ static void free_segments(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
link.tx.buf[i] = NULL;
|
link.tx.buf[i] = NULL;
|
||||||
|
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||||
/* Mark as canceled */
|
/* Mark as canceled */
|
||||||
BLE_MESH_ADV(buf)->busy = 0U;
|
BLE_MESH_ADV(buf)->busy = 0U;
|
||||||
/** Changed by Espressif. Add this to avoid buf->ref is 2 which will
|
|
||||||
* cause lack of buf.
|
|
||||||
*/
|
|
||||||
if (buf->ref > 1) {
|
|
||||||
buf->ref = 1;
|
|
||||||
}
|
|
||||||
net_buf_unref(buf);
|
net_buf_unref(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1311,7 +1306,7 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf)
|
||||||
BT_DBG("Resending link ack");
|
BT_DBG("Resending link ack");
|
||||||
bearer_ctl_send(LINK_ACK, NULL, 0);
|
bearer_ctl_send(LINK_ACK, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
BT_WARN("Ignoring bearer open: link already active");
|
BT_INFO("Ignoring bearer open: link already active");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1436,19 +1431,11 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
|
||||||
BT_DBG("len %u, seg_index %u", buf->len, seg);
|
BT_DBG("len %u, seg_index %u", buf->len, seg);
|
||||||
|
|
||||||
if (!link.rx.seg && link.rx.prev_id == rx->xact_id) {
|
if (!link.rx.seg && link.rx.prev_id == rx->xact_id) {
|
||||||
BT_WARN("Resending ack");
|
BT_INFO("Resending ack");
|
||||||
gen_prov_ack_send(rx->xact_id);
|
gen_prov_ack_send(rx->xact_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An issue here:
|
|
||||||
* If the Transaction Start PDU is lost and the device receives corresponding
|
|
||||||
* Transaction Continuation PDU fist, this will trigger the following error -
|
|
||||||
* handling code to be executed and the device must wait for the timeout of
|
|
||||||
* PB-ADV provisioning procedure. Then another provisioning procedure can be
|
|
||||||
* started (link.rx.id will be reset after each provisioning PDU is received
|
|
||||||
* completely). This issue also exists in Provisioner.
|
|
||||||
*/
|
|
||||||
if (rx->xact_id != link.rx.id) {
|
if (rx->xact_id != link.rx.id) {
|
||||||
BT_WARN("Data for unknown transaction (%u != %u)",
|
BT_WARN("Data for unknown transaction (%u != %u)",
|
||||||
rx->xact_id, link.rx.id);
|
rx->xact_id, link.rx.id);
|
||||||
|
@ -1473,7 +1460,7 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(link.rx.seg & BIT(seg))) {
|
if (!(link.rx.seg & BIT(seg))) {
|
||||||
BT_WARN("Ignoring already received segment");
|
BT_INFO("Ignoring already received segment");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1501,12 +1488,12 @@ static void gen_prov_ack(struct prov_rx *rx, struct net_buf_simple *buf)
|
||||||
static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
|
static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
if (link.rx.seg) {
|
if (link.rx.seg) {
|
||||||
BT_WARN("Got Start while there are unreceived segments");
|
BT_INFO("Got Start while there are unreceived segments");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link.rx.prev_id == rx->xact_id) {
|
if (link.rx.prev_id == rx->xact_id) {
|
||||||
BT_WARN("Resending ack");
|
BT_INFO("Resending ack");
|
||||||
gen_prov_ack_send(rx->xact_id);
|
gen_prov_ack_send(rx->xact_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1096,14 +1096,9 @@ static void free_segments(const u8_t idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
link[idx].tx.buf[i] = NULL;
|
link[idx].tx.buf[i] = NULL;
|
||||||
|
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||||
/* Mark as canceled */
|
/* Mark as canceled */
|
||||||
BLE_MESH_ADV(buf)->busy = 0;
|
BLE_MESH_ADV(buf)->busy = 0U;
|
||||||
/** Change by Espressif. Add this to avoid buf->ref is 2 which will
|
|
||||||
* cause lack of buf.
|
|
||||||
*/
|
|
||||||
if (buf->ref > 1) {
|
|
||||||
buf->ref = 1;
|
|
||||||
}
|
|
||||||
net_buf_unref(buf);
|
net_buf_unref(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2550,7 +2545,7 @@ static void link_ack(const u8_t idx, struct prov_rx *rx, struct net_buf_simple *
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link[idx].expect == PROV_CAPABILITIES) {
|
if (link[idx].expect == PROV_CAPABILITIES) {
|
||||||
BT_WARN("%s, Link ACK is already received", __func__);
|
BT_INFO("%s, Link ACK is already received", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2652,7 +2647,7 @@ static void gen_prov_cont(const u8_t idx, struct prov_rx *rx, struct net_buf_sim
|
||||||
BT_DBG("len %u, seg_index %u", buf->len, seg);
|
BT_DBG("len %u, seg_index %u", buf->len, seg);
|
||||||
|
|
||||||
if (!link[idx].rx.seg && link[idx].rx.prev_id == rx->xact_id) {
|
if (!link[idx].rx.seg && link[idx].rx.prev_id == rx->xact_id) {
|
||||||
BT_WARN("%s, Resending ack", __func__);
|
BT_INFO("%s, Resending ack", __func__);
|
||||||
gen_prov_ack_send(idx, rx->xact_id);
|
gen_prov_ack_send(idx, rx->xact_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2683,7 +2678,7 @@ static void gen_prov_cont(const u8_t idx, struct prov_rx *rx, struct net_buf_sim
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(link[idx].rx.seg & BIT(seg))) {
|
if (!(link[idx].rx.seg & BIT(seg))) {
|
||||||
BT_WARN("%s, Ignore already received segment", __func__);
|
BT_INFO("%s, Ignore already received segment", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2736,12 +2731,12 @@ static void gen_prov_ack(const u8_t idx, struct prov_rx *rx, struct net_buf_simp
|
||||||
static void gen_prov_start(const u8_t idx, struct prov_rx *rx, struct net_buf_simple *buf)
|
static void gen_prov_start(const u8_t idx, struct prov_rx *rx, struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
if (link[idx].rx.seg) {
|
if (link[idx].rx.seg) {
|
||||||
BT_WARN("%s, Get Start while there are unreceived segments", __func__);
|
BT_INFO("%s, Get Start while there are unreceived segments", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link[idx].rx.prev_id == rx->xact_id) {
|
if (link[idx].rx.prev_id == rx->xact_id) {
|
||||||
BT_WARN("%s, Resending ack", __func__);
|
BT_INFO("%s, Resending ack", __func__);
|
||||||
gen_prov_ack_send(idx, rx->xact_id);
|
gen_prov_ack_send(idx, rx->xact_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,12 +205,8 @@ static void seg_tx_reset(struct seg_tx *tx)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Change by Espressif. Add this to avoid buf->ref is 2 which will
|
bt_mesh_adv_buf_ref_debug(__func__, tx->seg[i], 3U, BLE_MESH_BUF_REF_SMALL);
|
||||||
* cause lack of buf.
|
BLE_MESH_ADV(tx->seg[i])->busy = 0U;
|
||||||
*/
|
|
||||||
if (tx->seg[i]->ref > 1) {
|
|
||||||
tx->seg[i]->ref = 1;
|
|
||||||
}
|
|
||||||
net_buf_unref(tx->seg[i]);
|
net_buf_unref(tx->seg[i]);
|
||||||
tx->seg[i] = NULL;
|
tx->seg[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue