in nimble/host/mesh/src/net.c [244:351]
bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update)
{
if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
/* We're currently in IV Update mode */
if (iv_index != bt_mesh.iv_index) {
BT_WARN("IV Index mismatch: 0x%08x != 0x%08x",
(unsigned) iv_index,
(unsigned) bt_mesh.iv_index);
return false;
}
if (iv_update) {
/* Nothing to do */
BT_DBG("Already in IV Update in Progress state");
return false;
}
} else {
/* We're currently in Normal mode */
if (iv_index == bt_mesh.iv_index) {
BT_DBG("Same IV Index in normal mode");
return false;
}
if (iv_index < bt_mesh.iv_index ||
iv_index > bt_mesh.iv_index + 42) {
BT_ERR("IV Index out of sync: 0x%08x != 0x%08x",
(unsigned) iv_index,
(unsigned) bt_mesh.iv_index);
return false;
}
if ((iv_index > bt_mesh.iv_index + 1) ||
(iv_index == bt_mesh.iv_index + 1 && !iv_update)) {
if (ivi_was_recovered) {
BT_ERR("IV Index Recovery before minimum delay");
return false;
}
/* The Mesh profile specification allows to initiate an
* IV Index Recovery procedure if previous IV update has
* been missed. This allows the node to remain
* functional.
*/
BT_WARN("Performing IV Index Recovery");
ivi_was_recovered = true;
bt_mesh_rpl_clear();
bt_mesh.iv_index = iv_index;
bt_mesh.seq = 0;
goto do_update;
}
}
if (!(IS_ENABLED(CONFIG_BT_MESH_IV_UPDATE_TEST) &&
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_TEST))) {
if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
BT_WARN("IV Update before minimum duration");
return false;
}
}
/* Defer change to Normal Operation if there are pending acks */
if (!iv_update && bt_mesh_tx_in_progress()) {
BT_WARN("IV Update deferred because of pending transfer");
atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_PENDING);
return false;
}
if (iv_update) {
bt_mesh.iv_index = iv_index;
BT_DBG("IV Update state entered. New index 0x%08x",
(unsigned) bt_mesh.iv_index);
bt_mesh_rpl_reset();
ivi_was_recovered = false;
} else {
BT_DBG("Normal mode entered");
bt_mesh.seq = 0;
}
do_update:
atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv_update);
bt_mesh.ivu_duration = 0U;
k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
/* Notify other modules */
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
bt_mesh_friend_sec_update(BT_MESH_KEY_ANY);
}
bt_mesh_subnet_foreach(bt_mesh_beacon_update);
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
bt_mesh_proxy_beacon_send(NULL);
}
if (MYNEWT_VAL(BLE_MESH_CDB)) {
bt_mesh_cdb_iv_update(iv_index, iv_update);
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
store_iv(false);
}
return true;
}