feat(ble_mesh): Support Bluetooth Mesh SAR enhancement

This commit is contained in:
Liu Linyan
2023-11-02 16:25:41 +08:00
parent c628a94513
commit ff7639bcd6
15 changed files with 2430 additions and 36 deletions

View File

@@ -515,7 +515,6 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/core/rpl.c" "esp_ble_mesh/core/rpl.c"
"esp_ble_mesh/core/scan.c" "esp_ble_mesh/core/scan.c"
"esp_ble_mesh/core/test.c" "esp_ble_mesh/core/test.c"
"esp_ble_mesh/core/transport.c"
"esp_ble_mesh/models/common/device_property.c" "esp_ble_mesh/models/common/device_property.c"
"esp_ble_mesh/models/common/model_common.c" "esp_ble_mesh/models/common/model_common.c"
"esp_ble_mesh/models/client/client_common.c" "esp_ble_mesh/models/client/client_common.c"
@@ -552,6 +551,12 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c" "esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c" "esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c"
"esp_ble_mesh/v1.1/ext.c") "esp_ble_mesh/v1.1/ext.c")
if(CONFIG_BLE_MESH_SAR_ENHANCEMENT)
list(APPEND srcs "esp_ble_mesh/core/transport.enh.c")
else()
list(APPEND srcs "esp_ble_mesh/core/transport.c")
endif()
endif() endif()

View File

@@ -678,6 +678,13 @@ if BLE_MESH
When the above situation is encountered, this option can be used to decide whether When the above situation is encountered, this option can be used to decide whether
to perform the IV index recovery procedure. to perform the IV index recovery procedure.
config BLE_MESH_SAR_ENHANCEMENT
bool "Segmentation and reassembly enhancement"
default n
help
Enable this option to use the enhanced segmentation and reassembly
mechanism introduced in Bluetooth Mesh Protocol 1.1.
config BLE_MESH_TX_SEG_MSG_COUNT config BLE_MESH_TX_SEG_MSG_COUNT
int "Maximum number of simultaneous outgoing segmented messages" int "Maximum number of simultaneous outgoing segmented messages"
default 1 default 1

View File

@@ -32,8 +32,11 @@
/* Pre-5.0 controllers enforce a minimum interval of 100ms /* Pre-5.0 controllers enforce a minimum interval of 100ms
* whereas 5.0+ controllers can go down to 20ms. * whereas 5.0+ controllers can go down to 20ms.
*/ */
#define ADV_INT_DEFAULT_MS 100 #if CONFIG_BLE_MESH_HCI_5_0
#define ADV_INT_FAST_MS 20 #define ADV_ITVL_MIN 20
#else
#define ADV_ITVL_MIN 100
#endif
static const uint8_t adv_type[] = { static const uint8_t adv_type[] = {
[BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV,
@@ -141,10 +144,19 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
} }
} }
uint16_t bt_mesh_pdu_duration(uint8_t xmit)
{
uint16_t duration = 0U;
uint16_t adv_int = 0U;
adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit));
duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10);
return duration;
}
static inline int adv_send(struct net_buf *buf) static inline int adv_send(struct net_buf *buf)
{ {
const int32_t adv_int_min = ((bt_mesh_dev.hci_version >= BLE_MESH_HCI_VERSION_5_0) ?
ADV_INT_FAST_MS : ADV_INT_DEFAULT_MS);
const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb;
void *cb_data = BLE_MESH_ADV(buf)->cb_data; void *cb_data = BLE_MESH_ADV(buf)->cb_data;
struct bt_mesh_adv_param param = {0}; struct bt_mesh_adv_param param = {0};
@@ -158,7 +170,7 @@ static inline int adv_send(struct net_buf *buf)
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
if (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) { if (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) {
#endif #endif
adv_int = MAX(adv_int_min, adv_int = MAX(ADV_ITVL_MIN,
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit)); BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) * duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
(adv_int + 10); (adv_int + 10);

View File

@@ -25,6 +25,8 @@ extern "C" {
#define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf)) #define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf))
uint16_t bt_mesh_pdu_duration(uint8_t xmit);
typedef struct bt_mesh_msg { typedef struct bt_mesh_msg {
bool relay; /* Flag indicates if the packet is a relayed one */ bool relay; /* Flag indicates if the packet is a relayed one */
void *arg; /* Pointer to the struct net_buf */ void *arg; /* Pointer to the struct net_buf */

View File

@@ -90,7 +90,7 @@ static struct seg_tx {
uint8_t tag; /* Additional metadata */ uint8_t tag; /* Additional metadata */
const struct bt_mesh_send_cb *cb; const struct bt_mesh_send_cb *cb;
void *cb_data; void *cb_data;
struct k_delayed_work retransmit; /* Retransmit timer */ struct k_delayed_work rtx_timer; /* Segment Retransmission timer */
} 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 {
@@ -106,7 +106,7 @@ static struct seg_rx {
uint16_t dst; uint16_t dst;
uint32_t block; uint32_t block;
uint32_t last; uint32_t last;
struct k_delayed_work ack; struct k_delayed_work ack_timer;
struct net_buf_simple buf; struct net_buf_simple buf;
} seg_rx[CONFIG_BLE_MESH_RX_SEG_MSG_COUNT] = { } seg_rx[CONFIG_BLE_MESH_RX_SEG_MSG_COUNT] = {
[0 ... (CONFIG_BLE_MESH_RX_SEG_MSG_COUNT - 1)] = { [0 ... (CONFIG_BLE_MESH_RX_SEG_MSG_COUNT - 1)] = {
@@ -145,7 +145,7 @@ uint8_t bt_mesh_get_seg_rtx_num(void)
return SEG_RETRANSMIT_ATTEMPTS; return SEG_RETRANSMIT_ATTEMPTS;
} }
int32_t bt_mesh_get_seg_rtx_timeout(uint8_t ttl) int32_t bt_mesh_get_seg_rtx_timeout(uint16_t dst, uint8_t ttl)
{ {
/* This function will be used when a client model sending an /* This function will be used when a client model sending an
* acknowledged message. And if the dst of a message is not * acknowledged message. And if the dst of a message is not
@@ -322,7 +322,7 @@ static void seg_tx_reset(struct seg_tx *tx)
bt_mesh_seg_tx_lock(); bt_mesh_seg_tx_lock();
k_delayed_work_cancel(&tx->retransmit); k_delayed_work_cancel(&tx->rtx_timer);
tx->cb = NULL; tx->cb = NULL;
tx->cb_data = NULL; tx->cb_data = NULL;
@@ -360,6 +360,8 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err)
seg_tx_reset(tx); seg_tx_reset(tx);
/* TODO: notify the completion of sending segmented message */
if (cb && cb->end) { if (cb && cb->end) {
cb->end(err, cb_data); cb->end(err, cb_data);
} }
@@ -377,7 +379,7 @@ static void schedule_retransmit(struct seg_tx *tx)
return; return;
} }
k_delayed_work_submit(&tx->retransmit, SEG_RETRANSMIT_TIMEOUT(tx)); k_delayed_work_submit(&tx->rtx_timer, SEG_RETRANSMIT_TIMEOUT(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)
@@ -471,7 +473,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
static void seg_retransmit(struct k_work *work) static void seg_retransmit(struct k_work *work)
{ {
struct seg_tx *tx = CONTAINER_OF(work, struct seg_tx, retransmit); struct seg_tx *tx = CONTAINER_OF(work, struct seg_tx, rtx_timer);
seg_tx_send_unacked(tx); seg_tx_send_unacked(tx);
} }
@@ -511,10 +513,6 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
} }
tx->dst = net_tx->ctx->addr; tx->dst = net_tx->ctx->addr;
/* TODO:
* When SAR Transmitter is introduced, the xmit may be
* updated with "bt_mesh_get_sar_seg_transmit()".
*/
if (sdu->len) { if (sdu->len) {
tx->seg_n = (sdu->len - 1) / seg_len(!!ctl_op); tx->seg_n = (sdu->len - 1) / seg_len(!!ctl_op);
} else { } else {
@@ -784,6 +782,12 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr,
rx->ctl, rx->ctx.recv_ttl, rx->ctx.addr, rx->ctx.recv_dst, rx->ctl, rx->ctx.recv_ttl, rx->ctx.addr, rx->ctx.recv_dst,
bt_hex(sdu->data, sdu->len)); bt_hex(sdu->data, sdu->len));
/* When the Device Key Candidate is available, and an access message
* is decrypted using the Device Key Candidate that was delivered to
* the access layer, then the node shall revoke the device key, the
* Device Key Candidate shall become the device key, and the Device
* Key Candidate shall become unavailable.
*/
revoke_dev_key(dev_key); revoke_dev_key(dev_key);
rx->ctx.app_idx = BLE_MESH_KEY_DEV; rx->ctx.app_idx = BLE_MESH_KEY_DEV;
@@ -942,7 +946,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
return -EINVAL; return -EINVAL;
} }
k_delayed_work_cancel(&tx->retransmit); k_delayed_work_cancel(&tx->rtx_timer);
while ((bit = find_lsb_set(ack))) { while ((bit = find_lsb_set(ack))) {
if (tx->seg[bit - 1]) { if (tx->seg[bit - 1]) {
@@ -1216,11 +1220,9 @@ static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst,
static void seg_rx_reset(struct seg_rx *rx, bool full_reset) static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
{ {
BT_DBG("rx %p", rx);
bt_mesh_seg_rx_lock(); bt_mesh_seg_rx_lock();
k_delayed_work_cancel(&rx->ack); k_delayed_work_cancel(&rx->ack_timer);
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->obo && if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->obo &&
rx->block != BLOCK_COMPLETE(rx->seg_n)) { rx->block != BLOCK_COMPLETE(rx->seg_n)) {
@@ -1267,9 +1269,7 @@ static uint32_t incomplete_timeout(struct seg_rx *rx)
static void seg_ack(struct k_work *work) static void seg_ack(struct k_work *work)
{ {
struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack); struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack_timer);
BT_DBG("rx %p", rx);
bt_mesh_seg_rx_lock(); bt_mesh_seg_rx_lock();
@@ -1291,14 +1291,14 @@ static void seg_ack(struct k_work *work)
send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth, send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth,
rx->block, rx->obo); rx->block, rx->obo);
k_delayed_work_submit(&rx->ack, ack_timeout(rx)); k_delayed_work_submit(&rx->ack_timer, ack_timeout(rx));
bt_mesh_seg_rx_unlock(); bt_mesh_seg_rx_unlock();
} }
static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n) static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
{ {
return ((seg_n * seg_len(ctl) + 1) <= CONFIG_BLE_MESH_RX_SDU_MAX); return ((seg_n + 1) * seg_len(ctl) <= CONFIG_BLE_MESH_RX_SDU_MAX);
} }
static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx, static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
@@ -1568,9 +1568,9 @@ found_rx:
/* Reset the Incomplete Timer */ /* Reset the Incomplete Timer */
rx->last = k_uptime_get_32(); rx->last = k_uptime_get_32();
if (!k_delayed_work_remaining_get(&rx->ack) && if (!k_delayed_work_remaining_get(&rx->ack_timer) &&
!bt_mesh_lpn_established()) { !bt_mesh_lpn_established()) {
k_delayed_work_submit(&rx->ack, ack_timeout(rx)); k_delayed_work_submit(&rx->ack_timer, ack_timeout(rx));
} }
/* Location in buffer can be calculated based on seg_o & rx->ctl */ /* Location in buffer can be calculated based on seg_o & rx->ctl */
@@ -1594,7 +1594,7 @@ found_rx:
*pdu_type = BLE_MESH_FRIEND_PDU_COMPLETE; *pdu_type = BLE_MESH_FRIEND_PDU_COMPLETE;
k_delayed_work_cancel(&rx->ack); k_delayed_work_cancel(&rx->ack_timer);
send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo); net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
@@ -1754,11 +1754,11 @@ void bt_mesh_trans_init(void)
bt_mesh_sar_init(); bt_mesh_sar_init();
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].retransmit, seg_retransmit); k_delayed_work_init(&seg_tx[i].rtx_timer, seg_retransmit);
} }
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) { for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
k_delayed_work_init(&seg_rx[i].ack, seg_ack); k_delayed_work_init(&seg_rx[i].ack_timer, seg_ack);
seg_rx[i].buf.__buf = (seg_rx_buf_data + seg_rx[i].buf.__buf = (seg_rx_buf_data +
(i * CONFIG_BLE_MESH_RX_SDU_MAX)); (i * CONFIG_BLE_MESH_RX_SDU_MAX));
seg_rx[i].buf.data = seg_rx[i].buf.__buf; seg_rx[i].buf.data = seg_rx[i].buf.__buf;
@@ -1778,11 +1778,11 @@ void bt_mesh_trans_deinit(bool erase)
bt_mesh_rpl_reset(erase); bt_mesh_rpl_reset(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].retransmit); k_delayed_work_free(&seg_tx[i].rtx_timer);
} }
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); k_delayed_work_free(&seg_rx[i].ack_timer);
} }
bt_mesh_mutex_free(&seg_tx_lock); bt_mesh_mutex_free(&seg_tx_lock);

File diff suppressed because it is too large Load Diff

View File

@@ -96,7 +96,7 @@ struct bt_mesh_ctl_friend_sub_confirm {
uint8_t bt_mesh_get_seg_rtx_num(void); uint8_t bt_mesh_get_seg_rtx_num(void);
int32_t bt_mesh_get_seg_rtx_timeout(uint8_t ttl); int32_t bt_mesh_get_seg_rtx_timeout(uint16_t dst, uint8_t ttl);
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx); struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx);

View File

@@ -198,7 +198,7 @@ static int32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx,
* All the messages sent from here are access messages. * All the messages sent from here are access messages.
*/ */
seg_rtx_num = bt_mesh_get_seg_rtx_num(); seg_rtx_num = bt_mesh_get_seg_rtx_num();
seg_rtx_to = bt_mesh_get_seg_rtx_timeout(ctx->send_ttl); seg_rtx_to = bt_mesh_get_seg_rtx_timeout(ctx->addr, ctx->send_ttl);
seg_count = (msg->len + mic_size - 1) / 12U + 1U; seg_count = (msg->len + mic_size - 1) / 12U + 1U;
duration = bt_mesh_get_adv_duration(ctx); duration = bt_mesh_get_adv_duration(ctx);

View File

@@ -63,7 +63,7 @@ typedef struct {
sar_unicast_retrans_interval_step:4; /*!< SAR Unicast Retransmissions Interval Step state */ sar_unicast_retrans_interval_step:4; /*!< SAR Unicast Retransmissions Interval Step state */
uint8_t sar_unicast_retrans_interval_increment:4, /*!< SAR Unicast Retransmissions Interval Increment state */ uint8_t sar_unicast_retrans_interval_increment:4, /*!< SAR Unicast Retransmissions Interval Increment state */
sar_multicast_retrans_count:4; /*!< SAR Multicast Retransmissions Count state */ sar_multicast_retrans_count:4; /*!< SAR Multicast Retransmissions Count state */
uint8_t sar_multicast_retrans_interval:4; /*!< SAR Multicast Retransmissions Interval state */ uint8_t sar_multicast_retrans_interval_step:4; /*!< SAR Multicast Retransmissions Interval state */
} esp_ble_mesh_sar_transmitter_set_t; } esp_ble_mesh_sar_transmitter_set_t;
/** Parameters of SAR Receiver Set */ /** Parameters of SAR Receiver Set */
@@ -91,7 +91,7 @@ typedef struct {
sar_unicast_retrans_interval_step:4; /*!< SAR Unicast Retransmissions Interval Step state */ sar_unicast_retrans_interval_step:4; /*!< SAR Unicast Retransmissions Interval Step state */
uint8_t sar_unicast_retrans_interval_increment:4, /*!< SAR Unicast Retransmissions Interval Increment state */ uint8_t sar_unicast_retrans_interval_increment:4, /*!< SAR Unicast Retransmissions Interval Increment state */
sar_multicast_retrans_count:4; /*!< SAR Multicast Retransmissions Count state */ sar_multicast_retrans_count:4; /*!< SAR Multicast Retransmissions Count state */
uint8_t sar_multicast_retrans_interval:4; /*!< SAR Multicast Retransmissions Interval state */ uint8_t sar_multicast_retrans_interval_step:4; /*!< SAR Multicast Retransmissions Interval state */
} esp_ble_mesh_sar_transmitter_status_t; } esp_ble_mesh_sar_transmitter_status_t;
/** Parameters of SAR Receiver Status */ /** Parameters of SAR Receiver Status */

View File

@@ -248,6 +248,30 @@ uint8_t bt_mesh_net_retrans_match(void *rx, uint8_t *cred, uint8_t *tag);
bool bt_mesh_dev_key_ca_valid(void); bool bt_mesh_dev_key_ca_valid(void);
uint8_t bt_mesh_get_sar_sis(void);
uint8_t bt_mesh_get_sar_urc(void);
uint8_t bt_mesh_get_sar_urwpc(void);
uint8_t bt_mesh_get_sar_uris(void);
uint8_t bt_mesh_get_sar_urii(void);
uint8_t bt_mesh_get_sar_mrc(void);
uint8_t bt_mesh_get_sar_mris(void);
uint8_t bt_mesh_get_sar_st(void);
uint8_t bt_mesh_get_sar_adi(void);
uint8_t bt_mesh_get_sar_arc(void);
uint8_t bt_mesh_get_sar_dt(void);
uint8_t bt_mesh_get_sar_rsis(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif