Bluetooth: Mesh: Add database for managing nodes and keys

Refactor the handling of network nodes and their keys into a separate
Mesh Configuration Database (CDB). This, not only creates a separation
of the local node and the other nodes, but also makes it possible to
implement functions to manage the whole, or at least parts of the mesh
network.

Signed-off-by: Tobias Svehagen <tobias.svehagen@gmail.com>
This commit is contained in:
Tobias Svehagen 2019-11-04 16:14:07 +01:00 committed by Johan Hedberg
commit 46a95f12ad
16 changed files with 1707 additions and 292 deletions

View file

@ -21,5 +21,6 @@
#include <bluetooth/mesh/cfg_cli.h>
#include <bluetooth/mesh/health_cli.h>
#include <bluetooth/mesh/proxy.h>
#include <bluetooth/mesh/cdb.h>
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_H_ */

View file

@ -0,0 +1,263 @@
/*
* Copyright (c) 2019 Tobias Svehagen
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_
#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_
#if defined(CONFIG_BT_MESH_CDB)
#define NODE_COUNT CONFIG_BT_MESH_CDB_NODE_COUNT
#define SUBNET_COUNT CONFIG_BT_MESH_CDB_SUBNET_COUNT
#define APP_KEY_COUNT CONFIG_BT_MESH_CDB_APP_KEY_COUNT
#else
#define NODE_COUNT 0
#define SUBNET_COUNT 0
#define APP_KEY_COUNT 0
#endif
enum {
BT_MESH_CDB_NODE_CONFIGURED,
BT_MESH_CDB_NODE_BLACKLISTED,
BT_MESH_CDB_NODE_FLAG_COUNT
};
struct bt_mesh_cdb_node {
u8_t uuid[16];
u16_t addr;
u16_t net_idx;
u8_t num_elem;
u8_t dev_key[16];
ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT);
};
struct bt_mesh_cdb_subnet {
u16_t net_idx;
bool kr_flag;
u8_t kr_phase;
struct {
u8_t net_key[16];
} keys[2];
};
struct bt_mesh_cdb_app_key {
u16_t net_idx;
u16_t app_idx;
struct {
u8_t app_key[16];
} keys[2];
};
enum {
BT_MESH_CDB_VALID,
BT_MESH_CDB_SUBNET_PENDING,
BT_MESH_CDB_KEYS_PENDING,
BT_MESH_CDB_NODES_PENDING,
BT_MESH_CDB_IVU_IN_PROGRESS,
BT_MESH_CDB_FLAG_COUNT,
};
struct bt_mesh_cdb {
u32_t iv_index;
ATOMIC_DEFINE(flags, BT_MESH_CDB_FLAG_COUNT);
struct bt_mesh_cdb_node nodes[NODE_COUNT];
struct bt_mesh_cdb_subnet subnets[SUBNET_COUNT];
struct bt_mesh_cdb_app_key app_keys[APP_KEY_COUNT];
};
extern struct bt_mesh_cdb bt_mesh_cdb;
/** @brief Create the Mesh Configuration Database.
*
* Create and initialize the Mesh Configuration Database. A primary subnet,
* ie one with NetIdx 0, will be added and the provided key will be used as
* NetKey for that subnet.
*
* @param key The NetKey to be used for the primary subnet.
*
* @return 0 on success or negative error code on failure.
*/
int bt_mesh_cdb_create(const u8_t key[16]);
/** @brief Clear the Mesh Configuration Database.
*
* Remove all nodes, subnets and app-keys stored in the database and mark
* the database as invalid. The data will be cleared from persistent storage
* if CONFIG_BT_SETTINGS is enabled.
*/
void bt_mesh_cdb_clear(void);
/** @brief Set and store the IV Index and IV Update flag.
*
* The IV Index stored in the CDB will be the one used during provisioning
* of new nodes. This function is generally only used from inside the stack.
*
* This function will store the data to persistent storage if
* CONFIG_BT_SETTINGS is enabled.
*
* @param iv_index The new IV Index to use.
* @param iv_update True if there is an ongoing IV Update procedure.
*/
void bt_mesh_cdb_iv_update(u32_t iv_index, bool iv_update);
/** @brief Allocate a node.
*
* Allocate a new node in the CDB.
*
* @param uuid UUID of the node.
* @param addr Address of the node's primary element. If 0, the lowest
* possible address available will be assigned to the node.
* @param num_elem Number of elements that the node has.
* @param net_idx NetIdx that the node was provisioned to.
*
* @return The new node or NULL if it cannot be allocated.
*/
struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const u8_t uuid[16], u16_t addr,
u8_t num_elem, u16_t net_idx);
/** @brief Delete a node.
*
* Delete a node from the CDB.
*
* @param node The node to be deleted.
* @param store If true, the node will be cleared from persistent storage.
*/
void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store);
/** @brief Get a node by address.
*
* Try to find the node that has the provided address assigned to one of its
* elements.
*
* @param addr Address of the element to look for.
*
* @return The node that has an element with address addr or NULL if no such
* node exists.
*/
struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(u16_t addr);
/** @brief Store node to persistent storage.
*
* @param node Node to be stored.
*/
void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node);
enum {
BT_MESH_CDB_ITER_STOP = 0,
BT_MESH_CDB_ITER_CONTINUE,
};
/** @typedef bt_mesh_cdb_node_func_t
* @brief Node iterator callback.
*
* @param node Node found.
* @param user_data Data given.
*
* @return BT_MESH_CDB_ITER_CONTINUE to continue to iterate through the nodes
* or BT_MESH_CDB_ITER_STOP to stop.
*/
typedef u8_t (*bt_mesh_cdb_node_func_t)(struct bt_mesh_cdb_node *node,
void *user_data);
/** @brief Node iterator.
*
* Iterate nodes in the Mesh Configuration Database. The callback function
* will only be called for valid, ie allocated, nodes.
*
* @param func Callback function.
* @param user_data Data to pass to the callback.
*/
void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data);
/** @brief Allocate a subnet.
*
* Allocate a new subnet in the CDB.
*
* @param net_idx NetIdx of the subnet.
*
* @return The new subnet or NULL if it cannot be allocated.
*/
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(u16_t net_idx);
/** @brief Delete a subnet.
*
* Delete a subnet from the CDB.
*
* @param sub The subnet to be deleted.
* @param store If true, the subnet will be cleared from persistent storage.
*/
void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store);
/** @brief Get a subnet by NetIdx
*
* Try to find the subnet with the specified NetIdx.
*
* @param net_idx NetIdx of the subnet to look for.
*
* @return The subnet with the specified NetIdx or NULL if no such subnet
* exists.
*/
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(u16_t net_idx);
/** @brief Store subnet to persistent storage.
*
* @param sub Subnet to be stored.
*/
void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub);
/** @brief Get the flags for a subnet
*
* @param sub The subnet to get flags for.
*
* @return The flags for the subnet.
*/
u8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub);
/** @brief Allocate an application key.
*
* Allocate a new application key in the CDB.
*
* @param net_idx NetIdx of NetKey that the application key is bound to.
* @param app_idx AppIdx of the application key.
*
* @return The new application key or NULL if it cannot be allocated.
*/
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(u16_t net_idx,
u16_t app_idx);
/** @brief Delete an application key.
*
* Delete an application key from the CDB.
*
* @param key The application key to be deleted.
* @param store If true, the key will be cleared from persistent storage.
*/
void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store);
/** @brief Get an application key by AppIdx
*
* Try to find the application key with the specified AppIdx.
*
* @param app_idx AppIdx of the application key to look for.
*
* @return The application key with the specified AppIdx or NULL if no such key
* exists.
*/
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(u16_t app_idx);
/** @brief Store application key to persistent storage.
*
* @param key Application key to be stored.
*/
void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key);
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */

View file

@ -190,10 +190,12 @@ struct bt_mesh_prov {
* the specified NetKeyIndex and primary element address.
*
* @param net_idx NetKeyIndex given during provisioning.
* @param uuid UUID of the added node
* @param addr Primary element address.
* @param num_elem Number of elements that this node has.
*/
void (*node_added)(u16_t net_idx, u16_t addr, u8_t num_elem);
void (*node_added)(u16_t net_idx, u8_t uuid[16], u16_t addr,
u8_t num_elem);
/** @brief Node has been reset.
*

View file

@ -33,5 +33,4 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH_SELF_TEST test.c)
zephyr_library_sources_ifdef(CONFIG_BT_MESH_SHELL shell.c)
zephyr_library_sources_ifdef(CONFIG_BT_MESH_PROVISIONER nodes.c)
zephyr_library_sources_ifdef(CONFIG_BT_MESH_CDB cdb.c)

View file

@ -37,17 +37,36 @@ config BT_MESH_PROVISIONER
help
Enable this option to have support for provisioning remote devices.
if BT_MESH_PROVISIONER
config BT_MESH_CDB
bool "Mesh Configuration Database [EXPERIMENTAL]"
config BT_MESH_NODE_COUNT
int "Maximum number of saved nodes per network"
if BT_MESH_CDB
config BT_MESH_CDB_NODE_COUNT
int "Maximum number of nodes in the database"
default 1
range 1 4096
help
This option specifies how many nodes each network can at most
save in the provisioning database.
save in the configuration database.
endif # BT_MESH_PROVISIONER
config BT_MESH_CDB_SUBNET_COUNT
int "Maximum number of subnets in the database"
default 1
range 1 4096
help
This option specifies how many subnets that can at most be
saved in the configuration database.
config BT_MESH_CDB_APP_KEY_COUNT
int "Maximum number of application keys in the database"
default 1
range 1 4096
help
This option specifies how many application keys that can at most
be saved in the configuration database.
endif # BT_MESH_CDB
if BT_CONN
@ -591,6 +610,12 @@ config BT_MESH_DEBUG_SETTINGS
help
Use this option to enable persistent settings debug logs.
config BT_MESH_DEBUG_CDB
bool "Configuration database debug"
depends on BT_MESH_CDB
help
Use this option to enable configuration database debug logs.
endif # BT_MESH_DEBUG
endif # BT_MESH

382
subsys/bluetooth/mesh/cdb.c Normal file
View file

@ -0,0 +1,382 @@
/*
* Copyright (c) 2019 Tobias Svehagen
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <string.h>
#include <bluetooth/mesh.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_CDB)
#define LOG_MODULE_NAME bt_mesh_cdb
#include "common/log.h"
#include "mesh.h"
#include "net.h"
#include "settings.h"
struct bt_mesh_cdb bt_mesh_cdb = {
.nodes = {
[0 ... (CONFIG_BT_MESH_CDB_NODE_COUNT - 1)] = {
.addr = BT_MESH_ADDR_UNASSIGNED,
}
},
.subnets = {
[0 ... (CONFIG_BT_MESH_CDB_SUBNET_COUNT - 1)] = {
.net_idx = BT_MESH_KEY_UNUSED,
}
},
.app_keys = {
[0 ... (CONFIG_BT_MESH_CDB_APP_KEY_COUNT - 1)] = {
.net_idx = BT_MESH_KEY_UNUSED,
}
},
};
/*
* Check if an address range from addr_start for addr_start + num_elem - 1 is
* free for use. When a conflict is found, next will be set to the next address
* available after the conflicting range and -EAGAIN will be returned.
*/
static int addr_is_free(u16_t addr_start, u8_t num_elem, u16_t *next)
{
u16_t addr_end = addr_start + num_elem - 1;
u16_t other_start, other_end;
int i;
if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
!BT_MESH_ADDR_IS_UNICAST(addr_end) ||
num_elem == 0) {
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
continue;
}
other_start = node->addr;
other_end = other_start + node->num_elem - 1;
if (!(addr_end < other_start || addr_start > other_end)) {
if (next) {
*next = other_end + 1;
}
return -EAGAIN;
}
}
return 0;
}
/*
* Find the lowest possible starting address that can fit num_elem elements. If
* a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
* returned. Otherwise the first address in the range is returned.
*
* NOTE: This is quite an ineffective algorithm as it might need to look
* through the array of nodes N+2 times. A more effective algorithm
* could be used if the nodes were stored in a sorted list.
*/
static u16_t find_lowest_free_addr(u8_t num_elem)
{
u16_t addr = 1, next;
int err, i;
/*
* It takes a maximum of node count + 2 to find a free address if there
* is any. +1 for our own address and +1 for making sure that the
* address range is valid.
*/
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) {
err = addr_is_free(addr, num_elem, &next);
if (err == 0) {
break;
} else if (err != -EAGAIN) {
addr = BT_MESH_ADDR_UNASSIGNED;
break;
}
addr = next;
}
return addr;
}
int bt_mesh_cdb_create(const u8_t key[16])
{
struct bt_mesh_cdb_subnet *sub;
if (atomic_test_and_set_bit(bt_mesh_cdb.flags,
BT_MESH_CDB_VALID)) {
return -EALREADY;
}
sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY);
if (sub == NULL) {
return -ENOMEM;
}
memcpy(sub->keys[0].net_key, key, 16);
bt_mesh_cdb.iv_index = 0;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cdb();
bt_mesh_store_cdb_subnet(sub);
}
return 0;
}
void bt_mesh_cdb_clear(void)
{
int i;
atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) {
bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true);
}
}
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) {
bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true);
}
}
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) {
bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true);
}
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cdb();
}
}
void bt_mesh_cdb_iv_update(u32_t iv_index, bool iv_update)
{
BT_DBG("Updating IV index to %d\n", iv_index);
bt_mesh_cdb.iv_index = iv_index;
atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS,
iv_update);
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cdb();
}
}
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(u16_t net_idx)
{
struct bt_mesh_cdb_subnet *sub;
int i;
if (bt_mesh_cdb_subnet_get(net_idx) != NULL) {
return NULL;
}
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
sub = &bt_mesh_cdb.subnets[i];
if (sub->net_idx != BT_MESH_KEY_UNUSED) {
continue;
}
sub->net_idx = net_idx;
return sub;
}
return NULL;
}
void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store)
{
BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_clear_cdb_subnet(sub);
}
sub->net_idx = BT_MESH_KEY_UNUSED;
memset(sub->keys, 0, sizeof(sub->keys));
}
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(u16_t net_idx)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
if (bt_mesh_cdb.subnets[i].net_idx == net_idx) {
return &bt_mesh_cdb.subnets[i];
}
}
return NULL;
}
void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub)
{
bt_mesh_store_cdb_subnet(sub);
}
u8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub)
{
u8_t flags = 0x00;
if (sub && sub->kr_flag) {
flags |= BT_MESH_NET_FLAG_KR;
}
if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) {
flags |= BT_MESH_NET_FLAG_IVU;
}
return flags;
}
struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const u8_t uuid[16], u16_t addr,
u8_t num_elem, u16_t net_idx)
{
int i;
if (addr == BT_MESH_ADDR_UNASSIGNED) {
addr = find_lowest_free_addr(num_elem);
if (addr == BT_MESH_ADDR_UNASSIGNED) {
return NULL;
}
} else if (addr_is_free(addr, num_elem, NULL) < 0) {
BT_DBG("Address range 0x%04x-0x%04x is not free", addr,
addr + num_elem - 1);
return NULL;
}
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
memcpy(node->uuid, uuid, 16);
node->addr = addr;
node->num_elem = num_elem;
node->net_idx = net_idx;
atomic_set(node->flags, 0);
return node;
}
}
return NULL;
}
void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store)
{
BT_DBG("Node addr 0x%04x store %u", node->addr, store);
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_clear_cdb_node(node);
}
node->addr = BT_MESH_ADDR_UNASSIGNED;
memset(node->dev_key, 0, sizeof(node->dev_key));
}
struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(u16_t addr)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
if (addr >= node->addr &&
addr <= node->addr + node->num_elem - 1) {
return node;
}
}
return NULL;
}
void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node)
{
bt_mesh_store_cdb_node(node);
}
void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) {
continue;
}
if (func(&bt_mesh_cdb.nodes[i], user_data) ==
BT_MESH_CDB_ITER_STOP) {
break;
}
}
}
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(u16_t net_idx,
u16_t app_idx)
{
struct bt_mesh_cdb_app_key *key;
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
key = &bt_mesh_cdb.app_keys[i];
if (key->net_idx != BT_MESH_KEY_UNUSED) {
continue;
}
key->net_idx = net_idx;
key->app_idx = app_idx;
return key;
}
return NULL;
}
void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store)
{
BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_clear_cdb_app_key(key);
}
key->net_idx = BT_MESH_ADDR_UNASSIGNED;
memset(key->keys, 0, sizeof(key->keys));
}
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(u16_t app_idx)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) {
struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i];
if (key->net_idx != BT_MESH_KEY_UNUSED &&
key->app_idx == app_idx) {
return key;
}
}
return NULL;
}
void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key)
{
bt_mesh_store_cdb_app_key(key);
}

View file

@ -59,6 +59,53 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
pb_gatt_enabled = false;
}
/*
* FIXME:
* Should net_key and iv_index be over-ridden?
*/
if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
const struct bt_mesh_comp *comp;
const struct bt_mesh_prov *prov;
struct bt_mesh_cdb_node *node;
if (!atomic_test_bit(bt_mesh_cdb.flags,
BT_MESH_CDB_VALID)) {
BT_ERR("No valid network");
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
return -EINVAL;
}
comp = bt_mesh_comp_get();
if (comp == NULL) {
BT_ERR("Failed to get node composition");
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
return -EINVAL;
}
if (!bt_mesh_cdb_subnet_get(net_idx)) {
BT_ERR("No subnet with idx %d", net_idx);
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
return -ENOENT;
}
prov = bt_mesh_prov_get();
node = bt_mesh_cdb_node_alloc(prov->uuid, addr,
comp->elem_count, net_idx);
if (node == NULL) {
BT_ERR("Failed to allocate database node");
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
return -ENOMEM;
}
addr = node->addr;
iv_index = bt_mesh_cdb.iv_index;
memcpy(node->dev_key, dev_key, 16);
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cdb_node(node);
}
}
err = bt_mesh_net_create(net_idx, flags, net_key, iv_index);
if (err) {
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);

View file

@ -83,13 +83,6 @@ struct bt_mesh_net bt_mesh = {
.net_idx = BT_MESH_KEY_UNUSED,
}
},
#if defined(CONFIG_BT_MESH_PROVISIONER)
.nodes = {
[0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
.net_idx = BT_MESH_KEY_UNUSED,
}
},
#endif
};
static u32_t dup_cache[4];
@ -703,6 +696,10 @@ do_update:
}
}
if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
bt_mesh_cdb_iv_update(iv_index, iv_update);
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_iv(false);
}

View file

@ -222,7 +222,6 @@ enum {
BT_MESH_CFG_PENDING,
BT_MESH_MOD_PENDING,
BT_MESH_VA_PENDING,
BT_MESH_NODES_PENDING,
/* Don't touch - intentionally last */
BT_MESH_FLAG_COUNT,
@ -255,10 +254,6 @@ struct bt_mesh_net {
u8_t dev_key[16];
#if defined(CONFIG_BT_MESH_PROVISIONER)
struct bt_mesh_node nodes[CONFIG_BT_MESH_NODE_COUNT];
#endif
struct bt_mesh_app_key app_keys[CONFIG_BT_MESH_APP_KEY_COUNT];
struct bt_mesh_subnet sub[CONFIG_BT_MESH_SUBNET_COUNT];

View file

@ -1,161 +0,0 @@
/*
* Copyright (c) 2019 Tobias Svehagen
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <string.h>
#include <bluetooth/mesh.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_PROV)
#define LOG_MODULE_NAME bt_mesh_node
#include "common/log.h"
#include "mesh.h"
#include "net.h"
#include "access.h"
#include "settings.h"
/*
* Check if an address range from addr_start for addr_start + num_elem - 1 is
* free for use. When a conflict is found, next will be set to the next address
* available after the conflicting range and -EAGAIN will be returned.
*/
static int addr_is_free(u16_t addr_start, u8_t num_elem, u16_t *next)
{
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
u16_t addr_end = addr_start + num_elem - 1;
u16_t other_start, other_end;
int i;
if (comp == NULL) {
return -EINVAL;
}
if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
!BT_MESH_ADDR_IS_UNICAST(addr_end) ||
num_elem == 0 || next == NULL) {
return -EINVAL;
}
other_start = bt_mesh_primary_addr();
other_end = other_start + comp->elem_count - 1;
/* Compare with local element addresses */
if (!(addr_end < other_start || addr_start > other_end)) {
*next = other_end + 1;
return -EAGAIN;
}
for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) {
struct bt_mesh_node *node = &bt_mesh.nodes[i];
if (node->net_idx == BT_MESH_KEY_UNUSED) {
continue;
}
other_start = node->addr;
other_end = other_start + node->num_elem - 1;
if (!(addr_end < other_start || addr_start > other_end)) {
*next = other_end + 1;
return -EAGAIN;
}
}
return 0;
}
/*
* Find the lowest possible starting address that can fit num_elem elements. If
* a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
* returned. Otherwise the first address in the range is returned.
*
* NOTE: This is quite an ineffective algorithm as it might need to look
* through the array of nodes N+2 times. A more effective algorithm
* could be used if the nodes were stored in a sorted list.
*/
static u16_t find_lowest_free_addr(u8_t num_elem)
{
u16_t addr = 1, next;
int err, i;
/*
* It takes a maximum of node count + 2 to find a free address if there
* is any. +1 for our own address and +1 for making sure that the
* address range is valid.
*/
for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes) + 2; ++i) {
err = addr_is_free(addr, num_elem, &next);
if (err == 0) {
break;
} else if (err != -EAGAIN) {
addr = BT_MESH_ADDR_UNASSIGNED;
break;
}
addr = next;
}
return addr;
}
struct bt_mesh_node *bt_mesh_node_find(u16_t addr)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) {
struct bt_mesh_node *node = &bt_mesh.nodes[i];
if (addr >= node->addr &&
addr <= node->addr + node->num_elem - 1) {
return node;
}
}
return NULL;
}
struct bt_mesh_node *bt_mesh_node_alloc(u16_t addr, u8_t num_elem,
u16_t net_idx)
{
int i;
BT_DBG("");
if (addr == BT_MESH_ADDR_UNASSIGNED) {
addr = find_lowest_free_addr(num_elem);
if (addr == BT_MESH_ADDR_UNASSIGNED) {
return NULL;
}
} else if (!addr_is_free(addr, num_elem, NULL)) {
return NULL;
}
for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) {
struct bt_mesh_node *node = &bt_mesh.nodes[i];
if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
node->addr = addr;
node->num_elem = num_elem;
node->net_idx = net_idx;
return node;
}
}
return NULL;
}
void bt_mesh_node_del(struct bt_mesh_node *node, bool store)
{
BT_DBG("Node addr 0x%04x store %u", node->addr, store);
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_clear_node(node);
}
node->addr = BT_MESH_ADDR_UNASSIGNED;
(void)memset(node->dev_key, 0, sizeof(node->dev_key));
}

View file

@ -1,10 +0,0 @@
/*
* Copyright (c) 2019 Tobias Svehagen
*
* SPDX-License-Identifier: Apache-2.0
*/
struct bt_mesh_node *bt_mesh_node_find(u16_t addr);
struct bt_mesh_node *bt_mesh_node_alloc(u16_t addr, u8_t num_elem,
u16_t net_idx);
void bt_mesh_node_del(struct bt_mesh_node *node, bool store);

View file

@ -34,7 +34,6 @@
#include "proxy.h"
#include "prov.h"
#include "settings.h"
#include "nodes.h"
/* 3 transmissions, 20ms interval */
#define PROV_XMIT BT_MESH_TRANSMIT(2, 20)
@ -131,10 +130,11 @@ enum {
#endif
struct provisioner_link {
struct bt_mesh_node *node;
struct bt_mesh_cdb_node *node;
u16_t addr;
u16_t net_idx;
u8_t attention_duration;
u8_t uuid[16];
};
struct prov_link {
@ -234,7 +234,7 @@ static int reset_state(void)
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
link.provisioner->node != NULL) {
bt_mesh_node_del(link.provisioner->node, false);
bt_mesh_cdb_node_del(link.provisioner->node, false);
}
#if defined(CONFIG_BT_MESH_PB_GATT)
@ -690,9 +690,10 @@ static void prov_capabilities(const u8_t *data)
return;
}
link.provisioner->node = bt_mesh_node_alloc(link.provisioner->addr,
data[0],
link.provisioner->net_idx);
link.provisioner->node =
bt_mesh_cdb_node_alloc(link.provisioner->uuid,
link.provisioner->addr, data[0],
link.provisioner->net_idx);
if (link.provisioner->node == NULL) {
prov_send_fail_msg(PROV_ERR_RESOURCES);
return;
@ -1122,7 +1123,7 @@ static void prov_input_complete(const u8_t *data)
static void send_prov_data(void)
{
PROV_BUF(pdu, 34);
struct bt_mesh_subnet *sub;
struct bt_mesh_cdb_subnet *sub;
u8_t session_key[16];
u8_t nonce[13];
int err;
@ -1155,7 +1156,7 @@ static void send_prov_data(void)
BT_DBG("DevKey: %s", bt_hex(link.provisioner->node->dev_key, 16));
sub = bt_mesh_subnet_get(link.provisioner->node->net_idx);
sub = bt_mesh_cdb_subnet_get(link.provisioner->node->net_idx);
if (sub == NULL) {
BT_ERR("No subnet with net_idx %u",
link.provisioner->node->net_idx);
@ -1164,10 +1165,10 @@ static void send_prov_data(void)
}
prov_buf_init(&pdu, PROV_DATA);
net_buf_simple_add_mem(&pdu, sub->keys[sub->kr_flag].net, 16);
net_buf_simple_add_mem(&pdu, sub->keys[sub->kr_flag].net_key, 16);
net_buf_simple_add_be16(&pdu, link.provisioner->node->net_idx);
net_buf_simple_add_u8(&pdu, bt_mesh_net_flags(sub));
net_buf_simple_add_be32(&pdu, bt_mesh.iv_index);
net_buf_simple_add_u8(&pdu, bt_mesh_cdb_subnet_flags(sub));
net_buf_simple_add_be32(&pdu, bt_mesh_cdb.iv_index);
net_buf_simple_add_be16(&pdu, link.provisioner->node->addr);
net_buf_simple_add(&pdu, 8); /* For MIC */
@ -1197,7 +1198,7 @@ static void prov_complete(const u8_t *data)
return;
}
struct bt_mesh_node *node = link.provisioner->node;
struct bt_mesh_cdb_node *node = link.provisioner->node;
#if defined(CONFIG_BT_MESH_PB_ADV)
u8_t reason = CLOSE_REASON_SUCCESS;
#endif
@ -1207,7 +1208,7 @@ static void prov_complete(const u8_t *data)
node->addr);
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_node(node);
bt_mesh_store_cdb_node(node);
}
link.provisioner->node = NULL;
@ -1218,7 +1219,10 @@ static void prov_complete(const u8_t *data)
bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
#endif
bt_mesh_prov_node_added(node->net_idx, node->addr, node->num_elem);
if (prov->node_added) {
prov->node_added(node->net_idx, node->uuid, node->addr,
node->num_elem);
}
/*
* According to mesh profile spec (5.3.1.4.3), the close message should
@ -1808,6 +1812,7 @@ int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
bt_rand(&link.id, sizeof(link.id));
link.tx.id = 0x7F;
memcpy(link.provisioner->uuid, uuid, 16);
link.provisioner->addr = addr;
link.provisioner->net_idx = net_idx;
link.provisioner->attention_duration = attention_duration;
@ -1951,13 +1956,6 @@ void bt_mesh_prov_complete(u16_t net_idx, u16_t addr)
}
}
void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
{
if (prov->node_added) {
prov->node_added(net_idx, addr, num_elem);
}
}
void bt_mesh_prov_reset(void)
{
if (prov->reset) {

View file

@ -32,19 +32,21 @@
#include "foundation.h"
#include "proxy.h"
#include "settings.h"
#include "nodes.h"
/* Tracking of what storage changes are pending for App and Net Keys. We
* track this in a separate array here instead of within the respective
* bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key
* gets deleted its struct becomes invalid and may be reused for other keys.
*/
static struct key_update {
struct key_update {
u16_t key_idx:12, /* AppKey or NetKey Index */
valid:1, /* 1 if this entry is valid, 0 if not */
app_key:1, /* 1 if this is an AppKey, 0 if a NetKey */
clear:1; /* 1 if key needs clearing, 0 if storing */
} key_updates[CONFIG_BT_MESH_APP_KEY_COUNT + CONFIG_BT_MESH_SUBNET_COUNT];
};
static struct key_update key_updates[CONFIG_BT_MESH_APP_KEY_COUNT +
CONFIG_BT_MESH_SUBNET_COUNT];
static struct k_delayed_work pending_store;
@ -124,11 +126,19 @@ struct va_val {
u8_t uuid[16];
} __packed;
struct cdb_net_val {
u32_t iv_index;
bool iv_update;
} __packed;
/* Node storage information */
struct node_val {
u16_t net_idx;
u8_t dev_key[16];
u8_t num_elem;
u8_t flags;
#define F_NODE_CONFIGURED 0x01
u8_t uuid[16];
u8_t dev_key[16];
} __packed;
struct node_update {
@ -136,10 +146,13 @@ struct node_update {
bool clear;
};
#if defined(CONFIG_BT_MESH_PROVISIONER)
static struct node_update node_updates[CONFIG_BT_MESH_NODE_COUNT];
#if defined(CONFIG_BT_MESH_CDB)
static struct node_update cdb_node_updates[CONFIG_BT_MESH_CDB_NODE_COUNT];
static struct key_update cdb_key_updates[CONFIG_BT_MESH_CDB_SUBNET_COUNT +
CONFIG_BT_MESH_CDB_APP_KEY_COUNT];
#else
static struct node_update node_updates[0];
static struct node_update cdb_node_updates[0];
static struct key_update cdb_key_updates[0];
#endif
/* We need this so we don't overwrite app-hardcoded values in case FCB
@ -758,11 +771,39 @@ static int va_set(const char *name, size_t len_rd,
}
#endif
#if defined(CONFIG_BT_MESH_PROVISIONER)
static int node_set(const char *name, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
#if defined(CONFIG_BT_MESH_CDB)
static int cdb_net_set(const char *name, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
{
struct bt_mesh_node *node;
struct cdb_net_val net;
int err;
if (len_rd == 0) {
BT_DBG("val (null)");
return 0;
}
err = mesh_x_set(read_cb, cb_arg, &net, sizeof(net));
if (err) {
BT_ERR("Failed to set \'cdb_net\'");
return err;
}
bt_mesh_cdb.iv_index = net.iv_index;
if (net.iv_update) {
atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS);
}
atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
return 0;
}
static int cdb_node_set(const char *name, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
{
struct bt_mesh_cdb_node *node;
struct node_val val;
u16_t addr;
int err;
@ -778,9 +819,9 @@ static int node_set(const char *name, size_t len_rd,
BT_DBG("val (null)");
BT_DBG("Deleting node 0x%04x", addr);
node = bt_mesh_node_find(addr);
node = bt_mesh_cdb_node_get(addr);
if (node) {
bt_mesh_node_del(node, false);
bt_mesh_cdb_node_del(node, false);
}
return 0;
@ -792,9 +833,10 @@ static int node_set(const char *name, size_t len_rd,
return err;
}
node = bt_mesh_node_find(addr);
node = bt_mesh_cdb_node_get(addr);
if (!node) {
node = bt_mesh_node_alloc(addr, val.num_elem, val.net_idx);
node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem,
val.net_idx);
}
if (!node) {
@ -802,12 +844,168 @@ static int node_set(const char *name, size_t len_rd,
return -ENOMEM;
}
memcpy(node->dev_key, &val.dev_key, 16);
if (val.flags & F_NODE_CONFIGURED) {
atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED);
}
memcpy(node->uuid, val.uuid, 16);
memcpy(node->dev_key, val.dev_key, 16);
BT_DBG("Node 0x%04x recovered from storage", addr);
return 0;
}
static int cdb_subnet_set(const char *name, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
{
struct bt_mesh_cdb_subnet *sub;
struct net_key_val key;
u16_t net_idx;
int err;
if (!name) {
BT_ERR("Insufficient number of arguments");
return -ENOENT;
}
net_idx = strtol(name, NULL, 16);
sub = bt_mesh_cdb_subnet_get(net_idx);
if (len_rd == 0) {
BT_DBG("val (null)");
if (!sub) {
BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
return -ENOENT;
}
BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
bt_mesh_cdb_subnet_del(sub, false);
return 0;
}
err = mesh_x_set(read_cb, cb_arg, &key, sizeof(key));
if (err) {
BT_ERR("Failed to set \'net-key\'");
return err;
}
if (sub) {
BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
sub->kr_flag = key.kr_flag;
sub->kr_phase = key.kr_phase;
memcpy(sub->keys[0].net_key, &key.val[0], 16);
memcpy(sub->keys[1].net_key, &key.val[1], 16);
return 0;
}
sub = bt_mesh_cdb_subnet_alloc(net_idx);
if (!sub) {
BT_ERR("No space to allocate a new subnet");
return -ENOMEM;
}
sub->kr_flag = key.kr_flag;
sub->kr_phase = key.kr_phase;
memcpy(sub->keys[0].net_key, &key.val[0], 16);
memcpy(sub->keys[1].net_key, &key.val[1], 16);
BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
return 0;
}
static int cdb_app_key_set(const char *name, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
{
struct bt_mesh_cdb_app_key *app;
struct app_key_val key;
u16_t app_idx;
int err;
if (!name) {
BT_ERR("Insufficient number of arguments");
return -ENOENT;
}
app_idx = strtol(name, NULL, 16);
if (len_rd == 0) {
BT_DBG("val (null)");
BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
app = bt_mesh_cdb_app_key_get(app_idx);
if (app) {
bt_mesh_cdb_app_key_del(app, false);
}
return 0;
}
err = mesh_x_set(read_cb, cb_arg, &key, sizeof(key));
if (err) {
BT_ERR("Failed to set \'app-key\'");
return err;
}
app = bt_mesh_cdb_app_key_get(app_idx);
if (!app) {
app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx);
}
if (!app) {
BT_ERR("No space for a new app key");
return -ENOMEM;
}
memcpy(app->keys[0].app_key, key.val[0], 16);
memcpy(app->keys[1].app_key, key.val[1], 16);
BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
return 0;
}
static int cdb_set(const char *name, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
{
int len;
const char *next;
if (!name) {
BT_ERR("Insufficient number of arguments");
return -ENOENT;
}
if (!strcmp(name, "Net")) {
return cdb_net_set(name, len_rd, read_cb, cb_arg);
}
len = settings_name_next(name, &next);
if (!next) {
BT_ERR("Insufficient number of arguments");
return -ENOENT;
}
if (!strncmp(name, "Node", len)) {
return cdb_node_set(next, len_rd, read_cb, cb_arg);
}
if (!strncmp(name, "Subnet", len)) {
return cdb_subnet_set(next, len_rd, read_cb, cb_arg);
}
if (!strncmp(name, "AppKey", len)) {
return cdb_app_key_set(next, len_rd, read_cb, cb_arg);
}
BT_WARN("Unknown module key %s", name);
return -ENOENT;
}
#endif
const struct mesh_setting {
@ -828,8 +1026,8 @@ const struct mesh_setting {
#if CONFIG_BT_MESH_LABEL_COUNT > 0
{ "Va", va_set },
#endif
#if defined(CONFIG_BT_MESH_PROVISIONER)
{ "Node", node_set },
#if defined(CONFIG_BT_MESH_CDB)
{ "cdb", cdb_set },
#endif
};
@ -975,8 +1173,7 @@ SETTINGS_STATIC_HANDLER_DEFINE(bt_mesh, "bt/mesh", NULL, mesh_set, mesh_commit,
#define GENERIC_PENDING_BITS (BIT(BT_MESH_KEYS_PENDING) | \
BIT(BT_MESH_HB_PUB_PENDING) | \
BIT(BT_MESH_CFG_PENDING) | \
BIT(BT_MESH_MOD_PENDING) | \
BIT(BT_MESH_NODES_PENDING))
BIT(BT_MESH_MOD_PENDING))
static void schedule_store(int flag)
{
@ -1360,17 +1557,55 @@ static void store_pending_keys(void)
}
}
static void store_node(struct bt_mesh_node *node)
static void clear_cdb(void)
{
int err;
err = settings_delete("bt/mesh/cdb/Net");
if (err) {
BT_ERR("Failed to clear Network");
} else {
BT_DBG("Cleared Network");
}
}
static void store_pending_cdb(void)
{
struct cdb_net_val net;
int err;
BT_DBG("");
net.iv_index = bt_mesh_cdb.iv_index;
net.iv_update = atomic_test_bit(bt_mesh_cdb.flags,
BT_MESH_CDB_IVU_IN_PROGRESS);
err = settings_save_one("bt/mesh/cdb/Net", &net, sizeof(net));
if (err) {
BT_ERR("Failed to store Network value");
} else {
BT_DBG("Stored Network value");
}
}
static void store_cdb_node(const struct bt_mesh_cdb_node *node)
{
struct node_val val;
char path[20];
char path[30];
int err;
val.net_idx = node->net_idx;
val.num_elem = node->num_elem;
val.flags = 0;
if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) {
val.flags |= F_NODE_CONFIGURED;
}
memcpy(val.uuid, node->uuid, 16);
memcpy(val.dev_key, node->dev_key, 16);
snprintk(path, sizeof(path), "bt/mesh/Node/%x", node->addr);
snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", node->addr);
err = settings_save_one(path, &val, sizeof(val));
if (err) {
@ -1380,14 +1615,14 @@ static void store_node(struct bt_mesh_node *node)
}
}
static void clear_node(u16_t addr)
static void clear_cdb_node(u16_t addr)
{
char path[20];
char path[30];
int err;
BT_DBG("Node 0x%04x", addr);
snprintk(path, sizeof(path), "bt/mesh/Node/%x", addr);
snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", addr);
err = settings_delete(path);
if (err) {
BT_ERR("Failed to clear Node 0x%04x", addr);
@ -1396,25 +1631,27 @@ static void clear_node(u16_t addr)
}
}
static void store_pending_nodes(void)
static void store_pending_cdb_nodes(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(node_updates); ++i) {
struct node_update *update = &node_updates[i];
for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) {
struct node_update *update = &cdb_node_updates[i];
if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
continue;
}
if (update->clear) {
clear_node(update->addr);
} else {
struct bt_mesh_node *node;
BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear);
node = bt_mesh_node_find(update->addr);
if (update->clear) {
clear_cdb_node(update->addr);
} else {
struct bt_mesh_cdb_node *node;
node = bt_mesh_cdb_node_get(update->addr);
if (node) {
store_node(node);
store_cdb_node(node);
} else {
BT_WARN("Node 0x%04x not found", update->addr);
}
@ -1424,8 +1661,128 @@ static void store_pending_nodes(void)
}
}
static struct node_update *node_update_find(u16_t addr,
struct node_update **free_slot)
static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
{
struct net_key_val key;
char path[30];
int err;
BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
bt_hex(sub->keys[0].net_key, 16));
memcpy(&key.val[0], sub->keys[0].net_key, 16);
memcpy(&key.val[1], sub->keys[1].net_key, 16);
key.kr_flag = sub->kr_flag;
key.kr_phase = sub->kr_phase;
snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx);
err = settings_save_one(path, &key, sizeof(key));
if (err) {
BT_ERR("Failed to store Subnet value");
} else {
BT_DBG("Stored Subnet value");
}
}
static void clear_cdb_subnet(u16_t net_idx)
{
char path[30];
int err;
BT_DBG("NetKeyIndex 0x%03x", net_idx);
snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", net_idx);
err = settings_delete(path);
if (err) {
BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx);
} else {
BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx);
}
}
static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app)
{
struct app_key_val key;
char path[30];
int err;
key.net_idx = app->net_idx;
key.updated = false;
memcpy(key.val[0], app->keys[0].app_key, 16);
memcpy(key.val[1], app->keys[1].app_key, 16);
snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app->app_idx);
err = settings_save_one(path, &key, sizeof(key));
if (err) {
BT_ERR("Failed to store AppKey %s value", log_strdup(path));
} else {
BT_DBG("Stored AppKey %s value", log_strdup(path));
}
}
static void clear_cdb_app_key(u16_t app_idx)
{
char path[30];
int err;
snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app_idx);
err = settings_delete(path);
if (err) {
BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
} else {
BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
}
}
static void store_pending_cdb_keys(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
struct key_update *update = &cdb_key_updates[i];
if (!update->valid) {
continue;
}
if (update->clear) {
if (update->app_key) {
clear_cdb_app_key(update->key_idx);
} else {
clear_cdb_subnet(update->key_idx);
}
} else {
if (update->app_key) {
struct bt_mesh_cdb_app_key *key;
key = bt_mesh_cdb_app_key_get(update->key_idx);
if (key) {
store_cdb_app_key(key);
} else {
BT_WARN("AppKeyIndex 0x%03x not found",
update->key_idx);
}
} else {
struct bt_mesh_cdb_subnet *sub;
sub = bt_mesh_cdb_subnet_get(update->key_idx);
if (sub) {
store_cdb_subnet(sub);
} else {
BT_WARN("NetKeyIndex 0x%03x not found",
update->key_idx);
}
}
}
update->valid = 0U;
}
}
static struct node_update *cdb_node_update_find(u16_t addr,
struct node_update **free_slot)
{
struct node_update *match;
int i;
@ -1433,8 +1790,8 @@ static struct node_update *node_update_find(u16_t addr,
match = NULL;
*free_slot = NULL;
for (i = 0; i < ARRAY_SIZE(node_updates); i++) {
struct node_update *update = &node_updates[i];
for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) {
struct node_update *update = &cdb_node_updates[i];
if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
*free_slot = update;
@ -1665,9 +2022,26 @@ static void store_pending(struct k_work *work)
store_pending_va();
}
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NODES_PENDING)) {
store_pending_nodes();
if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
BT_MESH_CDB_SUBNET_PENDING)) {
if (atomic_test_bit(bt_mesh_cdb.flags,
BT_MESH_CDB_VALID)) {
store_pending_cdb();
} else {
clear_cdb();
}
}
if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
BT_MESH_CDB_NODES_PENDING)) {
store_pending_cdb_nodes();
}
if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
BT_MESH_CDB_KEYS_PENDING)) {
store_pending_cdb_keys();
}
}
}
@ -1856,51 +2230,196 @@ void bt_mesh_store_label(void)
schedule_store(BT_MESH_VA_PENDING);
}
void bt_mesh_store_node(struct bt_mesh_node *node)
static void schedule_cdb_store(int flag)
{
struct node_update *update, *free_slot;
BT_DBG("Node 0x%04x", node->addr);
update = node_update_find(node->addr, &free_slot);
if (update) {
update->clear = false;
schedule_store(BT_MESH_NODES_PENDING);
return;
}
if (!free_slot) {
store_node(node);
return;
}
free_slot->addr = node->addr;
schedule_store(BT_MESH_NODES_PENDING);
atomic_set_bit(bt_mesh_cdb.flags, flag);
k_delayed_work_submit(&pending_store, K_NO_WAIT);
}
void bt_mesh_clear_node(struct bt_mesh_node *node)
void bt_mesh_store_cdb(void)
{
schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING);
}
void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node)
{
struct node_update *update, *free_slot;
BT_DBG("Node 0x%04x", node->addr);
update = node_update_find(node->addr, &free_slot);
update = cdb_node_update_find(node->addr, &free_slot);
if (update) {
update->clear = true;
schedule_store(BT_MESH_NODES_PENDING);
update->clear = false;
schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
return;
}
if (!free_slot) {
clear_node(node->addr);
store_cdb_node(node);
return;
}
free_slot->clear = true;
free_slot->addr = node->addr;
schedule_store(BT_MESH_NODES_PENDING);
schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
}
void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node)
{
struct node_update *update, *free_slot;
BT_DBG("Node 0x%04x", node->addr);
update = cdb_node_update_find(node->addr, &free_slot);
if (update) {
update->clear = true;
schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
return;
}
if (!free_slot) {
clear_cdb_node(node->addr);
return;
}
free_slot->addr = node->addr;
free_slot->clear = true;
schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
}
/* TODO: Could be shared with key_update_find? */
static struct key_update *cdb_key_update_find(bool app_key, u16_t key_idx,
struct key_update **free_slot)
{
struct key_update *match;
int i;
match = NULL;
*free_slot = NULL;
for (i = 0; i < ARRAY_SIZE(key_updates); i++) {
struct key_update *update = &cdb_key_updates[i];
if (!update->valid) {
*free_slot = update;
continue;
}
if (update->app_key != app_key) {
continue;
}
if (update->key_idx == key_idx) {
match = update;
}
}
return match;
}
void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
{
struct key_update *update, *free_slot;
BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
update = cdb_key_update_find(false, sub->net_idx, &free_slot);
if (update) {
update->clear = 0U;
schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
return;
}
if (!free_slot) {
store_cdb_subnet(sub);
return;
}
free_slot->valid = 1U;
free_slot->key_idx = sub->net_idx;
free_slot->app_key = 0U;
free_slot->clear = 0U;
schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
}
void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub)
{
struct key_update *update, *free_slot;
BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
update = cdb_key_update_find(false, sub->net_idx, &free_slot);
if (update) {
update->clear = 1U;
schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
return;
}
if (!free_slot) {
clear_cdb_subnet(sub->net_idx);
return;
}
free_slot->valid = 1U;
free_slot->key_idx = sub->net_idx;
free_slot->app_key = 0U;
free_slot->clear = 1U;
schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
}
void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *key)
{
struct key_update *update, *free_slot;
BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
update = cdb_key_update_find(true, key->app_idx, &free_slot);
if (update) {
update->clear = 0U;
schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
return;
}
if (!free_slot) {
store_cdb_app_key(key);
return;
}
free_slot->valid = 1U;
free_slot->key_idx = key->app_idx;
free_slot->app_key = 1U;
free_slot->clear = 0U;
schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
}
void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *key)
{
struct key_update *update, *free_slot;
BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
update = cdb_key_update_find(true, key->app_idx, &free_slot);
if (update) {
update->clear = 1U;
schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
return;
}
if (!free_slot) {
clear_cdb_app_key(key->app_idx);
return;
}
free_slot->valid = 1U;
free_slot->key_idx = key->app_idx;
free_slot->app_key = 1U;
free_slot->clear = 1U;
schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
}
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,

View file

@ -16,12 +16,17 @@ 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_store_node(struct bt_mesh_node *node);
void bt_mesh_store_cdb(void);
void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node);
void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub);
void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *app);
void bt_mesh_clear_net(void);
void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
void bt_mesh_clear_app_key(struct bt_mesh_app_key *key);
void bt_mesh_clear_rpl(void);
void bt_mesh_clear_node(struct bt_mesh_node *node);
void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node);
void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub);
void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *app);
void bt_mesh_settings_init(void);

View file

@ -26,6 +26,7 @@
#include "net.h"
#include "transport.h"
#include "foundation.h"
#include "settings.h"
#define CID_NVAL 0xffff
@ -217,7 +218,8 @@ static void prov_complete(u16_t net_idx, u16_t addr)
net.dst = addr;
}
static void prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
static void prov_node_added(u16_t net_idx, u8_t uuid[16], u16_t addr,
u8_t num_elem)
{
shell_print(ctx_shell, "Node provisioned, net_idx 0x%04x address "
"0x%04x elements %d", net_idx, addr, num_elem);
@ -796,6 +798,33 @@ static int cmd_beacon(const struct shell *shell, size_t argc, char *argv[])
return 0;
}
static void print_unprovisioned_beacon(u8_t uuid[16],
bt_mesh_prov_oob_info_t oob_info,
u32_t *uri_hash)
{
char uuid_hex_str[32 + 1];
bin2hex(uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
shell_print(ctx_shell, "UUID %s, OOB Info 0x%04x, URI Hash 0x%x",
uuid_hex_str, oob_info,
(uri_hash == NULL ? 0 : *uri_hash));
}
static int cmd_beacon_listen(const struct shell *shell, size_t argc,
char *argv[])
{
u8_t val = str2u8(argv[1]);
if (val) {
prov.unprovisioned_beacon = print_unprovisioned_beacon;
} else {
prov.unprovisioned_beacon = NULL;
}
return 0;
}
static int cmd_ttl(const struct shell *shell, size_t argc, char *argv[])
{
u8_t ttl;
@ -1954,6 +1983,313 @@ static int cmd_del_fault(const struct shell *shell, size_t argc, char *argv[])
return 0;
}
#if defined(CONFIG_BT_MESH_CDB)
static int cmd_cdb_create(const struct shell *shell, size_t argc,
char *argv[])
{
u8_t net_key[16];
size_t len;
int err;
if (argc < 2) {
bt_rand(net_key, 16);
} else {
len = hex2bin(argv[1], strlen(argv[1]), net_key,
sizeof(net_key));
memset(net_key + len, 0, sizeof(net_key) - len);
}
err = bt_mesh_cdb_create(net_key);
if (err < 0) {
shell_print(shell, "Failed to create CDB (err %d)", err);
}
return 0;
}
static int cmd_cdb_clear(const struct shell *shell, size_t argc,
char *argv[])
{
bt_mesh_cdb_clear();
shell_print(shell, "Cleared CDB");
return 0;
}
static void cdb_print_nodes(const struct shell *shell)
{
char key_hex_str[32 + 1], uuid_hex_str[32 + 1];
struct bt_mesh_cdb_node *node;
int i, total = 0;
bool configured;
shell_print(shell, "Address Elements Flags %-32s DevKey", "UUID");
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
node = &bt_mesh_cdb.nodes[i];
if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
continue;
}
configured = atomic_test_bit(node->flags,
BT_MESH_CDB_NODE_CONFIGURED);
total++;
bin2hex(node->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
bin2hex(node->dev_key, 16, key_hex_str, sizeof(key_hex_str));
shell_print(shell, "0x%04x %-8d %-5s %s %s", node->addr,
node->num_elem, configured ? "C" : "-",
uuid_hex_str, key_hex_str);
}
shell_print(shell, "> Total nodes: %d", total);
}
static void cdb_print_subnets(const struct shell *shell)
{
struct bt_mesh_cdb_subnet *subnet;
char key_hex_str[32 + 1];
int i, total = 0;
shell_print(shell, "NetIdx NetKey");
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
subnet = &bt_mesh_cdb.subnets[i];
if (subnet->net_idx == BT_MESH_KEY_UNUSED) {
continue;
}
total++;
bin2hex(subnet->keys[0].net_key, 16, key_hex_str,
sizeof(key_hex_str));
shell_print(shell, "0x%03x %s", subnet->net_idx,
key_hex_str);
}
shell_print(shell, "> Total subnets: %d", total);
}
static void cdb_print_app_keys(const struct shell *shell)
{
struct bt_mesh_cdb_app_key *app_key;
char key_hex_str[32 + 1];
int i, total = 0;
shell_print(shell, "NetIdx AppIdx AppKey");
for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
app_key = &bt_mesh_cdb.app_keys[i];
if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
continue;
}
total++;
bin2hex(app_key->keys[0].app_key, 16, key_hex_str,
sizeof(key_hex_str));
shell_print(shell, "0x%03x 0x%03x %s",
app_key->net_idx, app_key->app_idx, key_hex_str);
}
shell_print(shell, "> Total app-keys: %d", total);
}
static int cmd_cdb_show(const struct shell *shell, size_t argc,
char *argv[])
{
if (!atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID)) {
shell_print(shell, "No valid networks");
return 0;
}
shell_print(shell, "Mesh Network Information");
shell_print(shell, "========================");
cdb_print_nodes(shell);
shell_print(shell, "---");
cdb_print_subnets(shell);
shell_print(shell, "---");
cdb_print_app_keys(shell);
return 0;
}
static int cmd_cdb_node_add(const struct shell *shell, size_t argc,
char *argv[])
{
struct bt_mesh_cdb_node *node;
u8_t uuid[16], dev_key[16];
u16_t addr, net_idx;
u8_t num_elem;
size_t len;
len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
memset(uuid + len, 0, sizeof(uuid) - len);
addr = strtoul(argv[2], NULL, 0);
num_elem = strtoul(argv[3], NULL, 0);
net_idx = strtoul(argv[4], NULL, 0);
if (argc < 6) {
bt_rand(dev_key, 16);
} else {
len = hex2bin(argv[5], strlen(argv[5]), dev_key,
sizeof(dev_key));
memset(dev_key + len, 0, sizeof(dev_key) - len);
}
node = bt_mesh_cdb_node_alloc(uuid, addr, num_elem, net_idx);
if (node == NULL) {
shell_print(shell, "Failed to allocate node");
return 0;
}
memcpy(node->dev_key, dev_key, 16);
if (IS_ENABLED(CONFIG_SETTINGS)) {
bt_mesh_store_cdb_node(node);
}
shell_print(shell, "Added node 0x%04x", addr);
return 0;
}
static int cmd_cdb_node_del(const struct shell *shell, size_t argc,
char *argv[])
{
struct bt_mesh_cdb_node *node;
u16_t addr;
addr = strtoul(argv[1], NULL, 0);
node = bt_mesh_cdb_node_get(addr);
if (node == NULL) {
shell_print(shell, "No node with address 0x%04x", addr);
return 0;
}
bt_mesh_cdb_node_del(node, true);
shell_print(shell, "Deleted node 0x%04x", addr);
return 0;
}
static int cmd_cdb_subnet_add(const struct shell *shell, size_t argc,
char *argv[])
{
struct bt_mesh_cdb_subnet *sub;
u8_t net_key[16];
u16_t net_idx;
size_t len;
net_idx = strtoul(argv[1], NULL, 0);
if (argc < 3) {
bt_rand(net_key, 16);
} else {
len = hex2bin(argv[2], strlen(argv[2]), net_key,
sizeof(net_key));
memset(net_key + len, 0, sizeof(net_key) - len);
}
sub = bt_mesh_cdb_subnet_alloc(net_idx);
if (sub == NULL) {
shell_print(shell, "Could not add subnet");
return 0;
}
memcpy(sub->keys[0].net_key, net_key, 16);
if (IS_ENABLED(CONFIG_SETTINGS)) {
bt_mesh_store_cdb_subnet(sub);
}
shell_print(shell, "Added Subnet 0x%03x", net_idx);
return 0;
}
static int cmd_cdb_subnet_del(const struct shell *shell, size_t argc,
char *argv[])
{
struct bt_mesh_cdb_subnet *sub;
u16_t net_idx;
net_idx = strtoul(argv[1], NULL, 0);
sub = bt_mesh_cdb_subnet_get(net_idx);
if (sub == NULL) {
shell_print(shell, "No subnet with NetIdx 0x%03x", net_idx);
return 0;
}
bt_mesh_cdb_subnet_del(sub, true);
shell_print(shell, "Deleted subnet 0x%03x", net_idx);
return 0;
}
static int cmd_cdb_app_key_add(const struct shell *shell, size_t argc,
char *argv[])
{
struct bt_mesh_cdb_app_key *key;
u16_t net_idx, app_idx;
u8_t app_key[16];
size_t len;
net_idx = strtoul(argv[1], NULL, 0);
app_idx = strtoul(argv[2], NULL, 0);
if (argc < 4) {
bt_rand(app_key, 16);
} else {
len = hex2bin(argv[3], strlen(argv[3]), app_key,
sizeof(app_key));
memset(app_key + len, 0, sizeof(app_key) - len);
}
key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx);
if (key == NULL) {
shell_print(shell, "Could not add AppKey");
return 0;
}
memcpy(key->keys[0].app_key, app_key, 16);
if (IS_ENABLED(CONFIG_SETTINGS)) {
bt_mesh_store_cdb_app_key(key);
}
shell_print(shell, "Added AppKey 0x%03x", app_idx);
return 0;
}
static int cmd_cdb_app_key_del(const struct shell *shell, size_t argc,
char *argv[])
{
struct bt_mesh_cdb_app_key *key;
u16_t app_idx;
app_idx = strtoul(argv[1], NULL, 0);
key = bt_mesh_cdb_app_key_get(app_idx);
if (key == NULL) {
shell_print(shell, "No AppKey 0x%03x", app_idx);
return 0;
}
bt_mesh_cdb_app_key_del(key, true);
shell_print(shell, "Deleted AppKey 0x%03x", app_idx);
return 0;
}
#endif
SHELL_STATIC_SUBCMD_SET_CREATE(mesh_cmds,
SHELL_CMD_ARG(init, NULL, NULL, cmd_init, 1, 0),
SHELL_CMD_ARG(timeout, NULL, "[timeout in seconds]", cmd_timeout, 1, 1),
@ -1998,6 +2334,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(mesh_cmds,
/* Configuration Client Model operations */
SHELL_CMD_ARG(get-comp, NULL, "[page]", cmd_get_comp, 1, 1),
SHELL_CMD_ARG(beacon, NULL, "[val: off, on]", cmd_beacon, 2, 1),
SHELL_CMD_ARG(beacon-listen, NULL, "[val: off, on]", cmd_beacon_listen,
2, 0),
SHELL_CMD_ARG(ttl, NULL, "[ttl: 0x00, 0x02-0x7f]", cmd_ttl, 1, 1),
SHELL_CMD_ARG(friend, NULL, "[val: off, on]", cmd_friend, 1, 1),
SHELL_CMD_ARG(gatt-proxy, NULL, "[val: off, on]", cmd_gatt_proxy, 1, 1),
@ -2053,6 +2391,24 @@ SHELL_STATIC_SUBCMD_SET_CREATE(mesh_cmds,
SHELL_CMD_ARG(add-fault, NULL, "<Fault ID>", cmd_add_fault, 2, 0),
SHELL_CMD_ARG(del-fault, NULL, "[Fault ID]", cmd_del_fault, 1, 1),
#if defined(CONFIG_BT_MESH_CDB)
/* Mesh Configuration Database Operations */
SHELL_CMD_ARG(cdb-create, NULL, "[NetKey]", cmd_cdb_create, 1, 1),
SHELL_CMD_ARG(cdb-clear, NULL, NULL, cmd_cdb_clear, 1, 0),
SHELL_CMD_ARG(cdb-show, NULL, NULL, cmd_cdb_show, 1, 0),
SHELL_CMD_ARG(cdb-node-add, NULL, "<UUID> <addr> <num-elem> "
"<NetKeyIdx> [DevKey]", cmd_cdb_node_add, 5, 1),
SHELL_CMD_ARG(cdb-node-del, NULL, "<addr>", cmd_cdb_node_del, 2, 0),
SHELL_CMD_ARG(cdb-subnet-add, NULL, "<NeyKeyIdx> [<NetKey>]",
cmd_cdb_subnet_add, 2, 1),
SHELL_CMD_ARG(cdb-subnet-del, NULL, "<NetKeyIdx>", cmd_cdb_subnet_del,
2, 0),
SHELL_CMD_ARG(cdb-app-key-add, NULL, "<NetKeyIdx> <AppKeyIdx> "
"[<AppKey>]", cmd_cdb_app_key_add, 3, 1),
SHELL_CMD_ARG(cdb-app-key-del, NULL, "<AppKeyIdx>", cmd_cdb_app_key_del,
2, 0),
#endif
SHELL_SUBCMD_SET_END
);

View file

@ -34,7 +34,6 @@
#include "foundation.h"
#include "settings.h"
#include "transport.h"
#include "nodes.h"
/* The transport layer needs at least three buffers for itself to avoid
* deadlocks. Ensure that there are a sufficient number of advertising
@ -653,7 +652,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
}
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
struct bt_mesh_node *node;
struct bt_mesh_cdb_node *node;
/*
* There is no way of knowing if we should use our
@ -661,7 +660,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
* message so we must try both.
*/
node = bt_mesh_node_find(rx->ctx.addr);
node = bt_mesh_cdb_node_get(rx->ctx.addr);
if (node == NULL) {
BT_ERR("No node found for addr 0x%04x",
rx->ctx.addr);
@ -1718,18 +1717,16 @@ int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
{
struct bt_mesh_app_key *app_key;
if (app_idx == BT_MESH_KEY_DEV_LOCAL ||
(app_idx == BT_MESH_KEY_DEV_REMOTE &&
bt_mesh_elem_find(addr) != NULL)) {
if (app_idx == BT_MESH_KEY_DEV_LOCAL) {
*aid = 0;
*key = bt_mesh.dev_key;
return 0;
} else if (app_idx == BT_MESH_KEY_DEV_REMOTE) {
if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) {
return -EINVAL;
}
struct bt_mesh_node *node = bt_mesh_node_find(addr);
struct bt_mesh_cdb_node *node = bt_mesh_cdb_node_get(addr);
if (!node) {
return -EINVAL;
}