From cc19e1da9ba51a6bd00979cc554ac363ee91dabd Mon Sep 17 00:00:00 2001 From: lly Date: Wed, 19 Feb 2020 18:16:16 +0800 Subject: [PATCH 1/7] ble_mesh: Provisioner ignores msg from removed node --- components/bt/esp_ble_mesh/mesh_core/net.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/components/bt/esp_ble_mesh/mesh_core/net.c b/components/bt/esp_ble_mesh/mesh_core/net.c index a06d62e5a..778092243 100644 --- a/components/bt/esp_ble_mesh/mesh_core/net.c +++ b/components/bt/esp_ble_mesh/mesh_core/net.c @@ -1394,6 +1394,24 @@ static bool ready_to_recv(void) return false; } +static bool ignore_net_msg(u16_t src, u16_t dst) +{ + if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && + bt_mesh_is_provisioner_en() && + BLE_MESH_ADDR_IS_UNICAST(dst) && + bt_mesh_elem_find(dst)) { + /* If the destination address of the message is the element + * address of Provisioner, but Provisioner fails to find the + * node in its provisioning database, then this message will + * be ignored. + */ + if (!bt_mesh_provisioner_get_node_with_addr(src)) { + return true; + } + } + return false; +} + void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi, enum bt_mesh_net_if net_if) { @@ -1411,6 +1429,10 @@ void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi, return; } + if (ignore_net_msg(rx.ctx.addr, rx.ctx.recv_dst)) { + return; + } + /* Save the state so the buffer can later be relayed */ net_buf_simple_save(&buf, &state); From 9fa5c14d580ac8f24a50db427f3d02bdafa717f0 Mon Sep 17 00:00:00 2001 From: lly Date: Wed, 19 Feb 2020 21:30:48 +0800 Subject: [PATCH 2/7] ble_mesh: Reset transport info when node is removed --- .../esp_ble_mesh/mesh_core/provisioner_main.c | 19 +++----- .../bt/esp_ble_mesh/mesh_core/transport.c | 44 +++++++++++++++++++ .../bt/esp_ble_mesh/mesh_core/transport.h | 2 + 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c index dcf3421f4..f60d9e22a 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c @@ -21,6 +21,7 @@ #include "access.h" #include "settings.h" #include "friend.h" +#include "transport.h" #include "mesh_common.h" #include "proxy_client.h" #include "provisioner_prov.h" @@ -380,7 +381,6 @@ int bt_mesh_provisioner_provision(const bt_mesh_addr_t *addr, const u8_t uuid[16 static int provisioner_remove_node(u16_t index, bool erase) { struct bt_mesh_node *node = NULL; - struct bt_mesh_rpl *rpl = NULL; bool is_prov = false; int i; @@ -398,17 +398,12 @@ static int provisioner_remove_node(u16_t index, bool erase) /* Reset corresponding network cache when reset the node */ bt_mesh_msg_cache_clear(node->unicast_addr, node->element_num); - /* Reset corresponding rpl when removing the node */ - for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { - rpl = &bt_mesh.rpl[i]; - if (rpl->src >= node->unicast_addr && - rpl->src < node->unicast_addr + node->element_num) { - memset(rpl, 0, sizeof(struct bt_mesh_rpl)); - - if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - bt_mesh_clear_rpl_single(node->unicast_addr); - } - } + /* Reset corresponding transport info when removing the node */ + for (i = 0; i < node->element_num; i++) { + bt_mesh_rx_reset_single(node->unicast_addr + i); + } + for (i = 0; i < node->element_num; i++) { + bt_mesh_tx_reset_single(node->unicast_addr + i); } if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.c b/components/bt/esp_ble_mesh/mesh_core/transport.c index 3d78e4365..6fa91aa66 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.c +++ b/components/bt/esp_ble_mesh/mesh_core/transport.c @@ -1584,6 +1584,50 @@ void bt_mesh_tx_reset(void) } } +#if CONFIG_BLE_MESH_PROVISIONER +void bt_mesh_rx_reset_single(u16_t src) +{ + int i; + + if (!BLE_MESH_ADDR_IS_UNICAST(src)) { + return; + } + + for (i = 0; i < ARRAY_SIZE(seg_rx); i++) { + struct seg_rx *rx = &seg_rx[i]; + if (src == rx->src) { + seg_rx_reset(rx, true); + } + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { + struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i]; + if (src == rpl->src) { + memset(rpl, 0, sizeof(struct bt_mesh_rpl)); + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { + bt_mesh_clear_rpl_single(src); + } + } + } +} + +void bt_mesh_tx_reset_single(u16_t dst) +{ + int i; + + if (!BLE_MESH_ADDR_IS_UNICAST(dst)) { + return; + } + + for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { + struct seg_tx *tx = &seg_tx[i]; + if (dst == tx->dst) { + seg_tx_reset(tx); + } + } +} +#endif /* CONFIG_BLE_MESH_PROVISIONER */ + void bt_mesh_trans_init(void) { int i; diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.h b/components/bt/esp_ble_mesh/mesh_core/transport.h index 028b62be8..b97382d3d 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.h +++ b/components/bt/esp_ble_mesh/mesh_core/transport.h @@ -88,6 +88,8 @@ bool bt_mesh_tx_in_progress(void); void bt_mesh_rx_reset(void); void bt_mesh_tx_reset(void); +void bt_mesh_rx_reset_single(u16_t src); +void bt_mesh_tx_reset_single(u16_t dst); int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data, size_t data_len, u64_t *seq_auth, From 04a6ac3cf564b690fdb594fa62e4dbcf6722d17a Mon Sep 17 00:00:00 2001 From: lly Date: Tue, 25 Feb 2020 10:43:04 +0800 Subject: [PATCH 3/7] ble_mesh: Allow maximum 377 octets payload --- components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index 28e64b767..067a35ded 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -1944,8 +1944,8 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg) break; } case BTC_BLE_MESH_ACT_SERVER_MODEL_SEND: { - /* arg->model_send.length contains opcode & message, 8 is used for TransMIC */ - struct net_buf_simple *buf = bt_mesh_alloc_buf(arg->model_send.length + 8); + /* arg->model_send.length contains opcode & message, 4 is used for TransMIC */ + struct net_buf_simple *buf = bt_mesh_alloc_buf(arg->model_send.length + 4); if (!buf) { BT_ERR("%s, Failed to allocate memory", __func__); break; @@ -1962,8 +1962,8 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg) } case BTC_BLE_MESH_ACT_CLIENT_MODEL_SEND: { bt_mesh_role_param_t common = {0}; - /* arg->model_send.length contains opcode & message, 8 is used for TransMIC */ - struct net_buf_simple *buf = bt_mesh_alloc_buf(arg->model_send.length + 8); + /* arg->model_send.length contains opcode & message, 4 is used for TransMIC */ + struct net_buf_simple *buf = bt_mesh_alloc_buf(arg->model_send.length + 4); if (!buf) { BT_ERR("%s, Failed to allocate memory", __func__); break; From 49fc8c86b3ee6cff9a9f89d95b08baa9acca68aa Mon Sep 17 00:00:00 2001 From: lly Date: Mon, 9 Dec 2019 14:30:46 +0800 Subject: [PATCH 4/7] ble_mesh: Unify client application and lower transport layer timeout --- .../bt/esp_ble_mesh/mesh_core/transport.c | 13 +++ .../bt/esp_ble_mesh/mesh_core/transport.h | 4 + .../mesh_models/client/client_common.c | 84 ++++++++++++++++++- 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.c b/components/bt/esp_ble_mesh/mesh_core/transport.c index 6fa91aa66..ba990e3f4 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.c +++ b/components/bt/esp_ble_mesh/mesh_core/transport.c @@ -125,6 +125,19 @@ static void bt_mesh_tx_seg_unlock(void) bt_mesh_mutex_unlock(&tx_seg_lock); } +u8_t bt_mesh_get_seg_retrans_num(void) +{ + return SEG_RETRANSMIT_ATTEMPTS; +} + +s32_t bt_mesh_get_seg_retrans_timeout(u8_t ttl) +{ + struct seg_tx tx = { + .ttl = ttl, + }; + return SEG_RETRANSMIT_TIMEOUT(&tx); +} + void bt_mesh_set_hb_sub_dst(u16_t addr) { hb_sub_dst = addr; diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.h b/components/bt/esp_ble_mesh/mesh_core/transport.h index b97382d3d..31356c46b 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.h +++ b/components/bt/esp_ble_mesh/mesh_core/transport.h @@ -80,6 +80,10 @@ struct bt_mesh_ctl_friend_sub_confirm { u8_t xact; } __packed; +u8_t bt_mesh_get_seg_retrans_num(void); + +s32_t bt_mesh_get_seg_retrans_timeout(u8_t ttl); + void bt_mesh_set_hb_sub_dst(u16_t addr); struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx); diff --git a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c index 13b2896cb..d95ef8bdf 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c @@ -17,9 +17,15 @@ #include "mesh.h" #include "mesh_main.h" +#include "transport.h" +#include "foundation.h" #include "client_common.h" #include "mesh_common.h" +#define UNSEG_ACCESS_MSG_MAX_LEN 11 /* 11 octets (Opcode + Payload), 4 octets TransMIC */ +#define SEG_ACCESS_MSG_SEG_LEN 12 /* 12 * 32 = 384 octets (Opcode + Payload + TransMIC) */ +#define HCI_TIME_FOR_START_ADV K_MSEC(5) /* Three adv related hci commands may take 4 ~ 5ms */ + static bt_mesh_client_node_t *bt_mesh_client_pick_node(sys_slist_t *list, u16_t tx_dst) { bt_mesh_client_node_t *node = NULL; @@ -156,6 +162,79 @@ static u32_t bt_mesh_client_get_status_op(const bt_mesh_client_op_pair_t *op_pai return 0; } +static s32_t bt_mesh_get_adv_duration(void) +{ + u16_t duration, adv_int; + u8_t xmit; + + xmit = bt_mesh_net_transmit_get(); /* Network transmit */ + adv_int = BLE_MESH_TRANSMIT_INT(xmit); + duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); + + return (s32_t)duration; +} + +static s32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *msg, + u32_t opcode, s32_t timeout) +{ + s32_t seg_retrans_to, duration, time; + u8_t seg_count, seg_retrans_num; + u8_t mic_size; + bool need_seg; + + if (msg->len > UNSEG_ACCESS_MSG_MAX_LEN || ctx->send_rel) { + need_seg = true; /* Needs segmentation */ + } + + mic_size = (need_seg && net_buf_simple_tailroom(msg) >= 8U) ? 8U : 4U; + + if (need_seg) { + /* Based on the message length, calculate how many segments are needed. + * All the messages sent from here are access messages. + */ + seg_retrans_num = bt_mesh_get_seg_retrans_num(); + seg_retrans_to = bt_mesh_get_seg_retrans_timeout(ctx->send_ttl); + seg_count = (msg->len + mic_size - 1) / 12U + 1U; + + duration = bt_mesh_get_adv_duration(); + + /* Currenlty only consider the time consumption of the same segmented + * messages, but if there are other messages between any two retrans- + * missions of the same segmented messages, then the whole time will + * be longer. + */ + if (duration + HCI_TIME_FOR_START_ADV < seg_retrans_to) { + s32_t seg_duration = seg_count * (duration + HCI_TIME_FOR_START_ADV); + time = (seg_duration + seg_retrans_to) * (seg_retrans_num - 1) + seg_duration; + } else { + /* If the duration is bigger than the segment retransmit timeout + * value. In this situation, the segment retransmit timeout value + * may need to be optimized based on the "Network Transmit" value. + */ + time = seg_count * (duration + HCI_TIME_FOR_START_ADV) * seg_retrans_num; + } + + BT_INFO("Original timeout %dms, calculated timeout %dms", timeout, time); + + if (time < timeout) { + /* If the calculated time is smaller than the input timeout value, + * then use the original timeout value. + */ + time = timeout; + } + } else { + /* For unsegmented access messages, directly use the timeout + * value from the application layer. + */ + time = timeout; + } + + BT_INFO("Client message 0x%08x with timeout %dms", opcode, time); + + return time; +} + int bt_mesh_client_send_msg(struct bt_mesh_model *model, u32_t opcode, struct bt_mesh_msg_ctx *ctx, @@ -203,6 +282,9 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model, bt_mesh_free(node); return -EINVAL; } + + s32_t time = bt_mesh_client_calc_timeout(ctx, msg, opcode, timeout ? timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); + if ((err = bt_mesh_model_send(model, ctx, msg, cb, cb_data)) != 0) { bt_mesh_free(node); } else { @@ -210,7 +292,7 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model, sys_slist_append(&internal->queue, &node->client_node); bt_mesh_list_unlock(); k_delayed_work_init(&node->timer, timer_handler); - k_delayed_work_submit(&node->timer, timeout ? timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); + k_delayed_work_submit(&node->timer, time); } } From 70eadc0b053de9340c537679370dad0205aff138 Mon Sep 17 00:00:00 2001 From: lly Date: Tue, 4 Feb 2020 12:20:41 +0800 Subject: [PATCH 5/7] ble_mesh: No timeout for client message to non-unicast address --- .../mesh_models/client/client_common.c | 103 ++++++++++++------ 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c index d95ef8bdf..75c88135f 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c @@ -245,7 +245,7 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model, void *cb_data) { bt_mesh_client_internal_data_t *internal = NULL; - bt_mesh_client_user_data_t *cli = NULL; + bt_mesh_client_user_data_t *client = NULL; bt_mesh_client_node_t *node = NULL; int err = 0; @@ -254,49 +254,80 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model, return -EINVAL; } - cli = (bt_mesh_client_user_data_t *)model->user_data; - __ASSERT(cli, "Invalid client value when sent client msg."); - internal = (bt_mesh_client_internal_data_t *)cli->internal_data; - __ASSERT(internal, "Invalid internal value when sent client msg."); + client = (bt_mesh_client_user_data_t *)model->user_data; + if (!client) { + BT_ERR("%s, Invalid client user data", __func__); + return -EINVAL; + } + + internal = (bt_mesh_client_internal_data_t *)client->internal_data; + if (!internal) { + BT_ERR("%s, Invalid client internal data", __func__); + return -EINVAL; + } + + if (ctx->addr == BLE_MESH_ADDR_UNASSIGNED) { + BT_ERR("%s, Invalid DST 0x%04x", __func__, ctx->addr); + return -EINVAL; + } if (!need_ack) { /* If this is an unack message, send it directly. */ return bt_mesh_model_send(model, ctx, msg, cb, cb_data); } - if (bt_mesh_client_check_node_in_list(&internal->queue, ctx->addr)) { - BT_ERR("%s, Busy sending message to DST 0x%04x", __func__, ctx->addr); - err = -EBUSY; - } else { - /* Don't forget to free the node in the timeout (timer_handler) function. */ - node = (bt_mesh_client_node_t *)bt_mesh_calloc(sizeof(bt_mesh_client_node_t)); - if (!node) { - BT_ERR("%s, Failed to allocate memory", __func__); - return -ENOMEM; - } - memcpy(&node->ctx, ctx, sizeof(struct bt_mesh_msg_ctx)); - node->ctx.model = model; - node->opcode = opcode; - if ((node->op_pending = bt_mesh_client_get_status_op(cli->op_pair, cli->op_pair_size, opcode)) == 0) { - BT_ERR("%s, Not found the status opcode in the op_pair list", __func__); - bt_mesh_free(node); - return -EINVAL; - } - - s32_t time = bt_mesh_client_calc_timeout(ctx, msg, opcode, timeout ? timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); - - if ((err = bt_mesh_model_send(model, ctx, msg, cb, cb_data)) != 0) { - bt_mesh_free(node); - } else { - bt_mesh_list_lock(); - sys_slist_append(&internal->queue, &node->client_node); - bt_mesh_list_unlock(); - k_delayed_work_init(&node->timer, timer_handler); - k_delayed_work_submit(&node->timer, time); - } + if (!BLE_MESH_ADDR_IS_UNICAST(ctx->addr)) { + /* If an acknowledged message is not sent to a unicast address, + * for example to a group/virtual address, then all the + * corresponding responses will be treated as publish messages. + * And no timeout will be used for the message. + */ + return bt_mesh_model_send(model, ctx, msg, cb, cb_data); } - return err; + if (!timer_handler) { + BT_ERR("%s, Invalid timeout handler", __func__); + return -EINVAL; + } + + if (bt_mesh_client_check_node_in_list(&internal->queue, ctx->addr)) { + BT_ERR("%s, Busy sending message to DST 0x%04x", __func__, ctx->addr); + return -EBUSY; + } + + /* Don't forget to free the node in the timeout (timer_handler) function. */ + node = (bt_mesh_client_node_t *)bt_mesh_calloc(sizeof(bt_mesh_client_node_t)); + if (!node) { + BT_ERR("%s, Failed to allocate memory", __func__); + return -ENOMEM; + } + + memcpy(&node->ctx, ctx, sizeof(struct bt_mesh_msg_ctx)); + node->ctx.model = model; + node->opcode = opcode; + node->op_pending = bt_mesh_client_get_status_op(client->op_pair, client->op_pair_size, opcode); + if (node->op_pending == 0U) { + BT_ERR("%s, Not found the status opcode in the op_pair list", __func__); + bt_mesh_free(node); + return -EINVAL; + } + + s32_t time = bt_mesh_client_calc_timeout(ctx, msg, opcode, timeout ? timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); + + err = bt_mesh_model_send(model, ctx, msg, cb, cb_data); + if (err) { + bt_mesh_free(node); + return err; + } + + bt_mesh_list_lock(); + sys_slist_append(&internal->queue, &node->client_node); + bt_mesh_list_unlock(); + + k_delayed_work_init(&node->timer, timer_handler); + k_delayed_work_submit(&node->timer, time); + + return 0; } static bt_mesh_mutex_t client_model_lock; From 91ad0f9f4abafc92a585c057bc3ad78ff70be170 Mon Sep 17 00:00:00 2001 From: lly Date: Tue, 4 Feb 2020 15:26:44 +0800 Subject: [PATCH 6/7] ble_mesh: Start the timer when starting to send the client message --- .../mesh_models/client/client_common.c | 44 ++++++++++++++----- .../client/include/client_common.h | 1 + 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c index 75c88135f..a3f68834b 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c @@ -235,6 +235,27 @@ static s32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx, return time; } +static void msg_send_start(u16_t duration, int err, void *cb_data) +{ + bt_mesh_client_node_t *node = cb_data; + + BT_DBG("%s, duration %ums", __func__, duration); + + if (err) { + if (!k_delayed_work_free(&node->timer)) { + bt_mesh_client_free_node(node); + } + return; + } + + k_delayed_work_submit(&node->timer, node->timeout); +} + +static const struct bt_mesh_send_cb send_cb = { + .start = msg_send_start, + .end = NULL, +}; + int bt_mesh_client_send_msg(struct bt_mesh_model *model, u32_t opcode, struct bt_mesh_msg_ctx *ctx, @@ -311,23 +332,26 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model, bt_mesh_free(node); return -EINVAL; } + node->timeout = bt_mesh_client_calc_timeout(ctx, msg, opcode, timeout ? timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); - s32_t time = bt_mesh_client_calc_timeout(ctx, msg, opcode, timeout ? timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); - - err = bt_mesh_model_send(model, ctx, msg, cb, cb_data); - if (err) { - bt_mesh_free(node); - return err; - } + k_delayed_work_init(&node->timer, timer_handler); bt_mesh_list_lock(); sys_slist_append(&internal->queue, &node->client_node); bt_mesh_list_unlock(); - k_delayed_work_init(&node->timer, timer_handler); - k_delayed_work_submit(&node->timer, time); + /* "bt_mesh_model_send" will post the mesh packet to the mesh adv queue. + * Due to the higher priority of adv_thread (than btc task), we need to + * send the packet after the list item "node" is initialized properly. + */ + err = bt_mesh_model_send(model, ctx, msg, &send_cb, node); + if (err) { + BT_ERR("Failed to send client message 0x%08x", node->opcode); + k_delayed_work_free(&node->timer); + bt_mesh_client_free_node(node); + } - return 0; + return err; } static bt_mesh_mutex_t client_model_lock; diff --git a/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h b/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h index 0e337d34b..ddf743b32 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h +++ b/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h @@ -65,6 +65,7 @@ typedef struct { struct bt_mesh_msg_ctx ctx; /* Message context */ u32_t opcode; /* Message opcode */ u32_t op_pending; /* Expected status message opcode */ + s32_t timeout; /* Calculated message timeout value */ struct k_delayed_work timer; /* Time used to get response. Only for internal use. */ } bt_mesh_client_node_t; From 0e2c77b185ed36899a8b79a8bc25e047e1cbac5c Mon Sep 17 00:00:00 2001 From: lly Date: Tue, 4 Feb 2020 18:06:40 +0800 Subject: [PATCH 7/7] ble_mesh: Calc incomplete timeout based on msg info --- .../bt/esp_ble_mesh/mesh_core/transport.c | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.c b/components/bt/esp_ble_mesh/mesh_core/transport.c index ba990e3f4..bb8a1cc54 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.c +++ b/components/bt/esp_ble_mesh/mesh_core/transport.c @@ -1143,13 +1143,33 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset) } } +static u32_t incomplete_timeout(struct seg_rx *rx) +{ + u32_t timeout = 0U; + u8_t ttl = 0U; + + if (rx->ttl == BLE_MESH_TTL_DEFAULT) { + ttl = bt_mesh_default_ttl_get(); + } else { + ttl = rx->ttl; + } + + /* "The incomplete timer shall be set to a minimum of 10 seconds." */ + timeout = K_SECONDS(10); + + /* The less segments being received, the shorter timeout will be used. */ + timeout += K_MSEC(ttl * popcount(rx->block) * 100U); + + return MIN(timeout, K_SECONDS(60)); +} + static void seg_ack(struct k_work *work) { struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack); BT_DBG("rx %p", rx); - if (k_uptime_get_32() - rx->last > K_SECONDS(60)) { + if (k_uptime_get_32() - rx->last > incomplete_timeout(rx)) { BT_WARN("Incomplete timer expired"); seg_rx_reset(rx, false); return;