Bluetooth: Mesh: Fix cyclic rewriting to flash when restoring state

When we're reading the initial state from flash, calling the various
internal functions was leading to scheduling a rewrite to flash. Add
an extra parameter to the appropriate functions so they know when
they're called due to active configuration by a configuration client,
and when they're called due to restoring the state from flash.

This was not only wasting flash space, but also causing erroneous
behavior with the FCB settings backend if there was an intermediate
node reset operation stored, followed by a reprovisioning. The node
reset entries would cause them to be re-appened after the second valid
provisioning, leading to an incomplete node state.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2018-06-26 11:34:27 +03:00 committed by Johan Hedberg
commit 59bbab99a8
3 changed files with 38 additions and 27 deletions

View file

@ -245,7 +245,7 @@ static bool app_key_is_valid(u16_t app_idx)
static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr, static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
u16_t app_idx, u8_t cred_flag, u8_t ttl, u8_t period, u16_t app_idx, u8_t cred_flag, u8_t ttl, u8_t period,
u8_t retransmit) u8_t retransmit, bool store)
{ {
if (!model->pub) { if (!model->pub) {
return STATUS_NVAL_PUB_PARAM; return STATUS_NVAL_PUB_PARAM;
@ -276,7 +276,7 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
k_delayed_work_cancel(&model->pub->timer); k_delayed_work_cancel(&model->pub->timer);
} }
if (IS_ENABLED(CONFIG_BT_SETTINGS)) { if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_store_mod_pub(model); bt_mesh_store_mod_pub(model);
} }
@ -307,7 +307,7 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
} }
} }
if (IS_ENABLED(CONFIG_BT_SETTINGS)) { if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_store_mod_pub(model); bt_mesh_store_mod_pub(model);
} }
@ -318,7 +318,7 @@ static u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx)
{ {
int i; int i;
BT_DBG("key_idx 0x%04x", key_idx); BT_DBG("model %p key_idx 0x%03x", model, key_idx);
if (!app_key_is_valid(key_idx)) { if (!app_key_is_valid(key_idx)) {
return STATUS_INVALID_APPKEY; return STATUS_INVALID_APPKEY;
@ -346,11 +346,11 @@ static u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx)
return STATUS_INSUFF_RESOURCES; return STATUS_INSUFF_RESOURCES;
} }
static u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx) static u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store)
{ {
int i; int i;
BT_DBG("model %p key_idx 0x%04x", model, key_idx); BT_DBG("model %p key_idx 0x%03x store %u", model, key_idx, store);
if (!app_key_is_valid(key_idx)) { if (!app_key_is_valid(key_idx)) {
return STATUS_INVALID_APPKEY; return STATUS_INVALID_APPKEY;
@ -363,13 +363,13 @@ static u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx)
model->keys[i] = BT_MESH_KEY_UNUSED; model->keys[i] = BT_MESH_KEY_UNUSED;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) { if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_store_mod_bind(model); bt_mesh_store_mod_bind(model);
} }
if (model->pub && model->pub->key == key_idx) { if (model->pub && model->pub->key == key_idx) {
_mod_pub_set(model, BT_MESH_ADDR_UNASSIGNED, _mod_pub_set(model, BT_MESH_ADDR_UNASSIGNED,
0, 0, 0, 0, 0); 0, 0, 0, 0, 0, store);
} }
} }
@ -530,19 +530,28 @@ static void app_key_update(struct bt_mesh_model *model,
} }
} }
struct unbind_data {
u16_t app_idx;
bool store;
};
static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data) bool vnd, bool primary, void *user_data)
{ {
u16_t *key_idx = user_data; struct unbind_data *data = user_data;
mod_unbind(mod, *key_idx); mod_unbind(mod, data->app_idx, data->store);
} }
void bt_mesh_app_key_del(struct bt_mesh_app_key *key) void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store)
{ {
bt_mesh_model_foreach(_mod_unbind, &key->app_idx); struct unbind_data data = { .app_idx = key->app_idx, .store = store };
if (IS_ENABLED(CONFIG_BT_SETTINGS)) { BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
bt_mesh_model_foreach(_mod_unbind, &data);
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_clear_app_key(key); bt_mesh_clear_app_key(key);
} }
@ -582,7 +591,7 @@ static void app_key_del(struct bt_mesh_model *model,
goto send_status; goto send_status;
} }
bt_mesh_app_key_del(key); bt_mesh_app_key_del(key, true);
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
send_status: send_status:
@ -1127,7 +1136,7 @@ static void mod_pub_set(struct bt_mesh_model *model,
} }
status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl, status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl,
pub_period, retransmit); pub_period, retransmit, true);
send_status: send_status:
send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
@ -1270,7 +1279,7 @@ static void mod_pub_va_set(struct bt_mesh_model *model,
status = va_add(label_uuid, &pub_addr); status = va_add(label_uuid, &pub_addr);
if (status == STATUS_SUCCESS) { if (status == STATUS_SUCCESS) {
status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag,
pub_ttl, pub_period, retransmit); pub_ttl, pub_period, retransmit, true);
} }
send_status: send_status:
@ -2217,7 +2226,7 @@ static void net_key_del(struct bt_mesh_model *model,
goto send_status; goto send_status;
} }
bt_mesh_subnet_del(sub); bt_mesh_subnet_del(sub, true);
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
send_status: send_status:
@ -2457,7 +2466,7 @@ static void mod_app_unbind(struct bt_mesh_model *model,
goto send_status; goto send_status;
} }
status = mod_unbind(mod, key_app_idx); status = mod_unbind(mod, key_app_idx, true);
if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) { if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) {
bt_test_mesh_model_unbound(ctx->addr, mod, key_app_idx); bt_test_mesh_model_unbound(ctx->addr, mod, key_app_idx);
@ -3246,7 +3255,7 @@ void bt_mesh_cfg_reset(void)
struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
if (sub->net_idx != BT_MESH_KEY_UNUSED) { if (sub->net_idx != BT_MESH_KEY_UNUSED) {
bt_mesh_subnet_del(sub); bt_mesh_subnet_del(sub, true);
} }
} }
@ -3388,14 +3397,16 @@ struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void)
return conf; return conf;
} }
void bt_mesh_subnet_del(struct bt_mesh_subnet *sub) void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store)
{ {
int i; int i;
BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
if (conf && conf->hb_pub.net_idx == sub->net_idx) { if (conf && conf->hb_pub.net_idx == sub->net_idx) {
hb_pub_disable(conf); hb_pub_disable(conf);
if (IS_ENABLED(CONFIG_BT_SETTINGS)) { if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_store_hb_pub(); bt_mesh_store_hb_pub();
} }
} }
@ -3405,7 +3416,7 @@ void bt_mesh_subnet_del(struct bt_mesh_subnet *sub)
struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
if (key->net_idx == sub->net_idx) { if (key->net_idx == sub->net_idx) {
bt_mesh_app_key_del(key); bt_mesh_app_key_del(key, store);
} }
} }
@ -3413,7 +3424,7 @@ void bt_mesh_subnet_del(struct bt_mesh_subnet *sub)
bt_mesh_friend_clear_net_idx(sub->net_idx); bt_mesh_friend_clear_net_idx(sub->net_idx);
} }
if (IS_ENABLED(CONFIG_BT_SETTINGS)) { if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
bt_mesh_clear_subnet(sub); bt_mesh_clear_subnet(sub);
} }

View file

@ -137,10 +137,10 @@ u8_t bt_mesh_beacon_get(void);
u8_t bt_mesh_gatt_proxy_get(void); u8_t bt_mesh_gatt_proxy_get(void);
u8_t bt_mesh_default_ttl_get(void); u8_t bt_mesh_default_ttl_get(void);
void bt_mesh_subnet_del(struct bt_mesh_subnet *sub); void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store);
struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx); struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx);
void bt_mesh_app_key_del(struct bt_mesh_app_key *key); void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store);
#include <misc/byteorder.h> #include <misc/byteorder.h>

View file

@ -337,7 +337,7 @@ static int net_key_set(int argc, char **argv, char *val)
} }
BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx); BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
bt_mesh_subnet_del(sub); bt_mesh_subnet_del(sub, false);
return 0; return 0;
} }
@ -404,7 +404,7 @@ static int app_key_set(int argc, char **argv, char *val)
app = bt_mesh_app_key_find(app_idx); app = bt_mesh_app_key_find(app_idx);
if (app) { if (app) {
bt_mesh_app_key_del(app); bt_mesh_app_key_del(app, false);
} }
return 0; return 0;