feat(ble_mesh): Support Bluetooth Mesh SAR enhancement

This commit is contained in:
Liu Linyan 2023-11-02 16:25:41 +08:00
parent f57acc21d6
commit d9876ffd53
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/scan.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/model_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_srpl_model.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()

View File

@ -678,6 +678,13 @@ if BLE_MESH
When the above situation is encountered, this option can be used to decide whether
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
int "Maximum number of simultaneous outgoing segmented messages"
default 1

View File

@ -32,8 +32,11 @@
/* Pre-5.0 controllers enforce a minimum interval of 100ms
* whereas 5.0+ controllers can go down to 20ms.
*/
#define ADV_INT_DEFAULT_MS 100
#define ADV_INT_FAST_MS 20
#if CONFIG_BLE_MESH_HCI_5_0
#define ADV_ITVL_MIN 20
#else
#define ADV_ITVL_MIN 100
#endif
static const uint8_t adv_type[] = {
[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)
{
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;
void *cb_data = BLE_MESH_ADV(buf)->cb_data;
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 (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) {
#endif
adv_int = MAX(adv_int_min,
adv_int = MAX(ADV_ITVL_MIN,
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
(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))
uint16_t bt_mesh_pdu_duration(uint8_t xmit);
typedef struct bt_mesh_msg {
bool relay; /* Flag indicates if the packet is a relayed one */
void *arg; /* Pointer to the struct net_buf */

View File

@ -90,7 +90,7 @@ static struct seg_tx {
uint8_t tag; /* Additional metadata */
const struct bt_mesh_send_cb *cb;
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];
static struct seg_rx {
@ -106,7 +106,7 @@ static struct seg_rx {
uint16_t dst;
uint32_t block;
uint32_t last;
struct k_delayed_work ack;
struct k_delayed_work ack_timer;
struct net_buf_simple buf;
} seg_rx[CONFIG_BLE_MESH_RX_SEG_MSG_COUNT] = {
[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;
}
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
* 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();
k_delayed_work_cancel(&tx->retransmit);
k_delayed_work_cancel(&tx->rtx_timer);
tx->cb = 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);
/* TODO: notify the completion of sending segmented message */
if (cb && cb->end) {
cb->end(err, cb_data);
}
@ -377,7 +379,7 @@ static void schedule_retransmit(struct seg_tx *tx)
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)
@ -471,7 +473,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
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);
}
@ -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;
/* TODO:
* When SAR Transmitter is introduced, the xmit may be
* updated with "bt_mesh_get_sar_seg_transmit()".
*/
if (sdu->len) {
tx->seg_n = (sdu->len - 1) / seg_len(!!ctl_op);
} 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,
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);
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;
}
k_delayed_work_cancel(&tx->retransmit);
k_delayed_work_cancel(&tx->rtx_timer);
while ((bit = find_lsb_set(ack))) {
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)
{
BT_DBG("rx %p", rx);
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 &&
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)
{
struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack);
BT_DBG("rx %p", rx);
struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack_timer);
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,
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();
}
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,
@ -1568,9 +1568,9 @@ found_rx:
/* Reset the Incomplete Timer */
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()) {
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 */
@ -1594,7 +1594,7 @@ found_rx:
*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,
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();
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++) {
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 +
(i * CONFIG_BLE_MESH_RX_SDU_MAX));
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);
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++) {
k_delayed_work_free(&seg_rx[i].ack);
k_delayed_work_free(&seg_rx[i].ack_timer);
}
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);
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);

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.
*/
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;
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 */
uint8_t sar_unicast_retrans_interval_increment:4, /*!< SAR Unicast Retransmissions Interval Increment 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;
/** Parameters of SAR Receiver Set */
@ -91,7 +91,7 @@ typedef struct {
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 */
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;
/** 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);
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
}
#endif