Explorar o código

Merge branch 'bugfix/fix_ble_mesh_adv_buf_unref_v4.0' into 'release/v4.0'

ble_mesh: Fix adv buf unref and link_id in exceptional list (v4.0)

See merge request espressif/esp-idf!7080
Jiang Jiang Jian %!s(int64=6) %!d(string=hai) anos
pai
achega
d41c020649

+ 32 - 3
components/bt/esp_ble_mesh/mesh_core/adv.c

@@ -142,6 +142,8 @@ static inline int adv_send(struct net_buf *buf)
     param.interval_min = ADV_SCAN_UNIT(adv_int);
     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(&param, &ad, 1, NULL, 0);
     net_buf_unref(buf);
     adv_send_start(duration, err, cb, cb_data);
@@ -273,6 +275,7 @@ static void adv_thread(void *p)
             }
 #endif
         } else {
+            bt_mesh_adv_buf_ref_debug(__func__, *buf, 1U, BLE_MESH_BUF_REF_EQUAL);
             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);
 }
 
+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)
 {
     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)->busy = 1U;
 
+    bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
+
     msg.arg = (void *)net_buf_ref(buf);
     bt_mesh_task_post(&msg, portMAX_DELAY);
 }
@@ -472,7 +501,7 @@ const bt_mesh_addr_t *bt_mesh_pba_get_addr(void)
     return dev_addr;
 }
 
-#if (CONFIG_BLE_MESH_PROVISIONER && COFNIG_BLE_MESH_PB_GATT) || \
+#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
     CONFIG_BLE_MESH_GATT_PROXY_CLIENT
 static bool bt_mesh_is_adv_flags_valid(struct net_buf_simple *buf)
 {
@@ -575,7 +604,7 @@ static void bt_mesh_adv_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_
 static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi,
                             u8_t adv_type, struct net_buf_simple *buf)
 {
-#if (CONFIG_BLE_MESH_PROVISIONER && COFNIG_BLE_MESH_PB_GATT) || \
+#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
     CONFIG_BLE_MESH_GATT_PROXY_CLIENT
     u16_t uuid;
 #endif
@@ -649,7 +678,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi,
             }
 #endif
             break;
-#if (CONFIG_BLE_MESH_PROVISIONER && COFNIG_BLE_MESH_PB_GATT) || \
+#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
     CONFIG_BLE_MESH_GATT_PROXY_CLIENT
         case BLE_MESH_DATA_FLAGS:
             if (!bt_mesh_is_adv_flags_valid(buf)) {

+ 9 - 0
components/bt/esp_ble_mesh/mesh_core/adv.h

@@ -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,
                                    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,
         bt_mesh_adv_alloc_t get_id,
         enum bt_mesh_adv_type type,

+ 1 - 1
components/bt/esp_ble_mesh/mesh_core/bluedroid_host/mesh_bearer_adapt.c

@@ -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__);
             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);

+ 3 - 0
components/bt/esp_ble_mesh/mesh_core/friend.c

@@ -168,7 +168,10 @@ static void friend_clear(struct bt_mesh_friend *frnd, u8_t reason)
     if (frnd->last) {
         /* Cancel the sending if necessary */
         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;
+        } else {
+            bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 1U, BLE_MESH_BUF_REF_EQUAL);
         }
 
         net_buf_unref(frnd->last);

+ 6 - 19
components/bt/esp_ble_mesh/mesh_core/prov.c

@@ -260,14 +260,9 @@ static void free_segments(void)
         }
 
         link.tx.buf[i] = NULL;
+        bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
         /* Mark as canceled */
         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);
     }
 }
@@ -1311,7 +1306,7 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf)
             BT_DBG("Resending link ack");
             bearer_ctl_send(LINK_ACK, NULL, 0);
         } else {
-            BT_WARN("Ignoring bearer open: link already active");
+            BT_INFO("Ignoring bearer open: link already active");
         }
 
         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);
 
     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);
         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) {
         BT_WARN("Data for unknown transaction (%u != %u)",
                 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))) {
-        BT_WARN("Ignoring already received segment");
+        BT_INFO("Ignoring already received segment");
         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)
 {
     if (link.rx.seg) {
-        BT_WARN("Got Start while there are unreceived segments");
+        BT_INFO("Got Start while there are unreceived segments");
         return;
     }
 
     if (link.rx.prev_id == rx->xact_id) {
-        BT_WARN("Resending ack");
+        BT_INFO("Resending ack");
         gen_prov_ack_send(rx->xact_id);
         return;
     }

+ 7 - 12
components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c

@@ -1096,14 +1096,9 @@ static void free_segments(const u8_t idx)
         }
 
         link[idx].tx.buf[i] = NULL;
+        bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
         /* Mark as canceled */
-        BLE_MESH_ADV(buf)->busy = 0;
-        /** Change by Espressif. Add this to avoid buf->ref is 2 which will
-         *  cause lack of buf.
-         */
-        if (buf->ref > 1) {
-            buf->ref = 1;
-        }
+        BLE_MESH_ADV(buf)->busy = 0U;
         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) {
-        BT_WARN("%s, Link ACK is already received", __func__);
+        BT_INFO("%s, Link ACK is already received", __func__);
         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);
 
     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);
         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))) {
-        BT_WARN("%s, Ignore already received segment", __func__);
+        BT_INFO("%s, Ignore already received segment", __func__);
         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)
 {
     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;
     }
 
     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);
         return;
     }

+ 2 - 6
components/bt/esp_ble_mesh/mesh_core/transport.c

@@ -205,12 +205,8 @@ static void seg_tx_reset(struct seg_tx *tx)
             continue;
         }
 
-        /** Change by Espressif. Add this to avoid buf->ref is 2 which will
-         *  cause lack of buf.
-         */
-        if (tx->seg[i]->ref > 1) {
-            tx->seg[i]->ref = 1;
-        }
+        bt_mesh_adv_buf_ref_debug(__func__, tx->seg[i], 3U, BLE_MESH_BUF_REF_SMALL);
+        BLE_MESH_ADV(tx->seg[i])->busy = 0U;
         net_buf_unref(tx->seg[i]);
         tx->seg[i] = NULL;
     }