fix(ble_mesh): avoid ble_mesh packet collision by using random adv interval

This commit is contained in:
Wu Meng Shi 2023-12-06 11:06:38 +08:00 committed by Island
parent 96f49c2603
commit a93783ae90
5 changed files with 58 additions and 7 deletions

View File

@ -6,6 +6,15 @@ if BLE_MESH
help
It is a temporary solution and needs further modifications.
config BLE_MESH_RANDOM_ADV_INTERVAL
bool "Support using random adv interval for mesh packets"
select BT_BLE_HIGH_DUTY_ADV_INTERVAL if BT_BLUEDROID_ENABLED
default n
help
Enable this option to allow using random advertising interval
for mesh packets. And this could help avoid collision of
advertising packets.
config BLE_MESH_USE_DUPLICATE_SCAN
bool "Support Duplicate Scan in BLE Mesh"
select BTDM_BLE_SCAN_DUPL if IDF_TARGET_ESP32

View File

@ -85,3 +85,8 @@ int bt_mesh_rand(void *buf, size_t len)
return 0;
}
uint32_t bt_mesh_get_rand(void)
{
return esp_random();
}

View File

@ -53,6 +53,8 @@ void bt_mesh_free_buf(struct net_buf_simple *buf);
int bt_mesh_rand(void *buf, size_t len);
uint32_t bt_mesh_get_rand(void);
#ifdef __cplusplus
}
#endif

View File

@ -324,6 +324,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
tBLE_ADDR_TYPE addr_type_own = 0U;
tBLE_BD_ADDR p_dir_bda = {0};
tBTM_BLE_AFP adv_fil_pol = 0U;
uint16_t interval = 0U;
uint8_t adv_type = 0U;
int err = 0;
@ -387,9 +388,24 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
adv_fil_pol = BLE_MESH_AP_SCAN_CONN_ALL;
p_start_adv_cb = start_adv_completed_cb;
interval = param->interval_min;
#if CONFIG_BLE_MESH_RANDOM_ADV_INTERVAL
/* If non-connectable mesh packets are transmitted with an adv interval
* not smaller than 10ms, then we will use a random adv interval between
* [interval / 2, interval] for them.
*/
if (adv_type == BLE_MESH_ADV_NONCONN_IND && interval >= 16) {
interval >>= 1;
interval += (bt_mesh_get_rand() % (interval + 1));
BT_INFO("%u->%u", param->interval_min, interval);
}
#endif
/* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */
BLE_MESH_BTM_CHECK_STATUS(
BTM_BleSetAdvParamsAll(param->interval_min, param->interval_max, adv_type,
BTM_BleSetAdvParamsAll(interval, interval, adv_type,
addr_type_own, &p_dir_bda,
channel_map, adv_fil_pol, p_start_adv_cb));
BLE_MESH_BTM_CHECK_STATUS(BTM_BleStartAdv());

View File

@ -758,15 +758,17 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *ad, size_t ad_len,
const struct bt_mesh_adv_data *sd, size_t sd_len)
{
struct ble_gap_adv_params adv_params;
uint8_t buf[BLE_HS_ADV_MAX_SZ];
uint16_t interval = 0;
uint8_t buf_len = 0;
int err;
#if BLE_MESH_DEV
if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) {
return -EALREADY;
}
#endif
uint8_t buf[BLE_HS_ADV_MAX_SZ];
uint8_t buf_len = 0;
int err;
struct ble_gap_adv_params adv_params;
err = set_ad(ad, ad_len, buf, &buf_len);
if (err) {
@ -797,8 +799,6 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
}
memset(&adv_params, 0, sizeof adv_params);
adv_params.itvl_min = param->interval_min;
adv_params.itvl_max = param->interval_max;
if (param->options & BLE_MESH_ADV_OPT_CONNECTABLE) {
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
@ -811,6 +811,25 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
adv_params.disc_mode = BLE_GAP_DISC_MODE_NON;
}
interval = param->interval_min;
#if CONFIG_BLE_MESH_RANDOM_ADV_INTERVAL
/* If non-connectable mesh packets are transmitted with an adv interval
* not smaller than 10ms, then we will use a random adv interval between
* [interval / 2, interval] for them.
*/
if (adv_params.conn_mode == BLE_GAP_CONN_MODE_NON &&
adv_params.disc_mode == BLE_GAP_DISC_MODE_NON && interval >= 16) {
interval >>= 1;
interval += (bt_mesh_get_rand() % (interval + 1));
BT_INFO("%u->%u", param->interval_min, interval);
}
#endif
adv_params.itvl_min = interval;
adv_params.itvl_max = interval;
again:
err = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params,
gap_event_cb, NULL);