Bluetooth: Mesh: Break up mesh settings
The mesh settings.c module is a giant piece of code responsible for storing the mesh stack configuration. Such approach makes it difficult to control the data to be stored, breaks the stack modules' encapsulation by forcing them to reveal the internal kitchen, which leads to unpleasant issues such as #19799. This commit moves the responsibility of storing the configuration to corresponding modules while keeping control of the moment of storing the configuration and of starting the stack after the settingss loading is completed. This doesn't introduce any abstraction between the mesh settings.c and other modules as it will add more complexity and overhead than necessary for the actual task. Fixes #19850 Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
parent
472febfe69
commit
561a8e4f0e
26 changed files with 2375 additions and 2352 deletions
|
@ -25,21 +25,45 @@
|
|||
#define LOG_MODULE_NAME bt_mesh_app_keys
|
||||
#include "common/log.h"
|
||||
|
||||
static struct bt_mesh_app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = {
|
||||
/* Tracking of what storage changes are pending for App Keys. We track this in
|
||||
* a separate array here instead of within the respective bt_mesh_app_key
|
||||
* struct itselve, since once a key gets deleted its struct becomes invalid
|
||||
* and may be reused for other keys.
|
||||
*/
|
||||
struct app_key_update {
|
||||
uint16_t key_idx:12, /* AppKey Index */
|
||||
valid:1, /* 1 if this entry is valid, 0 if not */
|
||||
clear:1; /* 1 if key needs clearing, 0 if storing */
|
||||
};
|
||||
|
||||
/* AppKey information for persistent storage. */
|
||||
struct app_key_val {
|
||||
uint16_t net_idx;
|
||||
bool updated;
|
||||
uint8_t val[2][16];
|
||||
} __packed;
|
||||
|
||||
/** Mesh Application Key. */
|
||||
struct app_key {
|
||||
uint16_t net_idx;
|
||||
uint16_t app_idx;
|
||||
bool updated;
|
||||
struct bt_mesh_app_cred {
|
||||
uint8_t id;
|
||||
uint8_t val[16];
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
static struct app_key_update app_key_updates[CONFIG_BT_MESH_APP_KEY_COUNT];
|
||||
|
||||
static struct app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = {
|
||||
[0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.net_idx = BT_MESH_KEY_UNUSED,
|
||||
}
|
||||
};
|
||||
|
||||
static void app_key_evt(struct bt_mesh_app_key *app, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
Z_STRUCT_SECTION_FOREACH(bt_mesh_app_key_cb, cb) {
|
||||
cb->evt_handler(app->app_idx, app->net_idx, evt);
|
||||
}
|
||||
}
|
||||
|
||||
static struct bt_mesh_app_key *app_get(uint16_t app_idx)
|
||||
static struct app_key *app_get(uint16_t app_idx)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
if (apps[i].app_idx == app_idx) {
|
||||
|
@ -50,9 +74,115 @@ static struct bt_mesh_app_key *app_get(uint16_t app_idx)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx)
|
||||
static void clear_app_key(uint16_t app_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app = NULL;
|
||||
char path[20];
|
||||
int err;
|
||||
|
||||
snprintk(path, sizeof(path), "bt/mesh/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_app_key(uint16_t app_idx)
|
||||
{
|
||||
const struct app_key *app;
|
||||
struct app_key_val key;
|
||||
char path[20];
|
||||
int err;
|
||||
|
||||
snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app_idx);
|
||||
|
||||
app = app_get(app_idx);
|
||||
if (!app) {
|
||||
BT_WARN("ApKeyIndex 0x%03x not found", app_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
key.net_idx = app->net_idx,
|
||||
key.updated = app->updated,
|
||||
|
||||
memcpy(key.val[0], app->keys[0].val, 16);
|
||||
memcpy(key.val[1], app->keys[1].val, 16);
|
||||
|
||||
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 struct app_key_update *app_key_update_find(uint16_t key_idx,
|
||||
struct app_key_update **free_slot)
|
||||
{
|
||||
struct app_key_update *match;
|
||||
int i;
|
||||
|
||||
match = NULL;
|
||||
*free_slot = NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(app_key_updates); i++) {
|
||||
struct app_key_update *update = &app_key_updates[i];
|
||||
|
||||
if (!update->valid) {
|
||||
*free_slot = update;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (update->key_idx == key_idx) {
|
||||
match = update;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
static void update_app_key_settings(uint16_t app_idx, bool store)
|
||||
{
|
||||
struct app_key_update *update, *free_slot;
|
||||
uint8_t clear = store ? 0U : 1U;
|
||||
|
||||
BT_DBG("AppKeyIndex 0x%03x", app_idx);
|
||||
|
||||
update = app_key_update_find(app_idx, &free_slot);
|
||||
if (update) {
|
||||
update->clear = clear;
|
||||
bt_mesh_settings_store_schedule(
|
||||
BT_MESH_SETTINGS_APP_KEYS_PENDING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!free_slot) {
|
||||
if (store) {
|
||||
store_app_key(app_idx);
|
||||
} else {
|
||||
clear_app_key(app_idx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
free_slot->valid = 1U;
|
||||
free_slot->key_idx = app_idx;
|
||||
free_slot->clear = clear;
|
||||
|
||||
bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_APP_KEYS_PENDING);
|
||||
}
|
||||
|
||||
static void app_key_evt(struct app_key *app, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
Z_STRUCT_SECTION_FOREACH(bt_mesh_app_key_cb, cb) {
|
||||
cb->evt_handler(app->app_idx, app->net_idx, evt);
|
||||
}
|
||||
}
|
||||
|
||||
static struct app_key *app_key_alloc(uint16_t app_idx)
|
||||
{
|
||||
struct app_key *app = NULL;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
/* Check for already existing app_key */
|
||||
|
@ -68,12 +198,12 @@ static struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx)
|
|||
return app;
|
||||
}
|
||||
|
||||
static void app_key_del(struct bt_mesh_app_key *app)
|
||||
static void app_key_del(struct app_key *app)
|
||||
{
|
||||
BT_DBG("AppIdx 0x%03x", app->app_idx);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_clear_app_key(app->app_idx);
|
||||
update_app_key_settings(app->app_idx, false);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_DELETED);
|
||||
|
@ -83,7 +213,7 @@ static void app_key_del(struct bt_mesh_app_key *app)
|
|||
(void)memset(app->keys, 0, sizeof(app->keys));
|
||||
}
|
||||
|
||||
static void app_key_revoke(struct bt_mesh_app_key *app)
|
||||
static void app_key_revoke(struct app_key *app)
|
||||
{
|
||||
if (!app->updated) {
|
||||
return;
|
||||
|
@ -94,7 +224,7 @@ static void app_key_revoke(struct bt_mesh_app_key *app)
|
|||
app->updated = false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
update_app_key_settings(app->app_idx, true);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_REVOKED);
|
||||
|
@ -103,7 +233,7 @@ static void app_key_revoke(struct bt_mesh_app_key *app)
|
|||
uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16])
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
struct app_key *app;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
|
||||
bt_hex(key, 16));
|
||||
|
@ -142,7 +272,7 @@ uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
|
|||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Storing AppKey persistently");
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
update_app_key_settings(app->app_idx, true);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_ADDED);
|
||||
|
@ -150,22 +280,10 @@ uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
app = app_get(app_idx);
|
||||
if (app) {
|
||||
return app;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16])
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
struct app_key *app;
|
||||
struct bt_mesh_subnet *sub;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
|
||||
|
@ -213,7 +331,7 @@ uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
|
|||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Storing AppKey persistently");
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
update_app_key_settings(app->app_idx, true);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_UPDATED);
|
||||
|
@ -223,7 +341,7 @@ uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
|
|||
|
||||
uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
struct app_key *app;
|
||||
|
||||
BT_DBG("AppIdx 0x%03x", app_idx);
|
||||
|
||||
|
@ -251,7 +369,7 @@ uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx)
|
|||
int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t old_key[16], const uint8_t new_key[16])
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
struct app_key *app;
|
||||
|
||||
app = app_key_alloc(app_idx);
|
||||
if (!app) {
|
||||
|
@ -300,7 +418,7 @@ ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
|
|||
size_t count = 0;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
struct app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
|
@ -329,7 +447,7 @@ int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
|
|||
struct bt_mesh_subnet **sub,
|
||||
const uint8_t *app_key[16], uint8_t *aid)
|
||||
{
|
||||
struct bt_mesh_app_key *app = NULL;
|
||||
struct app_key *app = NULL;
|
||||
|
||||
if (BT_MESH_IS_DEV_KEY(ctx->app_idx)) {
|
||||
/* With device keys, the application has to decide which subnet
|
||||
|
@ -425,7 +543,7 @@ uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
|
|||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
const struct bt_mesh_app_key *app = &apps[i];
|
||||
const struct app_key *app = &apps[i];
|
||||
const struct bt_mesh_app_cred *cred;
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
|
@ -464,7 +582,7 @@ static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
|
|||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
struct app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
|
@ -489,10 +607,68 @@ BT_MESH_SUBNET_CB_DEFINE(subnet_evt);
|
|||
void bt_mesh_app_keys_reset(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
struct app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx != BT_MESH_KEY_UNUSED) {
|
||||
app_key_del(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int app_key_set(const char *name, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct app_key_val key;
|
||||
uint16_t app_idx;
|
||||
int err;
|
||||
|
||||
if (!name) {
|
||||
BT_ERR("Insufficient number of arguments");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
app_idx = strtol(name, NULL, 16);
|
||||
|
||||
if (!len_rd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = bt_mesh_settings_set(read_cb, cb_arg, &key, sizeof(key));
|
||||
if (err < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = bt_mesh_app_key_set(app_idx, key.net_idx, key.val[0],
|
||||
key.updated ? key.val[1] : NULL);
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'app-key\'");
|
||||
return err;
|
||||
}
|
||||
|
||||
BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BT_MESH_SETTINGS_DEFINE(app, "AppKey", app_key_set);
|
||||
|
||||
void bt_mesh_app_key_pending_store(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(app_key_updates); i++) {
|
||||
struct app_key_update *update = &app_key_updates[i];
|
||||
|
||||
if (!update->valid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (update->clear) {
|
||||
clear_app_key(update->key_idx);
|
||||
} else {
|
||||
store_app_key(update->key_idx);
|
||||
}
|
||||
|
||||
update->valid = 0U;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue