From ad3ff34e98c285c0a063fc91fea58a34ebe04804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 20 Feb 2018 11:50:51 +0100 Subject: [PATCH 1/9] mesh: Fix passing CID to model publication messages The vendor variants of the model publication client messages were not passing onward the CID, rather passing CID_NVAL which is clearly not right. X-Original-Commit: 398fd57f82a407a343ff04e445aed6de9e990e8e --- nimble/host/mesh/src/cfg_cli.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index 05c302bd1..4d1af2e13 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -1132,8 +1132,7 @@ int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, return -EINVAL; } - return mod_pub_get(net_idx, addr, elem_addr, mod_id, CID_NVAL, - pub, status); + return mod_pub_get(net_idx, addr, elem_addr, mod_id, cid, pub, status); } static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr, @@ -1205,8 +1204,7 @@ int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, return -EINVAL; } - return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL, - pub, status); + return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status); } int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr, From 417418eaac3bee5a9237fa4db2219d66819ebeb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 20 Feb 2018 12:30:15 +0100 Subject: [PATCH 2/9] mesh: Add support for OOB info and URI in provisioning data Until now the OOB info and URI fields in unprovisioned beacons were generally ignored by the implementation. Add fields for these to bt_mesh_prov and make sure to take them into account when encoding advertising data, both for PB-ADV and PB-GATT. For PB-ADV the URI goes out in a separate beacon, whereas for PB-GATT it is placed in the scan response data. X-Original-Commit: e6b7f42e2688c2d4102dea83bf962d2fbc74ac5e --- nimble/host/mesh/include/mesh/glue.h | 2 ++ nimble/host/mesh/include/mesh/main.h | 26 ++++++++++++++++ nimble/host/mesh/src/adv.c | 5 ++-- nimble/host/mesh/src/adv.h | 1 + nimble/host/mesh/src/beacon.c | 41 ++++++++++++++++++++++--- nimble/host/mesh/src/prov.c | 4 +-- nimble/host/mesh/src/prov.h | 2 +- nimble/host/mesh/src/proxy.c | 45 ++++++++++++++++++++++++---- 8 files changed, 111 insertions(+), 15 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 4cb61c5bc..66c381813 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -97,6 +97,7 @@ #define BT_DATA_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */ #define BT_DATA_SVC_DATA32 0x20 /* Service data, 32-bit UUID */ #define BT_DATA_SVC_DATA128 0x21 /* Service data, 128-bit UUID */ +#define BT_DATA_URI 0x24 /* URI */ #define BT_DATA_MESH_PROV 0x29 /* Mesh Provisioning PDU */ #define BT_DATA_MESH_MESSAGE 0x2a /* Mesh Networking PDU */ #define BT_DATA_MESH_BEACON 0x2b /* Mesh Beacon */ @@ -356,6 +357,7 @@ static inline unsigned int find_msb_set(u32_t op) #define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT) #define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT) #define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS) +#define CONFIG_BT_DEVICE_NAME "nimble-mesh" #define printk console_printf diff --git a/nimble/host/mesh/include/mesh/main.h b/nimble/host/mesh/include/mesh/main.h index bc3c86f8f..752878fa1 100644 --- a/nimble/host/mesh/include/mesh/main.h +++ b/nimble/host/mesh/include/mesh/main.h @@ -39,11 +39,37 @@ typedef enum { BT_MESH_PROV_GATT = BIT(1), } bt_mesh_prov_bearer_t; +typedef enum { + BT_MESH_PROV_OOB_OTHER = BIT(0), + BT_MESH_PROV_OOB_URI = BIT(1), + BT_MESH_PROV_OOB_2D_CODE = BIT(2), + BT_MESH_PROV_OOB_BAR_CODE = BIT(3), + BT_MESH_PROV_OOB_NFC = BIT(4), + BT_MESH_PROV_OOB_NUMBER = BIT(5), + BT_MESH_PROV_OOB_STRING = BIT(6), + /* 7 - 10 are reserved */ + BT_MESH_PROV_OOB_ON_BOX = BIT(11), + BT_MESH_PROV_OOB_IN_BOX = BIT(12), + BT_MESH_PROV_OOB_ON_PAPER = BIT(13), + BT_MESH_PROV_OOB_IN_MANUAL = BIT(14), + BT_MESH_PROV_OOB_ON_DEV = BIT(15), +} bt_mesh_prov_oob_info_t; + /** Provisioning properties & capabilities. */ struct bt_mesh_prov { /** The UUID that's used when advertising as unprovisioned */ const u8_t *uuid; + /** Optional URI. This will be advertised separately from the + * unprovisioned beacon, however the unprovisioned beacon will + * contain a hash of it so the two can be associated by the + * provisioner. + */ + const char *uri; + + /** Out of Band information field. */ + bt_mesh_prov_oob_info_t oob_info; + /** Static OOB value */ const u8_t *static_val; /** Static OOB value length */ diff --git a/nimble/host/mesh/src/adv.c b/nimble/host/mesh/src/adv.c index c8aced18b..f5a032cd2 100644 --- a/nimble/host/mesh/src/adv.c +++ b/nimble/host/mesh/src/adv.c @@ -55,9 +55,10 @@ struct os_mbuf_pool adv_os_mbuf_pool; static struct os_mempool adv_buf_mempool; static const u8_t adv_type[] = { - [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV, - [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE, + [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV, + [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE, [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON, + [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI, }; diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index 27930d59f..e40d6673b 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -28,6 +28,7 @@ enum bt_mesh_adv_type BT_MESH_ADV_PROV, BT_MESH_ADV_DATA, BT_MESH_ADV_BEACON, + BT_MESH_ADV_URI, }; typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, u16_t duration, diff --git a/nimble/host/mesh/src/beacon.c b/nimble/host/mesh/src/beacon.c index ace6428fa..a54cedbd7 100644 --- a/nimble/host/mesh/src/beacon.c +++ b/nimble/host/mesh/src/beacon.c @@ -150,7 +150,10 @@ static int secure_beacon_send(void) static int unprovisioned_beacon_send(void) { #if (MYNEWT_VAL(BLE_MESH_PB_ADV)) + const struct bt_mesh_prov *prov; + u8_t uri_hash[16] = { 0 }; struct os_mbuf *buf; + u16_t oob_info; BT_DBG("unprovisioned_beacon_send"); @@ -161,15 +164,45 @@ static int unprovisioned_beacon_send(void) return -ENOBUFS; } - net_buf_add_u8(buf, BEACON_TYPE_UNPROVISIONED); - net_buf_add_mem(buf, bt_mesh_prov_get_uuid(), 16); + prov = bt_mesh_prov_get(); - /* OOB Info (2 bytes) + URI Hash (4 bytes) */ - net_buf_add_zeros(buf, 2 + 4); + net_buf_add_u8(buf, BEACON_TYPE_UNPROVISIONED); + net_buf_add_mem(buf, prov->uuid, 16); + + if (prov->uri) { + oob_info = prov->oob_info | BT_MESH_PROV_OOB_URI; + bt_mesh_s1(prov->uri, uri_hash); + } else { + oob_info = prov->oob_info; + } + + net_buf_add_be16(buf, oob_info); + net_buf_add_mem(buf, uri_hash, 4); bt_mesh_adv_send(buf, NULL, NULL); net_buf_unref(buf); + if (prov->uri) { + size_t len; + + buf = bt_mesh_adv_create(BT_MESH_ADV_URI, UNPROV_XMIT_COUNT, + UNPROV_XMIT_INT, K_NO_WAIT); + if (!buf) { + BT_ERR("Unable to allocate URI buffer"); + return -ENOBUFS; + } + + len = strlen(prov->uri); + if (net_buf_tailroom(buf) < len) { + BT_WARN("Too long URI to fit advertising data"); + } else { + net_buf_add_mem(buf, prov->uri, len); + bt_mesh_adv_send(buf, NULL, NULL); + } + + net_buf_unref(buf); + } + #endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */ return 0; } diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c index 695c0fa34..0a2d3b293 100644 --- a/nimble/host/mesh/src/prov.c +++ b/nimble/host/mesh/src/prov.c @@ -1540,9 +1540,9 @@ int bt_mesh_pb_gatt_close(uint16_t conn_handle) } #endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */ -const u8_t *bt_mesh_prov_get_uuid(void) +const struct bt_mesh_prov *bt_mesh_prov_get(void) { - return prov->uuid; + return prov; } bool bt_prov_active(void) diff --git a/nimble/host/mesh/src/prov.h b/nimble/host/mesh/src/prov.h index 3270b069d..3675b6cc7 100644 --- a/nimble/host/mesh/src/prov.h +++ b/nimble/host/mesh/src/prov.h @@ -21,7 +21,7 @@ int bt_mesh_pb_gatt_open(uint16_t conn_handle); int bt_mesh_pb_gatt_close(uint16_t conn_handle); int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf); -const u8_t *bt_mesh_prov_get_uuid(void); +const struct bt_mesh_prov *bt_mesh_prov_get(void); int bt_mesh_prov_init(const struct bt_mesh_prov *prov); diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/proxy.c index dae72e971..1fe531752 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/proxy.c @@ -985,10 +985,8 @@ static const struct bt_data prov_ad[] = { BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), }; -static const struct bt_data prov_sd[] = { - BT_DATA(BT_DATA_NAME_COMPLETE, "mynewtproxy", - (sizeof("mynewtproxy") - 1)), -}; +static struct bt_data prov_sd[2]; +static size_t prov_sd_len; #endif /* PB_GATT */ #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) @@ -1201,7 +1199,7 @@ s32_t bt_mesh_proxy_adv_start(void) } if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad), - prov_sd, ARRAY_SIZE(prov_sd)) == 0) { + prov_sd, prov_sd_len) == 0) { proxy_adv_enabled = true; /* Advertise 60 seconds using fast interval */ @@ -1338,7 +1336,42 @@ int bt_mesh_proxy_init(void) } #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - memcpy(prov_svc_data + 2, bt_mesh_prov_get_uuid(), 16); + const struct bt_mesh_prov *prov = bt_mesh_prov_get(); + size_t name_len = strlen(CONFIG_BT_DEVICE_NAME); + size_t sd_space = 31; + + memcpy(prov_svc_data + 2, prov->uuid, 16); + sys_put_be16(prov->oob_info, prov_svc_data + 18); + + if (prov->uri) { + size_t uri_len = strlen(prov->uri); + + if (uri_len > 29) { + /* There's no way to shorten an URI */ + BT_WARN("Too long URI to fit advertising packet"); + } else { + prov_sd[0].type = BT_DATA_URI; + prov_sd[0].data_len = uri_len; + prov_sd[0].data = (void *)prov->uri; + sd_space -= 2 + uri_len; + prov_sd_len++; + } + } + + if (sd_space > 2 && name_len > 0) { + sd_space -= 2; + + if (sd_space < name_len) { + prov_sd[prov_sd_len].type = BT_DATA_NAME_SHORTENED; + prov_sd[prov_sd_len].data_len = sd_space; + } else { + prov_sd[prov_sd_len].type = BT_DATA_NAME_COMPLETE; + prov_sd[prov_sd_len].data_len = name_len; + } + + prov_sd[prov_sd_len].data = (void *)CONFIG_BT_DEVICE_NAME; + prov_sd_len++; + } #endif resolve_svc_handles(); From 703c021133e3e7e158d79c736333fa53c57f1628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 20 Feb 2018 12:31:32 +0100 Subject: [PATCH 3/9] mesh: Fix coverity warning with unchecked error return This fixes Zephyr's Coverity CID 182769. X-Original-Commit: 584c807f5e25a9c325d90ad6643628198785128d --- nimble/host/mesh/src/beacon.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/beacon.c b/nimble/host/mesh/src/beacon.c index a54cedbd7..34ea6b82a 100644 --- a/nimble/host/mesh/src/beacon.c +++ b/nimble/host/mesh/src/beacon.c @@ -169,9 +169,8 @@ static int unprovisioned_beacon_send(void) net_buf_add_u8(buf, BEACON_TYPE_UNPROVISIONED); net_buf_add_mem(buf, prov->uuid, 16); - if (prov->uri) { + if (prov->uri && bt_mesh_s1(prov->uri, uri_hash) == 0) { oob_info = prov->oob_info | BT_MESH_PROV_OOB_URI; - bt_mesh_s1(prov->uri, uri_hash); } else { oob_info = prov->oob_info; } From 6e2c7d19022c4d9e956a309b55e326f130a455d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 20 Feb 2018 14:12:47 +0100 Subject: [PATCH 4/9] mesh: Account for scan window delaying adv events New advertising started while scanning is already enabled would delay the first advertisement event until the end of the current overlapping scan window in the Zephyr native BLE controller implementation. Hence, consider this scan window duration when calculating the advertising stop. X-Original-Commit: 9b8e353c059d260134310e0255bce8b40b00d394 --- nimble/host/mesh/include/mesh/glue.h | 1 + nimble/host/mesh/src/adv.c | 27 +++++++++++++++------------ nimble/host/mesh/src/glue.c | 5 +++++ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 66c381813..b1050d8c6 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -287,6 +287,7 @@ void k_delayed_work_cancel(struct k_delayed_work *w); void k_delayed_work_submit(struct k_delayed_work *w, uint32_t ms); int64_t k_uptime_get(void); u32_t k_uptime_get_32(void); +void k_sleep(int32_t duration); void k_work_submit(struct os_callout *w); void k_work_add_arg(struct os_callout *w, void *arg); void k_delayed_work_add_arg(struct k_delayed_work *w, void *arg); diff --git a/nimble/host/mesh/src/adv.c b/nimble/host/mesh/src/adv.c index f5a032cd2..3dce81c9e 100644 --- a/nimble/host/mesh/src/adv.c +++ b/nimble/host/mesh/src/adv.c @@ -1,6 +1,7 @@ /* Bluetooth Mesh */ /* + * Copyright (c) 2018 Nordic Semiconductor ASA * Copyright (c) 2017 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 @@ -23,20 +24,22 @@ #include "prov.h" #include "proxy.h" -/* Window and Interval are equal for continuous scanning */ -#define MESH_SCAN_INTERVAL 0x10 -#define MESH_SCAN_WINDOW 0x10 - /* Convert from ms to 0.625ms units */ -#define ADV_INT(_ms) ((_ms) * 8 / 5) +#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) + +/* Window and Interval are equal for continuous scanning */ +#define MESH_SCAN_INTERVAL_MS 10 +#define MESH_SCAN_WINDOW_MS 10 +#define MESH_SCAN_INTERVAL ADV_SCAN_UNIT(MESH_SCAN_INTERVAL_MS) +#define MESH_SCAN_WINDOW ADV_SCAN_UNIT(MESH_SCAN_WINDOW_MS) /* Pre-5.0 controllers enforce a minimum interval of 100ms * whereas 5.0+ controllers can go down to 20ms. */ -#define ADV_INT_DEFAULT K_MSEC(100) -#define ADV_INT_FAST K_MSEC(20) +#define ADV_INT_DEFAULT_MS 100 +#define ADV_INT_FAST_MS 20 -static s32_t adv_int_min = ADV_INT_DEFAULT; +static s32_t adv_int_min = ADV_INT_DEFAULT_MS; /* TinyCrypt PRNG consumes a lot of stack space, so we need to have * an increased call stack whenever it's used. @@ -97,7 +100,7 @@ static inline void adv_send(struct os_mbuf *buf) int err; adv_int = max(adv_int_min, adv->adv_int); - duration = (adv->count + 1) * (adv_int + 10); + duration = MESH_SCAN_WINDOW_MS + (adv->count + 1) * (adv_int + 10); BT_DBG("buf %p, type %u len %u:", buf, adv->type, buf->om_len); @@ -108,7 +111,7 @@ static inline void adv_send(struct os_mbuf *buf) ad.data_len = buf->om_len; ad.data = buf->om_data; - param.itvl_min = ADV_INT(adv_int); + param.itvl_min = ADV_SCAN_UNIT(adv_int); param.itvl_max = param.itvl_min; param.conn_mode = BLE_GAP_CONN_MODE_NON; @@ -122,7 +125,7 @@ static inline void adv_send(struct os_mbuf *buf) BT_DBG("Advertising started. Sleeping %u ms", duration); - os_time_delay(OS_TICKS_PER_SEC * duration / 1000); + k_sleep(K_MSEC(duration)); err = bt_le_adv_stop(); adv_send_end(err, cb, cb_data); @@ -315,7 +318,7 @@ void bt_mesh_adv_init(void) /* For BT5 controllers we can have fast advertising interval */ if (ble_hs_hci_get_hci_version() >= BLE_HCI_VER_BCS_5_0) { - adv_int_min = ADV_INT_FAST; + adv_int_min = ADV_INT_FAST_MS; } } diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index 086edaf8c..b93d9dbb9 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -391,6 +391,11 @@ u32_t k_uptime_get_32(void) return k_uptime_get(); } +void k_sleep(int32_t duration) +{ + os_time_delay(OS_TICKS_PER_SEC * duration / 1000); +} + static uint8_t pub[64]; static uint8_t priv[32]; static bool has_pub = false; From 35bcfc25b76b6be19093a5e85b94485e9160104c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 20 Feb 2018 14:23:49 +0100 Subject: [PATCH 5/9] mesh: Fix handling of failed transmissions When sending a segmented message, the state could get stuck if the advertising bearer fails in transmitting and we don't detect that it happened. Add a send_start callback for all packets so we can always know if sending fails. X-Original-Commit: c2f6fa5baf8eab609a705347e1c1b881e48bd710 --- nimble/host/mesh/src/transport.c | 36 ++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 9902a6d7c..4ae20f37b 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -46,6 +46,12 @@ /* Number of retransmit attempts (after the initial transmit) per segment */ #define SEG_RETRANSMIT_ATTEMPTS 4 +/* "This timer shall be set to a minimum of 200 + 50 * TTL milliseconds.". + * We use 400 since 300 is a common send duration for standard HCI, and we + * need to have a timeout that's bigger than that. + */ +#define SEG_RETRANSMIT_TIMEOUT(tx) (K_MSEC(400) + 50 * (tx)->ttl) + /* How long to wait for available buffers before giving up */ #define BUF_TIMEOUT K_NO_WAIT @@ -191,7 +197,7 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err) seg_tx_reset(tx); } -static void seg_send_start(u16_t duration, int err, void *user_data) +static void seg_first_send_start(u16_t duration, int err, void *user_data) { struct seg_tx *tx = user_data; @@ -200,27 +206,35 @@ static void seg_send_start(u16_t duration, int err, void *user_data) } } +static void seg_send_start(u16_t duration, int err, void *user_data) +{ + struct seg_tx *tx = user_data; + + /* If there's an error in transmitting the 'sent' callback will never + * be called. Make sure that we kick the retransmit timer also in this + * case since otherwise we risk the transmission of becoming stale. + */ + if (err) { + k_delayed_work_submit(&tx->retransmit, + SEG_RETRANSMIT_TIMEOUT(tx)); + } +} + static void seg_sent(int err, void *user_data) { struct seg_tx *tx = user_data; - s32_t timeout; - /* "This timer shall be set to a minimum of 200 + 50 * TTL - * milliseconds.". We use 400 since 300 is a common send - * duration for standard HCI, and we need to have a timeout - * that's bigger than that. - */ - timeout = K_MSEC(400) + 50 * tx->ttl; - - k_delayed_work_submit(&tx->retransmit, timeout); + k_delayed_work_submit(&tx->retransmit, + SEG_RETRANSMIT_TIMEOUT(tx)); } static const struct bt_mesh_send_cb first_sent_cb = { - .start = seg_send_start, + .start = seg_first_send_start, .end = seg_sent, }; static const struct bt_mesh_send_cb seg_sent_cb = { + .start = seg_send_start, .end = seg_sent, }; From 63b487ad59a15d268dc2a51d493ad0d2582dd49a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 20 Feb 2018 14:24:33 +0100 Subject: [PATCH 6/9] mesh: Resend Link Acknowledgment when necessary The Provisioner might have missed our earlier Link Acknowledgement, so if we receive another one with matching Link ID and link.expect state, simply send another acknowledgement. X-Original-Commit: b6d823cb5131e8750d7ec1152b4d48ea60ac85c3 --- nimble/host/mesh/src/prov.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c index 0a2d3b293..04cab17d3 100644 --- a/nimble/host/mesh/src/prov.c +++ b/nimble/host/mesh/src/prov.c @@ -1179,7 +1179,14 @@ static void link_open(struct prov_rx *rx, struct os_mbuf *buf) } if (atomic_test_bit(link.flags, LINK_ACTIVE)) { - BT_WARN("Ignoring bearer open: link already active"); + /* Send another link ack if the provisioner missed the last */ + if (link.id == rx->link_id && link.expect == PROV_INVITE) { + BT_DBG("Resending link ack"); + bearer_ctl_send(LINK_ACK, NULL, 0); + } else { + BT_WARN("Ignoring bearer open: link already active"); + } + return; } From d7fc4a5a1157006921aa1ffd61482cfdcb939728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 20 Feb 2018 14:24:57 +0100 Subject: [PATCH 7/9] mesh: Fix sending Provisioning Failed for PB-GATT In the case of an unexpected PDU we need to send the right response. This was already taken care of for PB-ADV, but not for PB-GATT. X-Original-Commit: 65b2467d6192e9bd943a3f898132775984d6b871 --- nimble/host/mesh/src/prov.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c index 04cab17d3..07d3d022b 100644 --- a/nimble/host/mesh/src/prov.c +++ b/nimble/host/mesh/src/prov.c @@ -1477,6 +1477,7 @@ int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf) type = net_buf_simple_pull_u8(buf); if (type != PROV_FAILED && type != link.expect) { BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect); + prov_send_fail_msg(PROV_ERR_UNEXP_PDU); return -EINVAL; } From 7ed968551eab2f54dfb5ca0d995e2679ed1a9fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 20 Feb 2018 14:25:30 +0100 Subject: [PATCH 8/9] mesh: Ignore segments of cancelled message This fixes the issue when after incomplete timer expiration host sent ACK. The host failed in two cases: 1. Sending ACK right after the incomplete timer expiration; 2. Sending ACK from new RX context. Now, seq_auth of cancelled message is not cleaned on RX reset, so segments of cancelled message will be discarded when resend. According to the Mesh Profile v1.0 "When the incomplete timer expires, the lower transport layer shall consider that the message being received has failed and cancel the acknowledgment timer. Any segment of a canceled message shall be ignored." X-Original-Commit: 50e7d632932c4188849aee89e0d23e2207352601 --- nimble/host/mesh/src/transport.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 4ae20f37b..918af1fe7 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -1009,9 +1009,7 @@ static void seg_ack(struct os_event *work) if (k_uptime_get_32() - rx->last > K_SECONDS(60)) { BT_WARN("Incomplete timer expired"); - send_ack(rx->sub, rx->dst, rx->src, rx->ttl, - &rx->seq_auth, 0, rx->obo); - seg_rx_reset(rx, true); + seg_rx_reset(rx, false); if (IS_ENABLED(CONFIG_BT_TESTING)) { bt_test_mesh_trans_incomp_timer_exp(); From e99920f59e5836ab75cd95fa8f71e938ebcfc368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Wed, 21 Feb 2018 12:56:20 +0100 Subject: [PATCH 9/9] mesh: Use a single transmission from Friend to LPN As per TSE 10009 the TS will enforce that a Friend ever only uses a single transmission when sending packets to an LPN. Make sure that our implementation follows this. https://www.bluetooth.org/tse/errata_view.cfm?errata_id=10009 X-Original-Commit: 564a956d1a3b291234dc1351f422830b781689f1 --- nimble/host/mesh/src/friend.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 9969737e9..42c9384b7 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -44,6 +44,12 @@ static struct os_mempool friend_buf_mempool; #define FRIEND_ADV(buf) CONTAINER_OF(BT_MESH_ADV(buf), \ struct friend_adv, adv) +/* PDUs from Friend to the LPN should only be transmitted once with the + * smallest possible interval (20ms). + */ +#define FRIEND_XMIT_COUNT 0 +#define FRIEND_XMIT_INT 20 + struct friend_pdu_info { u16_t src; u16_t dst; @@ -87,15 +93,13 @@ static void discard_buffer(void) static struct os_mbuf *friend_buf_alloc(u16_t src) { - u8_t xmit = bt_mesh_net_transmit_get(); struct os_mbuf *buf; do { buf = bt_mesh_adv_create_from_pool(&friend_os_mbuf_pool, adv_alloc, BT_MESH_ADV_DATA, - BT_MESH_TRANSMIT_COUNT(xmit), - BT_MESH_TRANSMIT_INT(xmit), - K_NO_WAIT); + FRIEND_XMIT_COUNT, + FRIEND_XMIT_INT, K_NO_WAIT); if (!buf) { discard_buffer(); }