mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-15 21:50:03 +00:00
host/mesh: Add API to manually store pending RPL entries
The current approach with storing RPL by timeout doesn't solve all issues as the node may loss power before the timer is fired. In addition to that this may wear out flash quickly if short timeout is used. This change adds an API to store the pending RPL entry upon user request. Additional Kconfig option allows to completely disable timer so that the whole storing relies on the user. The mesh stack still stays responsible for outdating RPL entries in case of IV Index update as this happens implicitly for the user. This is port of 65f798a00abb6bbb7c51091e754b926d15405d14
This commit is contained in:
committed by
Krzysztof Kopyściński
parent
d9413d20fb
commit
23217d8622
@@ -565,6 +565,19 @@ void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established));
|
||||
*/
|
||||
int bt_mesh_friend_terminate(uint16_t lpn_addr);
|
||||
|
||||
/** @brief Store pending RPL entry(ies) in the persistent storage.
|
||||
*
|
||||
* This API allows the user to store pending RPL entry(ies) in the persistent
|
||||
* storage without waiting for the timeout.
|
||||
*
|
||||
* @note When flash is used as the persistent storage, calling this API too
|
||||
* frequently may wear it out.
|
||||
*
|
||||
* @param addr Address of the node which RPL entry needs to be stored or
|
||||
* @ref BT_MESH_ADDR_ALL_NODES to store all pending RPL entries.
|
||||
*/
|
||||
void bt_mesh_rpl_pending_store(uint16_t addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -53,10 +53,17 @@ static void clear_rpl(struct bt_mesh_rpl *rpl)
|
||||
atomic_clear_bit(store, rpl_idx(rpl));
|
||||
}
|
||||
|
||||
static void schedule_rpl_store(struct bt_mesh_rpl *entry)
|
||||
static void schedule_rpl_store(struct bt_mesh_rpl *entry, bool force)
|
||||
{
|
||||
atomic_set_bit(store, rpl_idx(entry));
|
||||
bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING);
|
||||
if (force
|
||||
#ifdef CONFIG_BT_MESH_RPL_STORE_TIMEOUT
|
||||
|| CONFIG_BT_MESH_RPL_STORE_TIMEOUT >= 0
|
||||
#endif
|
||||
) {
|
||||
bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING);
|
||||
}
|
||||
}
|
||||
|
||||
static void schedule_rpl_clear(void)
|
||||
@@ -79,7 +86,7 @@ void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
|
||||
rpl->old_iv = rx->old_iv;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
schedule_rpl_store(rpl);
|
||||
schedule_rpl_store(rpl, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +207,7 @@ void bt_mesh_rpl_reset(void)
|
||||
} else {
|
||||
rpl->old_iv = true;
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
schedule_rpl_store(rpl);
|
||||
schedule_rpl_store(rpl, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,16 +313,35 @@ static void store_pending_rpl(struct bt_mesh_rpl *rpl)
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_rpl_pending_store(void)
|
||||
void bt_mesh_rpl_pending_store(uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_SETTINGS) ||
|
||||
(!BT_MESH_ADDR_IS_UNICAST(addr) &&
|
||||
addr != BT_MESH_ADDR_ALL_NODES)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr == BT_MESH_ADDR_ALL_NODES) {
|
||||
bt_mesh_settings_store_cancel(BT_MESH_SETTINGS_RPL_PENDING);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
|
||||
if (addr != BT_MESH_ADDR_ALL_NODES &&
|
||||
addr != replay_list[i].src) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
store_pending_rpl(&replay_list[i]);
|
||||
} else {
|
||||
clear_rpl(&replay_list[i]);
|
||||
}
|
||||
|
||||
if (addr != BT_MESH_ADDR_ALL_NODES) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,5 +29,4 @@ bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
|
||||
void bt_mesh_rpl_clear(void);
|
||||
void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
|
||||
struct bt_mesh_net_rx *rx);
|
||||
void bt_mesh_rpl_pending_store(void);
|
||||
void bt_mesh_rpl_init(void);
|
||||
@@ -104,11 +104,9 @@ void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)
|
||||
|
||||
if (atomic_get(pending_flags) & NO_WAIT_PENDING_BITS) {
|
||||
timeout_ms = 0;
|
||||
} else if (atomic_test_bit(pending_flags,
|
||||
BT_MESH_SETTINGS_RPL_PENDING) &&
|
||||
(!(atomic_get(pending_flags) & GENERIC_PENDING_BITS) ||
|
||||
(CONFIG_BT_MESH_RPL_STORE_TIMEOUT <
|
||||
CONFIG_BT_MESH_STORE_TIMEOUT))) {
|
||||
} else if (CONFIG_BT_MESH_RPL_STORE_TIMEOUT >= 0 &&
|
||||
atomic_test_bit(pending_flags, BT_MESH_SETTINGS_RPL_PENDING) &&
|
||||
!(atomic_get(pending_flags) & GENERIC_PENDING_BITS)) {
|
||||
timeout_ms = CONFIG_BT_MESH_RPL_STORE_TIMEOUT * MSEC_PER_SEC;
|
||||
} else {
|
||||
timeout_ms = CONFIG_BT_MESH_STORE_TIMEOUT * MSEC_PER_SEC;
|
||||
@@ -127,12 +125,18 @@ void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)
|
||||
k_work_schedule(&pending_store, K_MSEC(timeout_ms));
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag)
|
||||
{
|
||||
atomic_clear_bit(pending_flags, flag);
|
||||
}
|
||||
|
||||
static void store_pending(struct ble_npl_event *work)
|
||||
{
|
||||
BT_DBG("");
|
||||
if (atomic_test_and_clear_bit(pending_flags,
|
||||
BT_MESH_SETTINGS_RPL_PENDING)) {
|
||||
bt_mesh_rpl_pending_store();
|
||||
bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
|
||||
}
|
||||
|
||||
if (atomic_test_and_clear_bit(pending_flags,
|
||||
|
||||
@@ -23,3 +23,4 @@ enum bt_mesh_settings_flag {
|
||||
void bt_mesh_settings_init(void);
|
||||
int settings_name_next(char *name, char **next);
|
||||
void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag);
|
||||
void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag);
|
||||
|
||||
+16
-10
@@ -619,16 +619,22 @@ syscfg.defs:
|
||||
|
||||
BLE_MESH_RPL_STORE_TIMEOUT:
|
||||
description: >
|
||||
This value defines in seconds how soon the RPL gets written to
|
||||
persistent storage after a change occurs. If the node receives
|
||||
messages frequently it may make sense to have this set to a
|
||||
large value, whereas if the RPL gets updated infrequently a
|
||||
value as low as 0 (write immediately) may make sense. Note that
|
||||
if the node operates a security sensitive use case, and there's
|
||||
a risk of sudden power loss, it may be a security vulnerability
|
||||
to set this value to anything else than 0 (a power loss before
|
||||
writing to storage exposes the node to potential message
|
||||
replay attacks).
|
||||
Minimum interval after which unsaved RPL entries are updated in storage
|
||||
|
||||
This value defines in seconds how soon unsaved RPL entries
|
||||
gets written to the persistent storage. Setting this value
|
||||
to a large number may lead to security vulnerabilities if a node
|
||||
gets powered off before the timer is fired. When flash is used
|
||||
as the persistent storage setting this value to a low number
|
||||
may wear out flash sooner or later. However, if the RPL gets
|
||||
updated infrequently a value as low as 0 (write immediately)
|
||||
may make sense. Setting this value to -1 will disable this timer.
|
||||
In this case, a user is responsible to store pending RPL entries
|
||||
using @ref bt_mesh_rpl_pending_store. In the mean time, when
|
||||
IV Index is updated, the outdated RPL entries will still be
|
||||
stored by @ref BT_MESH_STORE_TIMEOUT. Finding the right balance
|
||||
between this timeout and calling @ref bt_mesh_rpl_pending_store
|
||||
may reduce a risk of security vulnerability and flash wear out.
|
||||
value: 5
|
||||
|
||||
BLE_MESH_DEVICE_NAME:
|
||||
|
||||
Reference in New Issue
Block a user