diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index 44d7fec6b..4309cdb3e 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -590,8 +590,7 @@ if BLE_MESH endif # BLE_MESH_LOW_POWER config BLE_MESH_FRIEND - bool "Support for acting as a Friend Node" - depends on BLE_MESH_NODE + bool "Support for Friend feature" help Enable this option to be able to act as a Friend Node. diff --git a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index d59c29eb6..733c718aa 100644 --- a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -356,16 +356,16 @@ typedef struct { esp_ble_mesh_model_t *model; uint16_t publish_addr; /*!< Publish Address. */ - uint16_t app_idx; /*!< Publish AppKey Index. */ + uint16_t app_idx:12, /*!< Publish AppKey Index. */ + cred:1; /*!< Friendship Credentials Flag. */ uint8_t ttl; /*!< Publish Time to Live. */ uint8_t retransmit; /*!< Retransmit Count & Interval Steps. */ uint8_t period; /*!< Publish Period. */ - uint16_t period_div: 4, /*!< Divisor for the Period. */ - cred: 1, /*!< Friendship Credentials Flag. */ - fast_period: 1, /*!< Use FastPeriodDivisor */ - count: 3; /*!< Retransmissions left. */ + uint8_t period_div:4, /*!< Divisor for the Period. */ + fast_period:1, /*!< Use FastPeriodDivisor */ + count:3; /*!< Retransmissions left. */ uint32_t period_start; /*!< Start of the current period. */ @@ -491,6 +491,9 @@ typedef struct { /** Destination address of a received message. Not used for sending. */ uint16_t recv_dst; + /** RSSI of received packet. Not used for sending. */ + int8_t recv_rssi; + /** Received TTL value. Not used for sending. */ uint8_t recv_ttl: 7; 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 415a543a0..7bd500ae2 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 @@ -783,7 +783,6 @@ static void btc_ble_mesh_heartbeat_msg_recv_cb(u8_t hops, u16_t feature) return; } -#if CONFIG_BLE_MESH_NODE #if CONFIG_BLE_MESH_LOW_POWER static void btc_ble_mesh_lpn_cb(u16_t friend_addr, bool established) { @@ -831,7 +830,6 @@ void btc_ble_mesh_friend_cb(bool establish, u16_t lpn_addr, u8_t reason) return; } #endif /* CONFIG_BLE_MESH_FRIEND */ -#endif /* CONFIG_BLE_MESH_NODE */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT static void btc_ble_mesh_proxy_client_adv_recv_cb(const bt_mesh_addr_t *addr, @@ -1507,12 +1505,6 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) arg->mesh_init.prov->link_close_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_link_close_cb; arg->mesh_init.prov->complete_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_complete_cb; arg->mesh_init.prov->reset_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_reset_cb; -#if CONFIG_BLE_MESH_LOW_POWER - bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb); -#endif /* CONFIG_BLE_MESH_LOW_POWER */ -#if CONFIG_BLE_MESH_FRIEND - bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb); -#endif /* CONFIG_BLE_MESH_FRIEND */ #endif /* CONFIG_BLE_MESH_NODE */ #if CONFIG_BLE_MESH_PROVISIONER arg->mesh_init.prov->provisioner_prov_read_oob_pub_key = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_read_oob_pub_key_cb; @@ -1523,6 +1515,12 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) arg->mesh_init.prov->provisioner_prov_comp = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_complete_cb; bt_mesh_prov_adv_pkt_cb_register(btc_ble_mesh_provisioner_recv_unprov_adv_pkt_cb); #endif /* CONFIG_BLE_MESH_PROVISIONER */ +#if CONFIG_BLE_MESH_LOW_POWER + bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb); +#endif /* CONFIG_BLE_MESH_LOW_POWER */ +#if CONFIG_BLE_MESH_FRIEND + bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb); +#endif /* CONFIG_BLE_MESH_FRIEND */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT bt_mesh_proxy_client_set_adv_recv_cb(btc_ble_mesh_proxy_client_adv_recv_cb); bt_mesh_proxy_client_set_conn_cb(btc_ble_mesh_proxy_client_connect_cb); diff --git a/components/bt/esp_ble_mesh/mesh_common/include/mesh_buf.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_buf.h index 6f1991dcc..e32569589 100644 --- a/components/bt/esp_ble_mesh/mesh_common/include/mesh_buf.h +++ b/components/bt/esp_ble_mesh/mesh_common/include/mesh_buf.h @@ -168,6 +168,19 @@ static inline void net_buf_simple_reset(struct net_buf_simple *buf) buf->data = buf->__buf; } +/** + * Clone buffer state, using the same data buffer. + * + * Initializes a buffer to point to the same data as an existing buffer. + * Allows operations on the same data without altering the length and + * offset of the original. + * + * @param original Buffer to clone. + * @param clone The new clone. + */ +void net_buf_simple_clone(const struct net_buf_simple *original, + struct net_buf_simple *clone); + /** * @brief Prepare data to be added at the end of the buffer * @@ -963,6 +976,20 @@ static inline void *net_buf_user_data(struct net_buf *buf) */ #define net_buf_pull(buf, len) net_buf_simple_pull(&(buf)->b, len) +/** + * @def net_buf_pull_mem + * @brief Remove data from the beginning of the buffer. + * + * Removes data from the beginning of the buffer by modifying the data + * pointer and buffer length. + * + * @param buf Buffer to update. + * @param len Number of bytes to remove. + * + * @return Pointer to the old beginning of the buffer data. + */ +#define net_buf_pull_mem(buf, len) net_buf_simple_pull_mem(&(buf)->b, len) + /** * @def net_buf_pull_u8 * @brief Remove a 8-bit value from the beginning of the buffer @@ -1052,6 +1079,180 @@ static inline void *net_buf_user_data(struct net_buf *buf) */ #define net_buf_headroom(buf) net_buf_simple_headroom(&(buf)->b) +/** + * @def net_buf_tail + * @brief Get the tail pointer for a buffer. + * + * Get a pointer to the end of the data in a buffer. + * + * @param buf Buffer. + * + * @return Tail pointer for the buffer. + */ +#define net_buf_tail(buf) net_buf_simple_tail(&(buf)->b) + +/** + * @brief Find the last fragment in the fragment list. + * + * @return Pointer to last fragment in the list. + */ +struct net_buf *net_buf_frag_last(struct net_buf *frags); + +/** + * @brief Insert a new fragment to a chain of bufs. + * + * Insert a new fragment into the buffer fragments list after the parent. + * + * Note: This function takes ownership of the fragment reference so the + * caller is not required to unref. + * + * @param parent Parent buffer/fragment. + * @param frag Fragment to insert. + */ +void net_buf_frag_insert(struct net_buf *parent, struct net_buf *frag); + +/** + * @brief Add a new fragment to the end of a chain of bufs. + * + * Append a new fragment into the buffer fragments list. + * + * Note: This function takes ownership of the fragment reference so the + * caller is not required to unref. + * + * @param head Head of the fragment chain. + * @param frag Fragment to add. + * + * @return New head of the fragment chain. Either head (if head + * was non-NULL) or frag (if head was NULL). + */ +struct net_buf *net_buf_frag_add(struct net_buf *head, struct net_buf *frag); + +/** + * @brief Delete existing fragment from a chain of bufs. + * + * @param parent Parent buffer/fragment, or NULL if there is no parent. + * @param frag Fragment to delete. + * + * @return Pointer to the buffer following the fragment, or NULL if it + * had no further fragments. + */ +#if defined(CONFIG_BLE_MESH_NET_BUF_LOG) +struct net_buf *net_buf_frag_del_debug(struct net_buf *parent, + struct net_buf *frag, + const char *func, int line); +#define net_buf_frag_del(_parent, _frag) \ + net_buf_frag_del_debug(_parent, _frag, __func__, __LINE__) +#else +struct net_buf *net_buf_frag_del(struct net_buf *parent, struct net_buf *frag); +#endif + +/** + * @brief Copy bytes from net_buf chain starting at offset to linear buffer + * + * Copy (extract) @a len bytes from @a src net_buf chain, starting from @a + * offset in it, to a linear buffer @a dst. Return number of bytes actually + * copied, which may be less than requested, if net_buf chain doesn't have + * enough data, or destination buffer is too small. + * + * @param dst Destination buffer + * @param dst_len Destination buffer length + * @param src Source net_buf chain + * @param offset Starting offset to copy from + * @param len Number of bytes to copy + * @return number of bytes actually copied + */ +size_t net_buf_linearize(void *dst, size_t dst_len, + struct net_buf *src, size_t offset, size_t len); + +/** + * @typedef net_buf_allocator_cb + * @brief Network buffer allocator callback. + * + * @details The allocator callback is called when net_buf_append_bytes + * needs to allocate a new net_buf. + * + * @param timeout Affects the action taken should the net buf pool be empty. + * If K_NO_WAIT, then return immediately. If K_FOREVER, then + * wait as long as necessary. Otherwise, wait up to the specified + * number of milliseconds before timing out. + * @param user_data The user data given in net_buf_append_bytes call. + * @return pointer to allocated net_buf or NULL on error. + */ +typedef struct net_buf *(*net_buf_allocator_cb)(s32_t timeout, void *user_data); + +/** + * @brief Append data to a list of net_buf + * + * @details Append data to a net_buf. If there is not enough space in the + * net_buf then more net_buf will be added, unless there are no free net_buf + * and timeout occurs. + * + * @param buf Network buffer. + * @param len Total length of input data + * @param value Data to be added + * @param timeout Timeout is passed to the net_buf allocator callback. + * @param allocate_cb When a new net_buf is required, use this callback. + * @param user_data A user data pointer to be supplied to the allocate_cb. + * This pointer is can be anything from a mem_pool or a net_pkt, the + * logic is left up to the allocate_cb function. + * + * @return Length of data actually added. This may be less than input + * length if other timeout than K_FOREVER was used, and there + * were no free fragments in a pool to accommodate all data. + */ +size_t net_buf_append_bytes(struct net_buf *buf, size_t len, + const void *value, s32_t timeout, + net_buf_allocator_cb allocate_cb, void *user_data); + +/** + * @brief Skip N number of bytes in a net_buf + * + * @details Skip N number of bytes starting from fragment's offset. If the total + * length of data is placed in multiple fragments, this function will skip from + * all fragments until it reaches N number of bytes. Any fully skipped buffers + * are removed from the net_buf list. + * + * @param buf Network buffer. + * @param len Total length of data to be skipped. + * + * @return Pointer to the fragment or + * NULL and pos is 0 after successful skip, + * NULL and pos is 0xffff otherwise. + */ +static inline struct net_buf *net_buf_skip(struct net_buf *buf, size_t len) +{ + while (buf && len--) { + net_buf_pull_u8(buf); + if (!buf->len) { + buf = net_buf_frag_del(NULL, buf); + } + } + + return buf; +} + +/** + * @brief Calculate amount of bytes stored in fragments. + * + * Calculates the total amount of data stored in the given buffer and the + * fragments linked to it. + * + * @param buf Buffer to start off with. + * + * @return Number of bytes in the buffer and its fragments. + */ +static inline size_t net_buf_frags_len(struct net_buf *buf) +{ + size_t bytes = 0; + + while (buf) { + bytes += buf->len; + buf = buf->frags; + } + + return bytes; +} + /** * @} */ diff --git a/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c b/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c index 885c489f5..2cb31d6d5 100644 --- a/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c +++ b/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c @@ -31,6 +31,12 @@ static inline struct net_buf *pool_get_uninit(struct net_buf_pool *pool, return buf; } +void net_buf_simple_clone(const struct net_buf_simple *original, + struct net_buf_simple *clone) +{ + memcpy(clone, original, sizeof(struct net_buf_simple)); +} + void *net_buf_simple_add(struct net_buf_simple *buf, size_t len) { u8_t *tail = net_buf_simple_tail(buf); @@ -447,4 +453,143 @@ struct net_buf *net_buf_alloc_fixed(struct net_buf_pool *pool, s32_t timeout) return net_buf_alloc_len(pool, fixed->data_size, timeout); } -#endif \ No newline at end of file +#endif + +struct net_buf *net_buf_frag_last(struct net_buf *buf) +{ + NET_BUF_ASSERT(buf); + + while (buf->frags) { + buf = buf->frags; + } + + return buf; +} + +void net_buf_frag_insert(struct net_buf *parent, struct net_buf *frag) +{ + NET_BUF_ASSERT(parent); + NET_BUF_ASSERT(frag); + + if (parent->frags) { + net_buf_frag_last(frag)->frags = parent->frags; + } + /* Take ownership of the fragment reference */ + parent->frags = frag; +} + +struct net_buf *net_buf_frag_add(struct net_buf *head, struct net_buf *frag) +{ + NET_BUF_ASSERT(frag); + + if (!head) { + return net_buf_ref(frag); + } + + net_buf_frag_insert(net_buf_frag_last(head), frag); + + return head; +} + +#if defined(CONFIG_BLE_MESH_NET_BUF_LOG) +struct net_buf *net_buf_frag_del_debug(struct net_buf *parent, + struct net_buf *frag, + const char *func, int line) +#else +struct net_buf *net_buf_frag_del(struct net_buf *parent, struct net_buf *frag) +#endif +{ + struct net_buf *next_frag; + + NET_BUF_ASSERT(frag); + + if (parent) { + NET_BUF_ASSERT(parent->frags); + NET_BUF_ASSERT(parent->frags == frag); + parent->frags = frag->frags; + } + + next_frag = frag->frags; + + frag->frags = NULL; + +#if defined(CONFIG_BLE_MESH_NET_BUF_LOG) + net_buf_unref_debug(frag, func, line); +#else + net_buf_unref(frag); +#endif + + return next_frag; +} + +size_t net_buf_linearize(void *dst, size_t dst_len, struct net_buf *src, + size_t offset, size_t len) +{ + struct net_buf *frag; + size_t to_copy; + size_t copied; + + len = MIN(len, dst_len); + + frag = src; + + /* find the right fragment to start copying from */ + while (frag && offset >= frag->len) { + offset -= frag->len; + frag = frag->frags; + } + + /* traverse the fragment chain until len bytes are copied */ + copied = 0; + while (frag && len > 0) { + to_copy = MIN(len, frag->len - offset); + memcpy((u8_t *)dst + copied, frag->data + offset, to_copy); + + copied += to_copy; + + /* to_copy is always <= len */ + len -= to_copy; + frag = frag->frags; + + /* after the first iteration, this value will be 0 */ + offset = 0; + } + + return copied; +} + +/* This helper routine will append multiple bytes, if there is no place for + * the data in current fragment then create new fragment and add it to + * the buffer. It assumes that the buffer has at least one fragment. + */ +size_t net_buf_append_bytes(struct net_buf *buf, size_t len, + const void *value, s32_t timeout, + net_buf_allocator_cb allocate_cb, void *user_data) +{ + struct net_buf *frag = net_buf_frag_last(buf); + size_t added_len = 0; + const u8_t *value8 = value; + + do { + u16_t count = MIN(len, net_buf_tailroom(frag)); + + net_buf_add_mem(frag, value8, count); + len -= count; + added_len += count; + value8 += count; + + if (len == 0) { + return added_len; + } + + frag = allocate_cb(timeout, user_data); + if (!frag) { + return added_len; + } + + net_buf_frag_add(buf, frag); + } while (1); + + /* Unreachable */ + return 0; +} \ No newline at end of file diff --git a/components/bt/esp_ble_mesh/mesh_core/access.c b/components/bt/esp_ble_mesh/mesh_core/access.c index 43e6e746a..65b0f9129 100644 --- a/components/bt/esp_ble_mesh/mesh_core/access.c +++ b/components/bt/esp_ble_mesh/mesh_core/access.c @@ -227,7 +227,7 @@ static s32_t next_period(struct bt_mesh_model *mod) BT_DBG("Publishing took %ums", elapsed); - if (elapsed > period) { + if (elapsed >= period) { BT_WARN("Publication sending took longer than the period"); /* Return smallest positive number since 0 means disabled */ return K_MSEC(1); @@ -761,21 +761,21 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, u32_t opcode) { net_buf_simple_init(msg, 0); - if (opcode < 0x100) { - /* 1-byte OpCode */ + switch (BLE_MESH_MODEL_OP_LEN(opcode)) { + case 1: net_buf_simple_add_u8(msg, opcode); - return; - } - - if (opcode < 0x10000) { - /* 2-byte OpCode */ + break; + case 2: net_buf_simple_add_be16(msg, opcode); - return; + break; + case 3: + net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff)); + net_buf_simple_add_le16(msg, opcode & 0xffff); + break; + default: + BT_WARN("Unknown opcode format"); + break; } - - /* 3-byte OpCode */ - net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff)); - net_buf_simple_add_le16(msg, opcode & 0xffff); } static bool ready_to_send(u8_t role, u16_t dst) diff --git a/components/bt/esp_ble_mesh/mesh_core/adv.c b/components/bt/esp_ble_mesh/mesh_core/adv.c index c57853182..e61eb259b 100644 --- a/components/bt/esp_ble_mesh/mesh_core/adv.c +++ b/components/bt/esp_ble_mesh/mesh_core/adv.c @@ -606,7 +606,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi, { #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT - u16_t uuid; + u16_t uuid = 0x0; #endif if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) { diff --git a/components/bt/esp_ble_mesh/mesh_core/adv.h b/components/bt/esp_ble_mesh/mesh_core/adv.h index 821e37ef9..7d7cce63f 100644 --- a/components/bt/esp_ble_mesh/mesh_core/adv.h +++ b/components/bt/esp_ble_mesh/mesh_core/adv.h @@ -46,15 +46,10 @@ struct bt_mesh_adv { busy: 1; u8_t xmit; - union { - /* Address, used e.g. for Friend Queue messages */ - u16_t addr; - - /* For transport layer segment sending */ - struct { - u8_t attempts; - } seg; - }; + /* For transport layer segment sending */ + struct { + u8_t attempts; + } seg; }; typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id); diff --git a/components/bt/esp_ble_mesh/mesh_core/cfg_cli.c b/components/bt/esp_ble_mesh/mesh_core/cfg_cli.c index d1c04f604..044c7c9b1 100644 --- a/components/bt/esp_ble_mesh/mesh_core/cfg_cli.c +++ b/components/bt/esp_ble_mesh/mesh_core/cfg_cli.c @@ -29,6 +29,9 @@ #define CID_NVAL 0xffff +/* 2 byte dummy opcode for getting compile time buffer sizes. */ +#define DUMMY_2_BYTE_OP BLE_MESH_MODEL_OP_2(0xff, 0xff) + s32_t config_msg_timeout; static bt_mesh_config_client_t *cli; @@ -685,7 +688,7 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { int bt_mesh_cfg_comp_data_get(struct bt_mesh_msg_ctx *ctx, u8_t page) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_DEV_COMP_DATA_GET, 1); int err; if (!ctx || !ctx->addr) { @@ -707,7 +710,7 @@ int bt_mesh_cfg_comp_data_get(struct bt_mesh_msg_ctx *ctx, u8_t page) static int get_state_u8(struct bt_mesh_msg_ctx *ctx, u32_t op) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 0); int err; bt_mesh_model_msg_init(&msg, op); @@ -723,7 +726,7 @@ static int get_state_u8(struct bt_mesh_msg_ctx *ctx, u32_t op) static int set_state_u8(struct bt_mesh_msg_ctx *ctx, u32_t op, u8_t new_val) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 1); int err; bt_mesh_model_msg_init(&msg, op); @@ -804,7 +807,7 @@ int bt_mesh_cfg_gatt_proxy_set(struct bt_mesh_msg_ctx *ctx, u8_t val) int bt_mesh_cfg_relay_get(struct bt_mesh_msg_ctx *ctx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_GET, 0); int err; if (!ctx || !ctx->addr) { @@ -826,7 +829,7 @@ int bt_mesh_cfg_relay_get(struct bt_mesh_msg_ctx *ctx) int bt_mesh_cfg_relay_set(struct bt_mesh_msg_ctx *ctx, u8_t new_relay, u8_t new_transmit) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_SET, 2); int err; if (!ctx || !ctx->addr) { @@ -850,7 +853,7 @@ int bt_mesh_cfg_relay_set(struct bt_mesh_msg_ctx *ctx, u8_t new_relay, int bt_mesh_cfg_net_key_add(struct bt_mesh_msg_ctx *ctx, u16_t key_net_idx, const u8_t net_key[16]) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 18 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_ADD, 18); int err; if (!ctx || !ctx->addr || !net_key) { @@ -874,7 +877,7 @@ int bt_mesh_cfg_net_key_add(struct bt_mesh_msg_ctx *ctx, u16_t key_net_idx, int bt_mesh_cfg_app_key_add(struct bt_mesh_msg_ctx *ctx, u16_t key_net_idx, u16_t key_app_idx, const u8_t app_key[16]) { - NET_BUF_SIMPLE_DEFINE(msg, 1 + 19 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_ADD, 19); int err; if (!ctx || !ctx->addr || !app_key) { @@ -898,7 +901,7 @@ int bt_mesh_cfg_app_key_add(struct bt_mesh_msg_ctx *ctx, u16_t key_net_idx, int bt_mesh_cfg_mod_app_bind(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t mod_app_idx, u16_t mod_id, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 8 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_BIND, 8); int err; if (!ctx || !ctx->addr) { @@ -926,7 +929,7 @@ int bt_mesh_cfg_mod_app_bind(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, static int mod_sub(u32_t op, struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t sub_addr, u16_t mod_id, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 8 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 8); int err; bt_mesh_model_msg_init(&msg, op); @@ -976,7 +979,7 @@ int bt_mesh_cfg_mod_sub_overwrite(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, static int mod_sub_va(u32_t op, struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, const u8_t label[16], u16_t mod_id, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 22 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 22); int err; BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x label %s", @@ -1030,7 +1033,7 @@ int bt_mesh_cfg_mod_sub_va_overwrite(struct bt_mesh_msg_ctx *ctx, u16_t elem_add int bt_mesh_cfg_mod_pub_get(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t mod_id, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 6 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_GET, 6); int err; if (!ctx || !ctx->addr) { @@ -1058,7 +1061,7 @@ int bt_mesh_cfg_mod_pub_set(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t mod_id, u16_t cid, struct bt_mesh_cfg_mod_pub *pub) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 13 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_SET, 13); int err; if (!ctx || !ctx->addr || !pub) { @@ -1090,7 +1093,7 @@ int bt_mesh_cfg_mod_pub_set(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, int bt_mesh_cfg_hb_sub_set(struct bt_mesh_msg_ctx *ctx, struct bt_mesh_cfg_hb_sub *sub) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 5 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_SET, 5); int err; if (!ctx || !ctx->addr || !sub) { @@ -1114,7 +1117,7 @@ int bt_mesh_cfg_hb_sub_set(struct bt_mesh_msg_ctx *ctx, int bt_mesh_cfg_hb_sub_get(struct bt_mesh_msg_ctx *ctx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_GET, 0); int err; if (!ctx || !ctx->addr) { @@ -1136,7 +1139,7 @@ int bt_mesh_cfg_hb_sub_get(struct bt_mesh_msg_ctx *ctx) int bt_mesh_cfg_hb_pub_set(struct bt_mesh_msg_ctx *ctx, const struct bt_mesh_cfg_hb_pub *pub) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_SET, 9); int err; if (!ctx || !ctx->addr || !pub) { @@ -1163,7 +1166,7 @@ int bt_mesh_cfg_hb_pub_set(struct bt_mesh_msg_ctx *ctx, int bt_mesh_cfg_hb_pub_get(struct bt_mesh_msg_ctx *ctx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_GET, 0); int err; if (!ctx || !ctx->addr) { @@ -1184,7 +1187,7 @@ int bt_mesh_cfg_hb_pub_get(struct bt_mesh_msg_ctx *ctx) int bt_mesh_cfg_node_reset(struct bt_mesh_msg_ctx *ctx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_RESET, 0); int err; if (!ctx || !ctx->addr) { @@ -1207,7 +1210,7 @@ int bt_mesh_cfg_mod_pub_va_set(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t mod_id, u16_t cid, const u8_t label[16], struct bt_mesh_cfg_mod_pub *pub) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 27 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_VA_SET, 27); int err; if (!ctx || !ctx->addr || !label || !pub) { @@ -1239,7 +1242,7 @@ int bt_mesh_cfg_mod_pub_va_set(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, int bt_mesh_cfg_mod_sub_del_all(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t mod_id, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 6 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_DEL_ALL, 6); int err; if (!ctx || !ctx->addr) { @@ -1266,7 +1269,7 @@ int bt_mesh_cfg_mod_sub_del_all(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, static int mod_sub_get(u32_t op, struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t mod_id, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 6 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 6); int err; bt_mesh_model_msg_init(&msg, op); @@ -1305,7 +1308,7 @@ int bt_mesh_cfg_mod_sub_get_vnd(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, int bt_mesh_cfg_net_key_update(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, const u8_t net_key[16]) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 18 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_UPDATE, 18); int err; if (!ctx || !ctx->addr || !net_key) { @@ -1328,7 +1331,7 @@ int bt_mesh_cfg_net_key_update(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, int bt_mesh_cfg_net_key_delete(struct bt_mesh_msg_ctx *ctx, u16_t net_idx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_DEL, 2); int err; if (!ctx || !ctx->addr) { @@ -1350,7 +1353,7 @@ int bt_mesh_cfg_net_key_delete(struct bt_mesh_msg_ctx *ctx, u16_t net_idx) int bt_mesh_cfg_net_key_get(struct bt_mesh_msg_ctx *ctx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_GET, 0); int err; if (!ctx || !ctx->addr) { @@ -1372,7 +1375,7 @@ int bt_mesh_cfg_net_key_get(struct bt_mesh_msg_ctx *ctx) int bt_mesh_cfg_app_key_update(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u16_t app_idx, const u8_t app_key[16]) { - NET_BUF_SIMPLE_DEFINE(msg, 1 + 19 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_UPDATE, 19); int err; if (!ctx || !ctx->addr || !app_key) { @@ -1395,7 +1398,7 @@ int bt_mesh_cfg_app_key_update(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, int bt_mesh_cfg_app_key_delete(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u16_t app_idx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_DEL, 3); int err; if (!ctx || !ctx->addr) { @@ -1417,7 +1420,7 @@ int bt_mesh_cfg_app_key_delete(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u16_t int bt_mesh_cfg_app_key_get(struct bt_mesh_msg_ctx *ctx, u16_t net_idx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_GET, 2); int err; if (!ctx || !ctx->addr) { @@ -1440,7 +1443,7 @@ int bt_mesh_cfg_app_key_get(struct bt_mesh_msg_ctx *ctx, u16_t net_idx) static int node_identity_op(u32_t op, struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u8_t identity) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 3); int err; bt_mesh_model_msg_init(&msg, op); @@ -1477,7 +1480,7 @@ int bt_mesh_cfg_node_identity_set(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u8 int bt_mesh_cfg_mod_app_unbind(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t app_idx, u16_t mod_id, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 8 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_UNBIND, 8); int err; if (!ctx || !ctx->addr) { @@ -1505,7 +1508,7 @@ int bt_mesh_cfg_mod_app_unbind(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, static int mod_app_get(u32_t op, struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, u16_t mod_id, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 6 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 6); int err; bt_mesh_model_msg_init(&msg, op); @@ -1544,7 +1547,7 @@ int bt_mesh_cfg_mod_app_get_vnd(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr, static int kr_phase_op(u32_t op, struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u8_t transition) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 3); int err; bt_mesh_model_msg_init(&msg, op); @@ -1580,7 +1583,7 @@ int bt_mesh_cfg_kr_phase_set(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u8_t tr int bt_mesh_cfg_lpn_timeout_get(struct bt_mesh_msg_ctx *ctx, u16_t lpn_addr) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_LPN_TIMEOUT_GET, 2); int err; if (!ctx || !ctx->addr) { diff --git a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c index c7f72a07d..b3c2b2609 100644 --- a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c @@ -47,11 +47,7 @@ static struct bt_mesh_cfg_srv *conf; -static struct label { - u16_t ref; - u16_t addr; - u8_t uuid[16]; -} labels[CONFIG_BLE_MESH_LABEL_COUNT]; +static struct label labels[CONFIG_BLE_MESH_LABEL_COUNT]; static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem, bool primary) @@ -451,7 +447,7 @@ static void app_key_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4); u16_t key_net_idx, key_app_idx; u8_t status; @@ -486,7 +482,7 @@ static void app_key_update(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4); u16_t key_net_idx, key_app_idx; u8_t status; @@ -549,7 +545,7 @@ static void app_key_del(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4); u16_t key_net_idx, key_app_idx; struct bt_mesh_app_key *key; u8_t status; @@ -607,8 +603,8 @@ static void app_key_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4 + - IDX_LEN(CONFIG_BLE_MESH_APP_KEY_COUNT)); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_LIST, + 3 + IDX_LEN(CONFIG_BLE_MESH_APP_KEY_COUNT)); u16_t get_idx, i, prev; u8_t status; @@ -666,8 +662,7 @@ static void beacon_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_BEACON_STATUS, 1); BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, @@ -685,8 +680,7 @@ static void beacon_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_BEACON_STATUS, 1); struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -728,8 +722,7 @@ static void default_ttl_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_STATUS, 1); BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, @@ -747,8 +740,7 @@ static void default_ttl_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_STATUS, 1); struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -781,8 +773,7 @@ static void default_ttl_set(struct bt_mesh_model *model, static void send_gatt_proxy_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_GATT_PROXY_STATUS, 1); bt_mesh_model_msg_init(&msg, OP_GATT_PROXY_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_gatt_proxy_get()); @@ -878,8 +869,7 @@ static void net_transmit_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_TRANSMIT_STATUS, 1); BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, @@ -897,8 +887,7 @@ static void net_transmit_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_TRANSMIT_STATUS, 1); struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -931,8 +920,7 @@ static void relay_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_STATUS, 2); BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, @@ -951,8 +939,7 @@ static void relay_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_STATUS, 2); struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -1005,8 +992,7 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod, bool vnd, struct bt_mesh_model *mod, u8_t status, u8_t *mod_id) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 14 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_STATUS, 14); bt_mesh_model_msg_init(&msg, OP_MOD_PUB_STATUS); @@ -1162,25 +1148,61 @@ send_status: } } -#if CONFIG_BLE_MESH_LABEL_COUNT > 0 -static u8_t va_add(u8_t *label_uuid, u16_t *addr) +struct label *get_label(u16_t index) { - struct label *free_slot = NULL; + if (index >= ARRAY_SIZE(labels)) { + return NULL; + } + + return &labels[index]; +} + +#if CONFIG_BLE_MESH_LABEL_COUNT > 0 +static inline void va_store(struct label *store) +{ + bt_mesh_atomic_set_bit(store->flags, BLE_MESH_VA_CHANGED); + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { + bt_mesh_store_label(); + } +} + +static struct label *va_find(const u8_t *label_uuid, + struct label **free_slot) +{ + struct label *match = NULL; int i; + if (free_slot != NULL) { + *free_slot = NULL; + } + for (i = 0; i < ARRAY_SIZE(labels); i++) { - if (!labels[i].ref) { - free_slot = &labels[i]; + if (labels[i].ref == 0) { + if (free_slot != NULL) { + *free_slot = &labels[i]; + } continue; } if (!memcmp(labels[i].uuid, label_uuid, 16)) { - *addr = labels[i].addr; - labels[i].ref++; - return STATUS_SUCCESS; + match = &labels[i]; } } + return match; +} + +static u8_t va_add(u8_t *label_uuid, u16_t *addr) +{ + struct label *update, *free_slot = NULL; + + update = va_find(label_uuid, &free_slot); + if (update) { + update->ref++; + va_store(update); + return STATUS_SUCCESS; + } + if (!free_slot) { return STATUS_INSUFF_RESOURCES; } @@ -1192,23 +1214,25 @@ static u8_t va_add(u8_t *label_uuid, u16_t *addr) free_slot->ref = 1U; free_slot->addr = *addr; memcpy(free_slot->uuid, label_uuid, 16); + va_store(free_slot); return STATUS_SUCCESS; } static u8_t va_del(u8_t *label_uuid, u16_t *addr) { - int i; + struct label *update; - for (i = 0; i < ARRAY_SIZE(labels); i++) { - if (!memcmp(labels[i].uuid, label_uuid, 16)) { - if (addr) { - *addr = labels[i].addr; - } + update = va_find(label_uuid, NULL); + if (update) { + update->ref--; - labels[i].ref--; - return STATUS_SUCCESS; + if (addr) { + *addr = update->addr; } + + va_store(update); + return STATUS_SUCCESS; } if (addr) { @@ -1386,8 +1410,7 @@ static void send_mod_sub_status(struct bt_mesh_model *model, u16_t elem_addr, u16_t sub_addr, u8_t *mod_id, bool vnd) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_STATUS, 9); BT_DBG("status 0x%02x elem_addr 0x%04x sub_addr 0x%04x", status, elem_addr, sub_addr); @@ -1696,8 +1719,8 @@ static void mod_sub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 5 + 4 + - CONFIG_BLE_MESH_MODEL_GROUP_COUNT * 2); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_LIST, + 5 + CONFIG_BLE_MESH_MODEL_GROUP_COUNT * 2); struct bt_mesh_model *mod; struct bt_mesh_elem *elem; u16_t addr, id; @@ -1752,8 +1775,8 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 7 + 4 + - CONFIG_BLE_MESH_MODEL_GROUP_COUNT * 2); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_LIST_VND, + 7 + CONFIG_BLE_MESH_MODEL_GROUP_COUNT * 2); struct bt_mesh_model *mod; struct bt_mesh_elem *elem; u16_t company, addr, id; @@ -2145,8 +2168,7 @@ static void send_net_key_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, u16_t idx, u8_t status) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_STATUS, 3); bt_mesh_model_msg_init(&msg, OP_NET_KEY_STATUS); @@ -2379,8 +2401,8 @@ static void net_key_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, - 2 + 4 + IDX_LEN(CONFIG_BLE_MESH_SUBNET_COUNT)); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_LIST, + IDX_LEN(CONFIG_BLE_MESH_SUBNET_COUNT)); u16_t prev, i; bt_mesh_model_msg_init(&msg, OP_NET_KEY_LIST); @@ -2415,8 +2437,7 @@ static void node_identity_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4); struct bt_mesh_subnet *sub; u8_t node_id; u16_t idx; @@ -2454,8 +2475,7 @@ static void node_identity_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4); struct bt_mesh_subnet *sub; u8_t node_id; u16_t idx; @@ -2531,7 +2551,7 @@ static void mod_app_bind(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_STATUS, 9); u16_t elem_addr, key_app_idx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; @@ -2594,7 +2614,7 @@ static void mod_app_unbind(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_STATUS, 9); u16_t elem_addr, key_app_idx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; @@ -2652,7 +2672,11 @@ static void mod_app_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + KEY_LIST_LEN + 4); + NET_BUF_SIMPLE_DEFINE(msg, + MAX(BLE_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST, + 9 + KEY_LIST_LEN), + BLE_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST, + 9 + KEY_LIST_LEN))); struct bt_mesh_model *mod; struct bt_mesh_elem *elem; u8_t *mod_id, status; @@ -2720,8 +2744,7 @@ static void node_reset(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_RESET_STATUS, 0); BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, @@ -2745,8 +2768,7 @@ static void node_reset(struct bt_mesh_model *model, static void send_friend_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_FRIEND_STATUS, 1); struct bt_mesh_cfg_srv *cfg = model->user_data; bt_mesh_model_msg_init(&msg, OP_FRIEND_STATUS); @@ -2818,8 +2840,7 @@ static void lpn_timeout_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 5 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_LPN_TIMEOUT_STATUS, 5); struct bt_mesh_friend *frnd; u16_t lpn_addr; s32_t timeout; @@ -2864,8 +2885,7 @@ static void send_krp_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, u16_t idx, u8_t phase, u8_t status) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_KRP_STATUS, 4); bt_mesh_model_msg_init(&msg, OP_KRP_STATUS); @@ -3008,8 +3028,7 @@ static void hb_pub_send_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, u8_t status, struct hb_pub_param *orig_msg) { - /* Needed size: opcode (1 byte) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 1 + 10 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_STATUS, 10); struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status); @@ -3147,8 +3166,7 @@ failed: static void hb_sub_send_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, u8_t status) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_STATUS, 9); struct bt_mesh_cfg_srv *cfg = model->user_data; u16_t period; s64_t uptime; diff --git a/components/bt/esp_ble_mesh/mesh_core/foundation.h b/components/bt/esp_ble_mesh/mesh_core/foundation.h index d1ccd31ae..19bc96dd7 100644 --- a/components/bt/esp_ble_mesh/mesh_core/foundation.h +++ b/components/bt/esp_ble_mesh/mesh_core/foundation.h @@ -117,6 +117,17 @@ #define STATUS_UNSPECIFIED 0x10 #define STATUS_INVALID_BINDING 0x11 +enum { + BLE_MESH_VA_CHANGED, /* Label information changed */ +}; + +struct label { + u16_t ref; + u16_t addr; + u8_t uuid[16]; + bt_mesh_atomic_t flags[1]; +}; + int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary); int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary); @@ -129,6 +140,8 @@ void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat); void bt_mesh_attention(struct bt_mesh_model *model, u8_t time); +struct label *get_label(u16_t index); + u8_t *bt_mesh_label_uuid_get(u16_t addr); struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void); diff --git a/components/bt/esp_ble_mesh/mesh_core/friend.c b/components/bt/esp_ble_mesh/mesh_core/friend.c index 794eb2ca4..894e88cf5 100644 --- a/components/bt/esp_ble_mesh/mesh_core/friend.c +++ b/components/bt/esp_ble_mesh/mesh_core/friend.c @@ -26,19 +26,18 @@ #include "access.h" #include "foundation.h" #include "friend.h" +#include "client_common.h" +#include "provisioner_main.h" #ifdef CONFIG_BLE_MESH_FRIEND -#define FRIEND_BUF_SIZE (BLE_MESH_ADV_DATA_SIZE - BLE_MESH_NET_HDR_LEN) - /* We reserve one extra buffer for each friendship, since we need to be able * to resend the last sent PDU, which sits separately outside of the queue. */ #define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \ CONFIG_BLE_MESH_FRIEND_LPN_COUNT) -#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), \ - struct friend_adv, adv) +#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), struct friend_adv, adv) /* PDUs from Friend to the LPN should only be transmitted once with the * smallest possible interval (20ms). @@ -62,7 +61,7 @@ NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT, static struct friend_adv { struct bt_mesh_adv adv; - u64_t seq_auth; + u16_t app_idx; } adv_pool[FRIEND_BUF_COUNT]; enum { @@ -75,10 +74,22 @@ enum { static void (*friend_cb)(bool establish, u16_t lpn_addr, u8_t reason); +static struct bt_mesh_subnet *friend_subnet_get(u16_t net_idx) +{ + struct bt_mesh_subnet *sub = NULL; + if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { + sub = bt_mesh_subnet_get(net_idx); + } else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) { + sub = provisioner_subnet_get(net_idx); + } + + return sub; +} static struct bt_mesh_adv *adv_alloc(int id) { + adv_pool[id].app_idx = BLE_MESH_KEY_UNUSED; return &adv_pool[id].adv; } @@ -318,13 +329,7 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd, struct friend_pdu_info *info, struct net_buf_simple *sdu) { - struct bt_mesh_subnet *sub; - const u8_t *enc, *priv; struct net_buf *buf; - u8_t nid; - - sub = bt_mesh_subnet_get(frnd->net_idx); - __ASSERT_NO_MSG(sub != NULL); buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc, BLE_MESH_ADV_DATA, @@ -333,22 +338,7 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd, return NULL; } - BLE_MESH_ADV(buf)->addr = info->src; - FRIEND_ADV(buf)->seq_auth = TRANS_SEQ_AUTH_NVAL; - - /* Friend Offer needs master security credentials */ - if (info->ctl && TRANS_CTL_OP(sdu->data) == TRANS_CTL_OP_FRIEND_OFFER) { - enc = sub->keys[sub->kr_flag].enc; - priv = sub->keys[sub->kr_flag].privacy; - nid = sub->keys[sub->kr_flag].nid; - } else { - if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) { - BT_ERR("%s, friend_cred_get failed", __func__); - goto failed; - } - } - - net_buf_add_u8(buf, (nid | (info->iv_index & 1) << 7)); + net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */ if (info->ctl) { net_buf_add_u8(buf, info->ttl | 0x80); @@ -363,25 +353,187 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd, net_buf_add_mem(buf, sdu->data, sdu->len); - /* We re-encrypt and obfuscate using the received IVI rather than - * the normal TX IVI (which may be different) since the transport - * layer nonce includes the IVI. - */ - if (bt_mesh_net_encrypt(enc, &buf->b, info->iv_index, false)) { - BT_ERR("%s, Re-encrypting failed", __func__); - goto failed; - } - - if (bt_mesh_net_obfuscate(buf->data, info->iv_index, priv)) { - BT_ERR("%s, Re-obfuscating failed", __func__); - goto failed; - } - return buf; +} -failed: - net_buf_unref(buf); - return NULL; +struct unseg_app_sdu_meta { + struct bt_mesh_net_rx net; + const u8_t *key; + struct bt_mesh_subnet *subnet; + bool is_dev_key; + u8_t aid; + u8_t *ad; +}; + +static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd, + struct net_buf *buf, + struct unseg_app_sdu_meta *meta) +{ + u16_t app_idx = FRIEND_ADV(buf)->app_idx; + u8_t role; + int err; + + meta->subnet = friend_subnet_get(frnd->net_idx); + if (!meta->subnet) { + BT_ERR("Invalid subnet for unseg app sdu"); + return -EINVAL; + } + + role = (IS_ENABLED(CONFIG_BLE_MESH_NODE) && + bt_mesh_is_provisioned()) ? NODE : PROVISIONER; + + meta->is_dev_key = (app_idx == BLE_MESH_KEY_DEV); + bt_mesh_net_header_parse(&buf->b, &meta->net); + err = bt_mesh_app_key_get(meta->subnet, app_idx, &meta->key, + &meta->aid, role, meta->net.ctx.addr); + if (err) { + BT_ERR("Failed to get AppKey"); + return err; + } + + if (BLE_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) { + meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst); + if (!meta->ad) { + BT_ERR("Failed to get label uuid"); + return -ENOENT; + } + } else { + meta->ad = NULL; + } + + return 0; +} + +static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd, + struct net_buf *buf, + const struct unseg_app_sdu_meta *meta) +{ + struct net_buf_simple sdu; + + net_buf_simple_clone(&buf->b, &sdu); + net_buf_simple_pull(&sdu, 10); + sdu.len -= 4; + + return bt_mesh_app_decrypt(meta->key, meta->is_dev_key, 0, &sdu, &sdu, + meta->ad, meta->net.ctx.addr, + meta->net.ctx.recv_dst, meta->net.seq, + BLE_MESH_NET_IVI_TX); +} + +static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd, + struct net_buf *buf, + const struct unseg_app_sdu_meta *meta) +{ + struct net_buf_simple sdu; + + net_buf_simple_clone(&buf->b, &sdu); + net_buf_simple_pull(&sdu, 10); + sdu.len -= 4; + + return bt_mesh_app_encrypt(meta->key, meta->is_dev_key, 0, &sdu, + meta->ad, meta->net.ctx.addr, + meta->net.ctx.recv_dst, bt_mesh.seq, + BLE_MESH_NET_IVI_TX); +} + +static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, + struct net_buf *buf) +{ + struct unseg_app_sdu_meta meta; + int err; + + if (FRIEND_ADV(buf)->app_idx == BLE_MESH_KEY_UNUSED) { + return 0; + } + + err = unseg_app_sdu_unpack(frnd, buf, &meta); + if (err) { + return err; + } + + /* No need to reencrypt the message if the sequence number is + * unchanged. + */ + if (meta.net.seq == bt_mesh.seq) { + return 0; + } + + err = unseg_app_sdu_decrypt(frnd, buf, &meta); + if (err) { + BT_WARN("Decryption failed! %d", err); + return err; + } + + err = unseg_app_sdu_encrypt(frnd, buf, &meta); + if (err) { + BT_WARN("Re-encryption failed! %d", err); + } + + return err; +} + +static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf, + bool master_cred) +{ + struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx); + const u8_t *enc, *priv; + u32_t iv_index; + u16_t src; + u8_t nid; + int err; + + if (!sub) { + BT_ERR("Invalid subnet to encrypt friend pdu"); + return -EINVAL; + } + + if (master_cred) { + enc = sub->keys[sub->kr_flag].enc; + priv = sub->keys[sub->kr_flag].privacy; + nid = sub->keys[sub->kr_flag].nid; + } else { + if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) { + BT_ERR("friend_cred_get failed"); + return -ENOENT; + } + } + + src = sys_get_be16(&buf->data[5]); + + if (bt_mesh_elem_find(src)) { + u32_t seq; + + if (FRIEND_ADV(buf)->app_idx != BLE_MESH_KEY_UNUSED) { + err = unseg_app_sdu_prepare(frnd, buf); + if (err) { + return err; + } + } + + seq = bt_mesh_next_seq(); + buf->data[2] = seq >> 16; + buf->data[3] = seq >> 8; + buf->data[4] = seq; + iv_index = BLE_MESH_NET_IVI_TX; + FRIEND_ADV(buf)->app_idx = BLE_MESH_KEY_UNUSED; + } else { + u8_t ivi = (buf->data[0] >> 7); + iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi)); + } + + buf->data[0] = (nid | (iv_index & 1) << 7); + + if (bt_mesh_net_encrypt(enc, &buf->b, iv_index, false)) { + BT_ERR("Encrypting failed"); + return -EINVAL; + } + + if (bt_mesh_net_obfuscate(buf->data, iv_index, priv)) { + BT_ERR("Obfuscating failed"); + return -EINVAL; + } + + return 0; } static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd, @@ -389,7 +541,6 @@ static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd, struct net_buf_simple *sdu) { struct friend_pdu_info info; - u32_t seq; BT_DBG("LPN 0x%04x", frnd->lpn); @@ -401,10 +552,7 @@ static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd, info.ctl = 1U; info.ttl = 0U; - seq = bt_mesh_next_seq(); - info.seq[0] = seq >> 16; - info.seq[1] = seq >> 8; - info.seq[2] = seq; + memset(info.seq, 0, sizeof(info.seq)); info.iv_index = BLE_MESH_NET_IVI_TX; @@ -415,7 +563,7 @@ static struct net_buf *encode_update(struct bt_mesh_friend *frnd, u8_t md) { struct bt_mesh_ctl_friend_update *upd; NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*upd)); - struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx); + struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx); __ASSERT_NO_MSG(sub != NULL); @@ -450,6 +598,10 @@ static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact) return; } + if (encrypt_friend_pdu(frnd, buf, false)) { + return; + } + if (frnd->last) { BT_DBG("Discarding last PDU"); net_buf_unref(frnd->last); @@ -651,7 +803,7 @@ static void send_friend_clear(struct bt_mesh_friend *frnd) .send_ttl = BLE_MESH_TTL_MAX, }; struct bt_mesh_net_tx tx = { - .sub = &bt_mesh.sub[0], + .sub = friend_subnet_get(frnd->net_idx), .ctx = &ctx, .src = bt_mesh_primary_addr(), .xmit = bt_mesh_net_transmit_get(), @@ -663,6 +815,11 @@ static void send_friend_clear(struct bt_mesh_friend *frnd) BT_DBG("%s", __func__); + if (!tx.sub) { + BT_ERR("Invalid subnet for Friend Clear"); + return; + } + bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req, sizeof(req), NULL, &clear_sent_cb, frnd); } @@ -759,6 +916,10 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi) return; } + if (encrypt_friend_pdu(frnd, buf, true)) { + return; + } + frnd->counter++; if (frnd->last) { @@ -879,7 +1040,7 @@ init_friend: frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr); BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums", - frnd->lpn, rx->rssi, frnd->recv_delay, frnd->poll_to); + frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, frnd->poll_to); /** * Spec says: @@ -894,18 +1055,40 @@ init_friend: } k_delayed_work_submit(&frnd->timer, - offer_delay(frnd, rx->rssi, msg->criteria)); + offer_delay(frnd, rx->ctx.recv_rssi, + msg->criteria)); friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter, frnd->counter); - enqueue_offer(frnd, rx->rssi); + enqueue_offer(frnd, rx->ctx.recv_rssi); return 0; } +static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero) +{ + struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue); + struct net_buf_simple_state state; + u16_t buf_seq_zero; + u16_t buf_src; + + if (!buf) { + return false; + } + + net_buf_simple_save(&buf->b, &state); + net_buf_skip(buf, 5); /* skip IVI, NID, CTL, TTL, SEQ */ + buf_src = net_buf_pull_be16(buf); + net_buf_skip(buf, 3); /* skip DST, OP/AID */ + buf_seq_zero = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK); + net_buf_simple_restore(&buf->b, &state); + + return ((src == buf_src) && (seq_zero == buf_seq_zero)); +} + static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, - u16_t src, u64_t *seq_auth, + u16_t src, u16_t seq_zero, u8_t seg_count) { struct bt_mesh_friend_seg *unassigned = NULL; @@ -913,14 +1096,12 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { struct bt_mesh_friend_seg *seg = &frnd->seg[i]; - struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue); - if (buf && BLE_MESH_ADV(buf)->addr == src && - FRIEND_ADV(buf)->seq_auth == *seq_auth) { + if (is_seg(seg, src, seq_zero)) { return seg; } - if (!unassigned && !buf) { + if (!unassigned && !sys_slist_peek_head(&seg->queue)) { unassigned = seg; } } @@ -934,10 +1115,10 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, enum bt_mesh_friend_pdu_type type, - u8_t seg_count, struct net_buf *buf) + u16_t src, u8_t seg_count, + struct net_buf *buf) { struct bt_mesh_friend_seg *seg; - struct friend_adv *adv; BT_DBG("type %u", type); @@ -950,11 +1131,11 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, return; } - adv = FRIEND_ADV(buf); - seg = get_seg(frnd, BLE_MESH_ADV(buf)->addr, &adv->seq_auth, seg_count); + u16_t seq_zero = (((buf->data[10] << 8 | buf->data[11]) >> 2) & TRANS_SEQ_ZERO_MASK); + + seg = get_seg(frnd, src, seq_zero, seg_count); if (!seg) { - BT_ERR("%s, No free friend segment RX contexts for 0x%04x", - __func__, BLE_MESH_ADV(buf)->addr); + BT_ERR("No free friend segment RX contexts for 0x%04x", src); net_buf_unref(buf); return; } @@ -966,16 +1147,9 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, enqueue_update(frnd, 1); } - /* Only acks should have a valid SeqAuth in the Friend queue - * (otherwise we can't easily detect them there), so clear - * the SeqAuth information from the segments before merging. - */ - SYS_SLIST_FOR_EACH_CONTAINER(&seg->queue, buf, node) { - FRIEND_ADV(buf)->seq_auth = TRANS_SEQ_AUTH_NVAL; - frnd->queue_size++; - } - sys_slist_merge_slist(&frnd->queue, &seg->queue); + + frnd->queue_size += seg->seg_count; seg->seg_count = 0U; } else { /* Mark the buffer as having more to come after it */ @@ -1052,6 +1226,10 @@ static void friend_timeout(struct k_work *work) return; } + if (encrypt_friend_pdu(frnd, frnd->last, false)) { + return; + } + /* Clear the flag we use for segment tracking */ frnd->last->flags &= ~NET_BUF_FRAGS; frnd->last->frags = NULL; @@ -1094,6 +1272,42 @@ int bt_mesh_friend_init(void) return 0; } +static bool is_segack(struct net_buf *buf, u64_t *seqauth, u16_t src) +{ + struct net_buf_simple_state state; + bool found = false; + + if (buf->len != 16) { + return false; + } + + net_buf_simple_save(&buf->b, &state); + + net_buf_skip(buf, 1); /* skip IVI, NID */ + + if (!(net_buf_pull_u8(buf) >> 7)) { + goto end; + } + + net_buf_pull(buf, 3); /* skip SEQNUM */ + + if (src != net_buf_pull_be16(buf)) { + goto end; + } + + net_buf_skip(buf, 2); /* skip dst */ + + if (TRANS_CTL_OP((u8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) { + goto end; + } + + found = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK) == + (*seqauth & TRANS_SEQ_ZERO_MASK); +end: + net_buf_simple_restore(&buf->b, &state); + return found; +} + static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth, u16_t src) { @@ -1105,8 +1319,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth, cur != NULL; prev = cur, cur = sys_slist_peek_next(cur)) { struct net_buf *buf = (void *)cur; - if (BLE_MESH_ADV(buf)->addr == src && - FRIEND_ADV(buf)->seq_auth == *seq_auth) { + if (is_segack(buf, seq_auth, src)) { BT_DBG("Removing old ack from Friend Queue"); sys_slist_remove(&frnd->queue, prev, cur); @@ -1129,6 +1342,14 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, struct friend_pdu_info info; struct net_buf *buf; + /* Because of network loopback, tx packets will also be passed into + * this rx function. These packets have already been added to the + * queue, and should be ignored. + */ + if (bt_mesh_elem_find(rx->ctx.addr)) { + return; + } + BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size); if (type == BLE_MESH_FRIEND_PDU_SINGLE && seq_auth) { @@ -1158,11 +1379,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, return; } - if (seq_auth) { - FRIEND_ADV(buf)->seq_auth = *seq_auth; - } - - enqueue_friend_pdu(frnd, type, seg_count, buf); + enqueue_friend_pdu(frnd, type, info.src, seg_count, buf); BT_DBG("Queued message for LPN 0x%04x, queue_size %u", frnd->lpn, frnd->queue_size); @@ -1176,7 +1393,6 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, { struct friend_pdu_info info; struct net_buf *buf; - u32_t seq; BT_DBG("LPN 0x%04x", frnd->lpn); @@ -1190,10 +1406,9 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, info.ttl = tx->ctx->send_ttl; info.ctl = (tx->ctx->app_idx == BLE_MESH_KEY_UNUSED); - seq = bt_mesh_next_seq(); - info.seq[0] = seq >> 16; - info.seq[1] = seq >> 8; - info.seq[2] = seq; + info.seq[0] = (bt_mesh.seq >> 16); + info.seq[1] = (bt_mesh.seq >> 8); + info.seq[2] = bt_mesh.seq; info.iv_index = BLE_MESH_NET_IVI_TX; @@ -1203,11 +1418,15 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, return; } - if (seq_auth) { - FRIEND_ADV(buf)->seq_auth = *seq_auth; + if (type == BLE_MESH_FRIEND_PDU_SINGLE && !info.ctl) { + /* Unsegmented application packets may be reencrypted later, + * as they depend on the the sequence number being the same + * when encrypting in transport and network. + */ + FRIEND_ADV(buf)->app_idx = tx->ctx->app_idx; } - enqueue_friend_pdu(frnd, type, seg_count, buf); + enqueue_friend_pdu(frnd, type, info.src, seg_count, buf); BT_DBG("Queued message for LPN 0x%04x", frnd->lpn); } @@ -1270,17 +1489,11 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr, for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { struct bt_mesh_friend_seg *seg = &frnd->seg[i]; - if (seq_auth) { - struct net_buf *buf; - + if (seq_auth && is_seg(seg, addr, *seq_auth & TRANS_SEQ_ZERO_MASK)) { /* If there's a segment queue for this message then the * space verification has already happened. */ - buf = (void *)sys_slist_peek_head(&seg->queue); - if (buf && BLE_MESH_ADV(buf)->addr == addr && - FRIEND_ADV(buf)->seq_auth == *seq_auth) { - return true; - } + return true; } total += seg->seg_count; @@ -1454,18 +1667,8 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src, for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) { struct bt_mesh_friend_seg *seg = &frnd->seg[j]; - struct net_buf *buf; - buf = (void *)sys_slist_peek_head(&seg->queue); - if (!buf) { - continue; - } - - if (BLE_MESH_ADV(buf)->addr != src) { - continue; - } - - if (FRIEND_ADV(buf)->seq_auth != *seq_auth) { + if (!is_seg(seg, src, *seq_auth & TRANS_SEQ_ZERO_MASK)) { continue; } @@ -1473,8 +1676,19 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src, purge_buffers(&seg->queue); seg->seg_count = 0U; + break; } } } +void bt_mesh_friend_remove_lpn(u16_t lpn_addr) +{ + struct bt_mesh_friend *frnd; + + frnd = bt_mesh_friend_find(BLE_MESH_KEY_ANY, lpn_addr, false, false); + if (frnd) { + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE); + } +} + #endif /* CONFIG_BLE_MESH_FRIEND */ diff --git a/components/bt/esp_ble_mesh/mesh_core/friend.h b/components/bt/esp_ble_mesh/mesh_core/friend.h index c6ecf7e6c..8c1fbe57b 100644 --- a/components/bt/esp_ble_mesh/mesh_core/friend.h +++ b/components/bt/esp_ble_mesh/mesh_core/friend.h @@ -51,4 +51,6 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, int bt_mesh_friend_init(void); +void bt_mesh_friend_remove_lpn(u16_t lpn_addr); + #endif /* _FRIEND_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_core/health_cli.c b/components/bt/esp_ble_mesh/mesh_core/health_cli.c index ee32e9ddd..ba4b73575 100644 --- a/components/bt/esp_ble_mesh/mesh_core/health_cli.c +++ b/components/bt/esp_ble_mesh/mesh_core/health_cli.c @@ -235,7 +235,7 @@ const struct bt_mesh_model_op bt_mesh_health_cli_op[] = { int bt_mesh_health_attention_get(struct bt_mesh_msg_ctx *ctx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_GET, 0); int err; if (!ctx || !ctx->addr) { @@ -257,7 +257,7 @@ int bt_mesh_health_attention_get(struct bt_mesh_msg_ctx *ctx) int bt_mesh_health_attention_set(struct bt_mesh_msg_ctx *ctx, u8_t attention, bool need_ack) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_SET, 1); u32_t opcode; int err; @@ -285,7 +285,7 @@ int bt_mesh_health_attention_set(struct bt_mesh_msg_ctx *ctx, int bt_mesh_health_period_get(struct bt_mesh_msg_ctx *ctx) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_GET, 0); int err; if (!ctx || !ctx->addr) { @@ -307,7 +307,7 @@ int bt_mesh_health_period_get(struct bt_mesh_msg_ctx *ctx) int bt_mesh_health_period_set(struct bt_mesh_msg_ctx *ctx, u8_t divisor, bool need_ack) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_SET, 1); u32_t opcode; int err; @@ -336,7 +336,7 @@ int bt_mesh_health_period_set(struct bt_mesh_msg_ctx *ctx, int bt_mesh_health_fault_test(struct bt_mesh_msg_ctx *ctx, u16_t cid, u8_t test_id, bool need_ack) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_TEST, 3); u32_t opcode; int err; @@ -366,7 +366,7 @@ int bt_mesh_health_fault_test(struct bt_mesh_msg_ctx *ctx, int bt_mesh_health_fault_clear(struct bt_mesh_msg_ctx *ctx, u16_t cid, bool need_ack) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_CLEAR, 2); u32_t opcode; int err; @@ -394,7 +394,7 @@ int bt_mesh_health_fault_clear(struct bt_mesh_msg_ctx *ctx, int bt_mesh_health_fault_get(struct bt_mesh_msg_ctx *ctx, u16_t cid) { - NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_GET, 2); int err; if (!ctx || !ctx->addr) { diff --git a/components/bt/esp_ble_mesh/mesh_core/health_srv.c b/components/bt/esp_ble_mesh/mesh_core/health_srv.c index 344b62d10..6b039b6f4 100644 --- a/components/bt/esp_ble_mesh/mesh_core/health_srv.c +++ b/components/bt/esp_ble_mesh/mesh_core/health_srv.c @@ -227,8 +227,7 @@ static void health_fault_test(struct bt_mesh_model *model, static void send_attention_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_STATUS, 1); struct bt_mesh_health_srv *srv = model->user_data; u8_t time; @@ -286,8 +285,7 @@ static void attention_set(struct bt_mesh_model *model, static void send_health_period_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { - /* Needed size: opcode (2 bytes) + msg + MIC */ - NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); + BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_STATUS, 1); bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_STATUS); net_buf_simple_add_u8(&msg, model->pub->period_div); diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_access.h b/components/bt/esp_ble_mesh/mesh_core/include/mesh_access.h index 48b9a188b..8c387a681 100644 --- a/components/bt/esp_ble_mesh/mesh_core/include/mesh_access.h +++ b/components/bt/esp_ble_mesh/mesh_core/include/mesh_access.h @@ -140,6 +140,9 @@ struct bt_mesh_msg_ctx { /** Destination address of a received message. Not used for sending. */ u16_t recv_dst; + /** RSSI of received packet. Not used for sending. */ + s8_t recv_rssi; + /** Received TTL value. Not used for sending. */ u8_t recv_ttl: 7; @@ -185,6 +188,56 @@ struct bt_mesh_model_op { /** Helper to define an empty model array */ #define BLE_MESH_MODEL_NONE ((struct bt_mesh_model []){}) +/** Length of a short Mesh MIC. */ +#define BLE_MESH_MIC_SHORT 4 +/** Length of a long Mesh MIC. */ +#define BLE_MESH_MIC_LONG 8 + +/** @def BLE_MESH_MODEL_OP_LEN + * + * @brief Helper to determine the length of an opcode. + * + * @param _op Opcode. + */ +#define BLE_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3) + +/** @def BLE_MESH_MODEL_BUF_LEN + * + * @brief Helper for model message buffer length. + * + * Returns the length of a Mesh model message buffer, including the opcode + * length and a short MIC. + * + * @param _op Opcode of the message. + * @param _payload_len Length of the model payload. + */ +#define BLE_MESH_MODEL_BUF_LEN(_op, _payload_len) \ + (BLE_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BLE_MESH_MIC_SHORT) + +/** @def BLE_MESH_MODEL_BUF_LEN_LONG_MIC + * + * @brief Helper for model message buffer length. + * + * Returns the length of a Mesh model message buffer, including the opcode + * length and a long MIC. + * + * @param _op Opcode of the message. + * @param _payload_len Length of the model payload. + */ +#define BLE_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \ + (BLE_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BLE_MESH_MIC_LONG) + +/** @def BLE_MESH_MODEL_BUF_DEFINE + * + * @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE_DEFINE. + * + * @param _buf Buffer name. + * @param _op Opcode of the message. + * @param _payload_len Length of the model message payload. + */ +#define BLE_MESH_MODEL_BUF_DEFINE(_buf, _op, _payload_len) \ + NET_BUF_SIMPLE_DEFINE(_buf, BLE_MESH_MODEL_BUF_LEN(_op, (_payload_len))) + #define BLE_MESH_MODEL(_id, _op, _pub, _user_data) \ { \ .id = (_id), \ @@ -282,15 +335,15 @@ struct bt_mesh_model_pub { struct bt_mesh_model *mod; u16_t addr; /**< Publish Address. */ - u16_t key; /**< Publish AppKey Index. */ + u16_t key:12, /**< Publish AppKey Index. */ + cred:1; /**< Friendship Credentials Flag. */ u8_t ttl; /**< Publish Time to Live. */ u8_t retransmit; /**< Retransmit Count & Interval Steps. */ u8_t period; /**< Publish Period. */ - u16_t period_div: 4, /**< Divisor for the Period. */ - cred: 1, /**< Friendship Credentials Flag. */ - fast_period: 1, /**< Use FastPeriodDivisor */ - count: 3; /**< Retransmissions left. */ + u8_t period_div:4, /**< Divisor for the Period. */ + fast_period:1,/**< Use FastPeriodDivisor */ + count:3; /**< Retransmissions left. */ u32_t period_start; /**< Start of the current period. */ diff --git a/components/bt/esp_ble_mesh/mesh_core/lpn.c b/components/bt/esp_ble_mesh/mesh_core/lpn.c index 06358cac4..a99b28dc4 100644 --- a/components/bt/esp_ble_mesh/mesh_core/lpn.c +++ b/components/bt/esp_ble_mesh/mesh_core/lpn.c @@ -324,7 +324,7 @@ static int send_friend_req(struct bt_mesh_lpn *lpn) .criteria = LPN_CRITERIA, .recv_delay = LPN_RECV_DELAY, .poll_to = LPN_POLL_TO, - .prev_addr = lpn->old_friend, + .prev_addr = sys_cpu_to_be16(lpn->old_friend), .num_elem = comp->elem_count, .lpn_counter = sys_cpu_to_be16(lpn->counter), }; diff --git a/components/bt/esp_ble_mesh/mesh_core/main.c b/components/bt/esp_ble_mesh/mesh_core/main.c index 13dc03610..90b00e635 100644 --- a/components/bt/esp_ble_mesh/mesh_core/main.c +++ b/components/bt/esp_ble_mesh/mesh_core/main.c @@ -413,6 +413,10 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers) provisioner_pb_gatt_enable(); } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + bt_mesh_friend_init(); + } + provisioner_en = true; return 0; @@ -437,6 +441,10 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers) bt_mesh_scan_disable(); } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + bt_mesh_friend_clear_net_idx(BLE_MESH_KEY_ANY); + } + provisioner_en = false; return 0; diff --git a/components/bt/esp_ble_mesh/mesh_core/net.c b/components/bt/esp_ble_mesh/mesh_core/net.c index 2bfba51d4..d021d333c 100644 --- a/components/bt/esp_ble_mesh/mesh_core/net.c +++ b/components/bt/esp_ble_mesh/mesh_core/net.c @@ -789,12 +789,10 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, return err; } - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && - bt_mesh_proxy_relay(&buf->b, dst)) { - send_cb_finalize(cb, cb_data); - return 0; - } + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + bt_mesh_proxy_relay(&buf->b, dst)) { + send_cb_finalize(cb, cb_data); + return 0; } bt_mesh_adv_send(buf, cb, cb_data); @@ -935,8 +933,9 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, #endif /* Deliver to local network interface if necessary */ - if (bt_mesh_fixed_group_match(tx->ctx->addr) || - bt_mesh_elem_find(tx->ctx->addr)) { + if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned() && + (bt_mesh_fixed_group_match(tx->ctx->addr) || + bt_mesh_elem_find(tx->ctx->addr))) { if (cb && cb->start) { cb->start(0, 0, cb_data); } @@ -1122,18 +1121,14 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len, continue; } -#if CONFIG_BLE_MESH_NODE - if (bt_mesh_is_provisioned()) { #if (defined(CONFIG_BLE_MESH_LOW_POWER) || defined(CONFIG_BLE_MESH_FRIEND)) - if (!friend_decrypt(sub, data, data_len, rx, buf)) { - rx->friend_cred = 1; - rx->ctx.net_idx = sub->net_idx; - rx->sub = sub; - return true; - } -#endif + if (!friend_decrypt(sub, data, data_len, rx, buf)) { + rx->friend_cred = 1; + rx->ctx.net_idx = sub->net_idx; + rx->sub = sub; + return true; } -#endif /* CONFIG_BLE_MESH_NODE */ +#endif if (NID(data) == sub->keys[0].nid && !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy, @@ -1308,6 +1303,17 @@ done: #endif /* CONFIG_BLE_MESH_NODE */ +void bt_mesh_net_header_parse(struct net_buf_simple *buf, + struct bt_mesh_net_rx *rx) +{ + rx->old_iv = (IVI(buf->data) != (bt_mesh.iv_index & 0x01)); + rx->ctl = CTL(buf->data); + rx->ctx.recv_ttl = TTL(buf->data); + rx->seq = SEQ(buf->data); + rx->ctx.addr = SRC(buf->data); + rx->ctx.recv_dst = DST(buf->data); +} + int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if, struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) { @@ -1398,7 +1404,7 @@ void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi, enum bt_mesh_net_if net_if) { NET_BUF_SIMPLE_DEFINE(buf, 29); - struct bt_mesh_net_rx rx = { .rssi = rssi }; + struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi }; struct net_buf_simple_state state; BT_DBG("rssi %d net_if %u", rssi, net_if); diff --git a/components/bt/esp_ble_mesh/mesh_core/net.h b/components/bt/esp_ble_mesh/mesh_core/net.h index bc600cfd1..47657f495 100644 --- a/components/bt/esp_ble_mesh/mesh_core/net.h +++ b/components/bt/esp_ble_mesh/mesh_core/net.h @@ -224,6 +224,7 @@ enum { BLE_MESH_HB_PUB_PENDING, BLE_MESH_CFG_PENDING, BLE_MESH_MOD_PENDING, + BLE_MESH_VA_PENDING, /* Don't touch - intentionally last */ BLE_MESH_FLAG_COUNT, @@ -296,7 +297,6 @@ struct bt_mesh_net_rx { local_match: 1, /* Matched a local element */ friend_match: 1; /* Matched an LPN we're friends for */ u16_t msg_cache_idx; /* Index of entry in message cache */ - s8_t rssi; }; /* Encoding context for Network/Transport data */ @@ -366,6 +366,8 @@ u32_t bt_mesh_next_seq(void); void bt_mesh_net_start(void); void bt_mesh_net_init(void); +void bt_mesh_net_header_parse(struct net_buf_simple *buf, + struct bt_mesh_net_rx *rx); /* Friendship Credential Management */ struct friend_cred { 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 7b40331a0..8fc1d4b3c 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c @@ -28,6 +28,7 @@ #include "adv.h" #include "net.h" #include "access.h" +#include "friend.h" #include "provisioner_prov.h" #include "proxy_client.h" @@ -142,6 +143,10 @@ int provisioner_node_reset(int node_index) } } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + bt_mesh_friend_remove_lpn(node->unicast_addr); + } + osi_free(mesh_nodes[node_index]); mesh_nodes[node_index] = NULL; diff --git a/components/bt/esp_ble_mesh/mesh_core/proxy_server.c b/components/bt/esp_ble_mesh/mesh_core/proxy_server.c index f5d361e8f..319f0ad2f 100644 --- a/components/bt/esp_ble_mesh/mesh_core/proxy_server.c +++ b/components/bt/esp_ble_mesh/mesh_core/proxy_server.c @@ -917,16 +917,6 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); - if (client->filter_type == WHITELIST) { - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - return true; - } - } - - return false; - } - if (client->filter_type == BLACKLIST) { for (i = 0; i < ARRAY_SIZE(client->filter); i++) { if (client->filter[i] == addr) { @@ -937,6 +927,18 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, return true; } + if (addr == BLE_MESH_ADDR_ALL_NODES) { + return true; + } + + if (client->filter_type == WHITELIST) { + for (i = 0; i < ARRAY_SIZE(client->filter); i++) { + if (client->filter[i] == addr) { + return true; + } + } + } + return false; } diff --git a/components/bt/esp_ble_mesh/mesh_core/settings.c b/components/bt/esp_ble_mesh/mesh_core/settings.c index 8705b1c9a..57393b903 100644 --- a/components/bt/esp_ble_mesh/mesh_core/settings.c +++ b/components/bt/esp_ble_mesh/mesh_core/settings.c @@ -55,6 +55,8 @@ * key: "mesh/v/xxxx/b" -> write/read to set/get VENDOR MODEL Bind AppKey List * key: "mesh/v/xxxx/s" -> write/read to set/get VENDOR MODEL Subscription List * key: "mesh/v/xxxx/p" -> write/read to set/get VENDOR MODEL Publication + * key: "mesh/vaddr" -> write/read to set/get all virtual addresses + * key: "mesh/va/xxxx" -> write/read to set/get the "xxxx" virtual address */ #if CONFIG_BLE_MESH_SETTINGS @@ -142,6 +144,13 @@ struct mod_pub_val { cred: 1; }; +/* Virtual Address information */ +struct va_val { + u16_t ref; + u16_t addr; + u8_t uuid[16]; +} __packed; + /* We need this so we don't overwrite app-hardcoded values in case FCB * contains a history of changes but then has a NULL at the end. */ @@ -695,6 +704,66 @@ static int vnd_mod_set(const char *name) return model_set(true, name); } +#if CONFIG_BLE_MESH_LABEL_COUNT > 0 +static int va_set(const char *name) +{ + struct net_buf_simple *buf = NULL; + struct va_val va = {0}; + char get[16] = {'\0'}; + struct label *lab; + size_t length; + bool exist; + int err = 0; + u16_t i; + + BT_DBG("%s", __func__); + + buf = bt_mesh_get_core_settings_item(name); + if (!buf) { + return 0; + } + + length = buf->len; + + for (i = 0U; i < length / SETTINGS_ITEM_SIZE; i++) { + u16_t index = net_buf_simple_pull_le16(buf); + sprintf(get, "mesh/va/%04x", index); + + err = bt_mesh_load_core_settings(get, (u8_t *)&va, sizeof(va), &exist); + if (err) { + BT_ERR("%s, Failed to load virtual address %s", __func__, get); + goto free; + } + + if (exist == false) { + continue; + } + + if (va.ref == 0) { + BT_DBG("Ignore virtual address %s with ref = 0", get); + goto free; + } + + lab = get_label(index); + if (lab == NULL) { + BT_WARN("%s, Out of labels buffers", __func__); + err = -ENOBUFS; + goto free; + } + + memcpy(lab->uuid, va.uuid, 16); + lab->addr = va.addr; + lab->ref = va.ref; + + BT_DBG("Restore virtual address 0x%04x ref 0x%04x", index, lab->ref); + } + +free: + bt_mesh_free_buf(buf); + return err; +} +#endif + const struct bt_mesh_setting { const char *name; int (*func)(const char *name); @@ -709,6 +778,9 @@ const struct bt_mesh_setting { { "mesh/cfg", cfg_set }, { "mesh/sig", sig_mod_set }, { "mesh/vnd", vnd_mod_set }, +#if CONFIG_BLE_MESH_LABEL_COUNT > 0 + { "mesh/vaddr", va_set }, +#endif }; int settings_core_load(void) @@ -1331,6 +1403,52 @@ static void store_pending_mod(struct bt_mesh_model *model, } } +#define IS_VA_DEL(_label) ((_label)->ref == 0) +static void store_pending_va(void) +{ + struct va_val va = {0}; + char name[16] = {'\0'}; + struct label *lab; + u16_t i; + int err; + + for (i = 0U; (lab = get_label(i)) != NULL; i++) { + if (!bt_mesh_atomic_test_and_clear_bit(lab->flags, + BLE_MESH_VA_CHANGED)) { + continue; + } + + sprintf(name, "mesh/va/%04x", i); + + if (IS_VA_DEL(lab)) { + err = bt_mesh_save_core_settings(name, NULL, 0); + } else { + va.ref = lab->ref; + va.addr = lab->addr; + memcpy(va.uuid, lab->uuid, 16); + err = bt_mesh_save_core_settings(name, (const u8_t *)&va, sizeof(va)); + } + if (err) { + BT_ERR("%s, Failed to %s virtual address %s", __func__, + IS_VA_DEL(lab) ? "delete" : "store", name); + return; + } + + if (IS_VA_DEL(lab)) { + err = bt_mesh_remove_core_settings_item("mesh/vaddr", i); + } else { + err = bt_mesh_add_core_settings_item("mesh/vaddr", i); + } + if (err) { + BT_ERR("%s, Failed to %s 0x%04x in mesh/vaddr", __func__, + IS_VA_DEL(lab) ? "delete" : "store", i); + return; + } + + BT_DBG("%s virtual address 0x%04x", IS_VA_DEL(lab) ? "Delete" : "Store", i); + } +} + static void store_pending(struct k_work *work) { BT_DBG("%s", __func__); @@ -1386,6 +1504,10 @@ static void store_pending(struct k_work *work) bt_mesh_save_core_settings("mesh/vnd", NULL, 0); } } + + if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_VA_PENDING)) { + store_pending_va(); + } } void bt_mesh_store_rpl(struct bt_mesh_rpl *entry) @@ -1570,6 +1692,11 @@ void bt_mesh_store_mod_pub(struct bt_mesh_model *model) schedule_store(BLE_MESH_MOD_PENDING); } +void bt_mesh_store_label(void) +{ + schedule_store(BLE_MESH_VA_PENDING); +} + int settings_core_init(void) { BT_DBG("%s", __func__); diff --git a/components/bt/esp_ble_mesh/mesh_core/settings.h b/components/bt/esp_ble_mesh/mesh_core/settings.h index 84b5e182b..3b1c4c696 100644 --- a/components/bt/esp_ble_mesh/mesh_core/settings.h +++ b/components/bt/esp_ble_mesh/mesh_core/settings.h @@ -28,6 +28,7 @@ void bt_mesh_store_cfg(void); void bt_mesh_store_mod_bind(struct bt_mesh_model *mod); void bt_mesh_store_mod_sub(struct bt_mesh_model *mod); void bt_mesh_store_mod_pub(struct bt_mesh_model *mod); +void bt_mesh_store_label(void); void bt_mesh_clear_net(void); void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub); diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.c b/components/bt/esp_ble_mesh/mesh_core/transport.c index 62d3a67ab..5b0a9a968 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.c +++ b/components/bt/esp_ble_mesh/mesh_core/transport.c @@ -139,32 +139,30 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, net_buf_add_mem(buf, sdu->data, sdu->len); - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { - if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, - tx->src, tx->ctx->addr, - NULL, 1)) { - if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - BT_ERR("Not enough space in Friend Queue"); - net_buf_unref(buf); - return -ENOBUFS; - } else { - BT_WARN("No space in Friend Queue"); - goto send; - } - } - - if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE, - NULL, 1, &buf->b) && - BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - /* PDUs for a specific Friend should only go - * out through the Friend Queue. - */ + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, + tx->src, tx->ctx->addr, + NULL, 1)) { + if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + BT_ERR("Not enough space in Friend Queue"); net_buf_unref(buf); - send_cb_finalize(cb, cb_data); - return 0; + return -ENOBUFS; + } else { + BT_WARN("No space in Friend Queue"); + goto send; } } + + if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE, + NULL, 1, &buf->b) && + BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + /* PDUs for a specific Friend should only go + * out through the Friend Queue. + */ + net_buf_unref(buf); + send_cb_finalize(cb, cb_data); + return 0; + } } send: @@ -371,7 +369,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, tx->ttl = net_tx->ctx->send_ttl; } - seq_zero = tx->seq_auth & 0x1fff; + seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK; BT_DBG("SeqZero 0x%04x", seq_zero); @@ -413,27 +411,25 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, net_buf_add_mem(seg, sdu->data, len); net_buf_simple_pull(sdu, len); - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { - enum bt_mesh_friend_pdu_type type; + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + enum bt_mesh_friend_pdu_type type; - if (seg_o == tx->seg_n) { - type = BLE_MESH_FRIEND_PDU_COMPLETE; - } else { - type = BLE_MESH_FRIEND_PDU_PARTIAL; - } + if (seg_o == tx->seg_n) { + type = BLE_MESH_FRIEND_PDU_COMPLETE; + } else { + type = BLE_MESH_FRIEND_PDU_PARTIAL; + } - if (bt_mesh_friend_enqueue_tx(net_tx, type, - &tx->seq_auth, - tx->seg_n + 1, - &seg->b) && - BLE_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) { - /* PDUs for a specific Friend should only go - * out through the Friend Queue. - */ - net_buf_unref(seg); - continue; - } + if (bt_mesh_friend_enqueue_tx(net_tx, type, + &tx->seq_auth, + tx->seg_n + 1, + &seg->b) && + BLE_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) { + /* PDUs for a specific Friend should only go + * out through the Friend Queue. + */ + net_buf_unref(seg); + continue; } } @@ -461,11 +457,9 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, send_cb_finalize(cb, cb_data); } - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && - bt_mesh_lpn_established()) { - bt_mesh_lpn_poll(); - } + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && + bt_mesh_lpn_established()) { + bt_mesh_lpn_poll(); } return 0; @@ -492,6 +486,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, { const u8_t *key = NULL; u8_t *ad, role; + u8_t aid; int err; if (net_buf_simple_tailroom(msg) < 4) { @@ -513,33 +508,14 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, return -EINVAL; } - if (tx->ctx->app_idx == BLE_MESH_KEY_DEV) { - key = bt_mesh_tx_devkey_get(role, tx->ctx->addr); - if (!key) { - BT_ERR("%s, Failed to get Device Key", __func__); - return -EINVAL; - } - - tx->aid = 0U; - } else { - struct bt_mesh_app_key *app_key = NULL; - - app_key = bt_mesh_tx_appkey_get(role, tx->ctx->app_idx, tx->ctx->net_idx); - if (!app_key) { - BT_ERR("%s, Failed to get AppKey", __func__); - return -EINVAL; - } - - if (tx->sub->kr_phase == BLE_MESH_KR_PHASE_2 && - app_key->updated) { - key = app_key->keys[1].val; - tx->aid = app_key->keys[1].id; - } else { - key = app_key->keys[0].val; - tx->aid = app_key->keys[0].id; - } + err = bt_mesh_app_key_get(tx->sub, tx->ctx->app_idx, &key, + &aid, role, tx->ctx->addr); + if (err) { + return err; } + tx->aid = aid; + if (!tx->ctx->send_rel || net_buf_simple_tailroom(msg) < 8) { tx->aszmic = 0U; } else { @@ -780,7 +756,7 @@ static struct seg_tx *seg_tx_lookup(u16_t seq_zero, u8_t obo, u16_t addr) for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { tx = &seg_tx[i]; - if ((tx->seq_auth & 0x1fff) != seq_zero) { + if ((tx->seq_auth & TRANS_SEQ_ZERO_MASK) != seq_zero) { continue; } @@ -818,7 +794,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr, seq_zero = net_buf_simple_pull_be16(buf); obo = seq_zero >> 15; - seq_zero = (seq_zero >> 2) & 0x1fff; + seq_zero = (seq_zero >> 2) & TRANS_SEQ_ZERO_MASK; if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match) { BT_DBG("Ack for LPN 0x%04x of this Friend", rx->ctx.recv_dst); @@ -922,49 +898,47 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr, return 0; } - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { - switch (ctl_op) { - case TRANS_CTL_OP_FRIEND_POLL: - return bt_mesh_friend_poll(rx, buf); - case TRANS_CTL_OP_FRIEND_REQ: - return bt_mesh_friend_req(rx, buf); - case TRANS_CTL_OP_FRIEND_CLEAR: - return bt_mesh_friend_clear(rx, buf); - case TRANS_CTL_OP_FRIEND_CLEAR_CFM: - return bt_mesh_friend_clear_cfm(rx, buf); - case TRANS_CTL_OP_FRIEND_SUB_ADD: - return bt_mesh_friend_sub_add(rx, buf); - case TRANS_CTL_OP_FRIEND_SUB_REM: - return bt_mesh_friend_sub_rem(rx, buf); - } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { + switch (ctl_op) { + case TRANS_CTL_OP_FRIEND_POLL: + return bt_mesh_friend_poll(rx, buf); + case TRANS_CTL_OP_FRIEND_REQ: + return bt_mesh_friend_req(rx, buf); + case TRANS_CTL_OP_FRIEND_CLEAR: + return bt_mesh_friend_clear(rx, buf); + case TRANS_CTL_OP_FRIEND_CLEAR_CFM: + return bt_mesh_friend_clear_cfm(rx, buf); + case TRANS_CTL_OP_FRIEND_SUB_ADD: + return bt_mesh_friend_sub_add(rx, buf); + case TRANS_CTL_OP_FRIEND_SUB_REM: + return bt_mesh_friend_sub_rem(rx, buf); } + } #if defined(CONFIG_BLE_MESH_LOW_POWER) - if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) { - return bt_mesh_lpn_friend_offer(rx, buf); - } - - if (rx->ctx.addr == bt_mesh.lpn.frnd) { - if (ctl_op == TRANS_CTL_OP_FRIEND_CLEAR_CFM) { - return bt_mesh_lpn_friend_clear_cfm(rx, buf); - } - - if (!rx->friend_cred) { - BT_WARN("Message from friend with wrong credentials"); - return -EINVAL; - } - - switch (ctl_op) { - case TRANS_CTL_OP_FRIEND_UPDATE: - return bt_mesh_lpn_friend_update(rx, buf); - case TRANS_CTL_OP_FRIEND_SUB_CFM: - return bt_mesh_lpn_friend_sub_cfm(rx, buf); - } - } -#endif /* CONFIG_BLE_MESH_LOW_POWER */ + if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) { + return bt_mesh_lpn_friend_offer(rx, buf); } + if (rx->ctx.addr == bt_mesh.lpn.frnd) { + if (ctl_op == TRANS_CTL_OP_FRIEND_CLEAR_CFM) { + return bt_mesh_lpn_friend_clear_cfm(rx, buf); + } + + if (!rx->friend_cred) { + BT_WARN("Message from friend with wrong credentials"); + return -EINVAL; + } + + switch (ctl_op) { + case TRANS_CTL_OP_FRIEND_UPDATE: + return bt_mesh_lpn_friend_update(rx, buf); + case TRANS_CTL_OP_FRIEND_SUB_CFM: + return bt_mesh_lpn_friend_sub_cfm(rx, buf); + } + } +#endif /* CONFIG_BLE_MESH_LOW_POWER */ + BT_WARN("Unhandled TransOpCode 0x%02x", ctl_op); return -ENOENT; @@ -1079,7 +1053,7 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst, .src = obo ? bt_mesh_primary_addr() : src, .xmit = bt_mesh_net_transmit_get(), }; - u16_t seq_zero = *seq_auth & 0x1fff; + u16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK; u8_t buf[6]; BT_DBG("SeqZero 0x%04x Block 0x%08x OBO %u", seq_zero, block, obo); @@ -1287,7 +1261,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, seq_zero = net_buf_simple_pull_be16(buf); seg_o = (seq_zero & 0x03) << 3; - seq_zero = (seq_zero >> 2) & 0x1fff; + seq_zero = (seq_zero >> 2) & TRANS_SEQ_ZERO_MASK; seg_n = net_buf_simple_pull_u8(buf); seg_o |= seg_n >> 5; seg_n &= 0x1f; @@ -1499,13 +1473,11 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) * requested the Friend to send them. The messages must also * be encrypted using the Friend Credentials. */ - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && - bt_mesh_lpn_established() && rx->net_if == BLE_MESH_NET_IF_ADV && - (!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) { - BT_WARN("Ignoring unexpected message in Low Power mode"); - return -EAGAIN; - } + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && + bt_mesh_lpn_established() && rx->net_if == BLE_MESH_NET_IF_ADV && + (!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) { + BT_WARN("Ignoring unexpected message in Low Power mode"); + return -EAGAIN; } /* Save the app-level state so the buffer can later be placed in @@ -1538,25 +1510,21 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) * timer, in which case we want to reset the timer at this point. * */ - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && - (bt_mesh_lpn_timer() || - (bt_mesh_lpn_established() && bt_mesh_lpn_waiting_update()))) { - bt_mesh_lpn_msg_received(rx); - } + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && + (bt_mesh_lpn_timer() || + (bt_mesh_lpn_established() && bt_mesh_lpn_waiting_update()))) { + bt_mesh_lpn_msg_received(rx); } net_buf_simple_restore(buf, &state); - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) { - if (seq_auth == TRANS_SEQ_AUTH_NVAL) { - bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL, - seg_count, buf); - } else { - bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth, - seg_count, buf); - } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) { + if (seq_auth == TRANS_SEQ_AUTH_NVAL) { + bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL, + seg_count, buf); + } else { + bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth, + seg_count, buf); } } @@ -1664,3 +1632,41 @@ void bt_mesh_heartbeat_send(void) bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb), NULL, NULL, NULL); } + +int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx, + const u8_t **key, u8_t *aid, u8_t role, u16_t dst) +{ + struct bt_mesh_app_key *app_key; + + if (app_idx == BLE_MESH_KEY_DEV) { + *key = bt_mesh_tx_devkey_get(role, dst); + if (!*key) { + BT_ERR("%s, Failed to get Device Key", __func__); + return -EINVAL; + } + + *aid = 0U; + return 0; + } + + if (!subnet) { + BT_ERR("%s, Invalid subnet", __func__); + return -EINVAL; + } + + app_key = bt_mesh_tx_appkey_get(role, app_idx, subnet->net_idx); + if (!app_key) { + BT_ERR("%s, Failed to get AppKey", __func__); + return -ENOENT; + } + + if (subnet->kr_phase == BLE_MESH_KR_PHASE_2 && app_key->updated) { + *key = app_key->keys[1].val; + *aid = app_key->keys[1].id; + } else { + *key = app_key->keys[0].val; + *aid = app_key->keys[0].id; + } + + return 0; +} diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.h b/components/bt/esp_ble_mesh/mesh_core/transport.h index 50a7aae1e..6fc81fdf2 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.h +++ b/components/bt/esp_ble_mesh/mesh_core/transport.h @@ -14,6 +14,7 @@ #define BLE_MESH_TX_SDU_MAX (CONFIG_BLE_MESH_TX_SEG_MAX * 12) +#define TRANS_SEQ_ZERO_MASK ((u16_t)BIT_MASK(13)) #define TRANS_CTL_OP_MASK ((u8_t)BIT_MASK(7)) #define TRANS_CTL_OP(data) ((data)[0] & TRANS_CTL_OP_MASK) #define TRANS_CTL_HDR(op, seg) ((op & TRANS_CTL_OP_MASK) | (seg << 7)) @@ -101,4 +102,7 @@ void bt_mesh_rpl_clear(void); void bt_mesh_heartbeat_send(void); +int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx, + const u8_t **key, u8_t *aid, u8_t role, u16_t dst); + #endif /* _TRANSPORT_H_ */