Skip to content

Commit e244b80

Browse files
ludvigsjnordicjm
authored andcommitted
[nrf fromtree] Bluetooth: Mesh: Decouple RPL store timeout from storage mode
Solve two issues: * Other storage modes than CONFIG_BT_MESH_RPL_STORAGE_MODE_SETTINGS could not reuse the pending store scheduler used by the settings backend. * The store timing of SRPL, which is always stored through the Settings subsystem, would use CONFIG_BT_MESH_RPL_STORE_TIMEOUT if RPL was also stored in settings via CONFIG_BT_MESH_RPL_STORAGE_MODE_SETTINGS, but not if another storage mode was used for RPL. Decouple the store scheduler from the Settings subsystem and the chosen RPL storage mode, so the scheduler code and the separate CONFIG_BT_MESH_RPL_STORE_TIMEOUT option are a) Available regardless of storage mode, and always used for SRPL when set and b) Available without CONFIG_BT_SETTINGS, in case an RPL storage mode does not need Settings but would like the scheduling. Also change the BT_MESH_SETTINGS_RPL_RESET_PENDING to always store immediately. This was in practice already the case whenever settings was used, since this was only ever scheduled right before a second NO_WAIT configuration was scheduled (like net key, IV, etc.). Now this behavior is consistent both with and without BT_SETTINGS enabled. Assisted-by: Copilot:claude-sonnet-5.5 Signed-off-by: Ludvig Jordet <ludvig.jordet@nordicsemi.no> (cherry picked from commit 3f878df514ad9ebe63d73b36a0ea50fa557517d7)
1 parent 0b35f49 commit e244b80

10 files changed

Lines changed: 145 additions & 69 deletions

File tree

‎doc/services/connectivity/bluetooth/api/mesh/core.rst‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,20 @@ is defined by the :kconfig:option:`CONFIG_BT_MESH_STORE_TIMEOUT` option. Once
8080
storing of data is scheduled, it can not be rescheduled until the work item is
8181
processed. Exceptions are made in certain cases as described below.
8282

83-
When IV index, Sequence Number or CDB configuration have to be stored, the work
84-
item is submitted to the workqueue without the delay. If the work item was
85-
previously scheduled, it will be rescheduled without the delay.
86-
87-
The Replay Protection List uses the same work item to store RPL entries. If
88-
storing of RPL entries is requested and no other configuration is pending to be
89-
stored, the delay is set to :kconfig:option:`CONFIG_BT_MESH_RPL_STORE_TIMEOUT`.
90-
If other stack configuration has to be stored, the delay defined by
91-
the :kconfig:option:`CONFIG_BT_MESH_STORE_TIMEOUT` option is less than
92-
:kconfig:option:`CONFIG_BT_MESH_RPL_STORE_TIMEOUT`, and the work item was
93-
scheduled by the Replay Protection List, the work item will be rescheduled.
94-
95-
When the work item is running, the stack will store all pending configuration,
96-
including the RPL entries.
83+
When IV index, Sequence Number, CDB configuration or a Replay Protection List
84+
reset have to be stored, the work item is submitted to the workqueue without
85+
the delay. If the work item was previously scheduled, it will be rescheduled
86+
without the delay.
87+
88+
The Replay Protection List and the Solicitation Replay Protection List are
89+
stored by a separate work item, scheduled with the delay defined by
90+
:kconfig:option:`CONFIG_BT_MESH_RPL_STORE_TIMEOUT`. Pending stores of other
91+
kinds do not shorten this delay. If the option is set to ``-1``, the replay
92+
protection lists are stored together with the rest of the stack
93+
configuration.
94+
95+
When a work item is running, the stack will store all pending configuration
96+
that the work item is responsible for.
9797

9898
Work item execution context
9999
===========================

‎subsys/bluetooth/mesh/CMakeLists.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH_ADV_LEGACY adv_legacy.c)
2626

2727
zephyr_library_sources_ifdef(CONFIG_BT_MESH_ADV_EXT adv_ext.c)
2828

29-
zephyr_library_sources_ifdef(CONFIG_BT_SETTINGS settings.c)
29+
zephyr_library_sources_ifdef(CONFIG_BT_MESH_PENDING_STORE settings.c)
3030

3131
zephyr_library_sources_ifdef(CONFIG_BT_MESH_RPL_STORAGE_MODE_SETTINGS rpl.c)
3232

‎subsys/bluetooth/mesh/Kconfig‎

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,8 +1868,16 @@ config BT_MESH_LABEL_COUNT
18681868

18691869
endmenu # Capabilities
18701870

1871+
config BT_MESH_PENDING_STORE
1872+
bool
1873+
default y if BT_SETTINGS
1874+
help
1875+
Scheduler for deferred storing of pending mesh data. Enabled with the
1876+
settings subsystem, and selected by storage backends that schedule
1877+
their stores through it without the settings subsystem.
1878+
18711879
menu "Persistent storage"
1872-
visible if BT_SETTINGS
1880+
visible if BT_MESH_PENDING_STORE
18731881

18741882
config BT_MESH_STORE_TIMEOUT
18751883
int "Delay (in seconds) before storing anything persistently"
@@ -1897,33 +1905,32 @@ config BT_MESH_SEQ_STORE_RATE
18971905
off with a value that's guaranteed to be larger than the last
18981906
one used before power off.
18991907

1900-
if BT_MESH_RPL_STORAGE_MODE_SETTINGS && BT_SETTINGS
1901-
19021908
config BT_MESH_RPL_STORE_TIMEOUT
1903-
int "Minimum interval after which unsaved RPL and SRPL entries are updated in the settings subsystem"
1909+
int "Minimum interval after which unsaved RPL and SRPL entries are stored"
1910+
depends on BT_MESH_PENDING_STORE
19041911
range -1 1000000
19051912
default 5
19061913
help
19071914
This value defines time in seconds until unsaved RPL and SRPL entries
1908-
are written to the persistent storage. Setting this value
1915+
are written to the persistent storage. The SRPL is always stored
1916+
through the settings subsystem, whereas the RPL is only affected if
1917+
its storage mode schedules stores with this timeout. Setting this value
19091918
to a large number may lead to security vulnerabilities if a node
19101919
gets powered off before the timer is fired. When flash is used
19111920
as the persistent storage setting this value to a low number
19121921
may wear out flash sooner or later. However, if the RPL gets
19131922
updated infrequently a value as low as 0 (write immediately)
19141923
may make sense. Setting this value to -1 will disable this timer.
1915-
In this case, a user is responsible to store pending RPL entries
1916-
using @ref bt_mesh_rpl_pending_store. In the mean time, when
1917-
IV Index is updated, the outdated RPL entries will still be
1918-
stored by @ref BT_MESH_STORE_TIMEOUT. Finding the right balance
1924+
With the settings storage mode, a user is then responsible to store
1925+
pending RPL entries using @ref bt_mesh_rpl_pending_store. In the
1926+
mean time, the replay list invalidated by an IV Index update or
1927+
recovery is still stored immediately. Finding the right balance
19191928
between this timeout and calling @ref bt_mesh_rpl_pending_store
19201929
may reduce a risk of security vulnerability and flash wear out.
19211930
Failure to store the RPL and becoming vulnerable after reboot
19221931
will cause the device to not perform the replay protection
19231932
required by the spec.
19241933

1925-
endif # BT_MESH_RPL_STORAGE_MODE_SETTINGS && BT_SETTINGS
1926-
19271934
config BT_MESH_SETTINGS_WORKQ
19281935
bool "Store the Bluetooth Mesh settings in a separate work queue"
19291936
default y

‎subsys/bluetooth/mesh/main.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ void bt_mesh_reset(void)
412412
bt_mesh_sol_reset();
413413
}
414414

415-
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
415+
if (IS_ENABLED(CONFIG_BT_MESH_PENDING_STORE)) {
416416
bt_mesh_settings_store_pending();
417417
}
418418

@@ -612,7 +612,7 @@ int bt_mesh_init(const struct bt_mesh_prov *prov,
612612
bt_mesh_beacon_init();
613613
bt_mesh_adv_init();
614614

615-
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
615+
if (IS_ENABLED(CONFIG_BT_MESH_PENDING_STORE)) {
616616
bt_mesh_settings_init();
617617
}
618618

‎subsys/bluetooth/mesh/rpl.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,10 @@ bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match, bo
2626
void bt_mesh_rpl_clear(void);
2727
void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
2828
struct bt_mesh_net_rx *rx);
29+
/*
30+
* A storage backend using the pending store scheduler schedules
31+
* BT_MESH_SETTINGS_RPL_PENDING for entry updates and
32+
* BT_MESH_SETTINGS_RPL_RESET_PENDING when an IV Index update or recovery
33+
* invalidates the list. Both run this function, which must cancel both flags.
34+
*/
2935
void bt_mesh_rpl_pending_store_all_nodes(void);

‎subsys/bluetooth/mesh/settings.c‎

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ LOG_MODULE_REGISTER(bt_mesh_settings);
5959
/* When true, the replay lists are stored on a deadline of their own. Otherwise
6060
* they are stored together with the generic pending flags.
6161
*/
62-
#define RPL_OWN_TIMEOUT (IS_ENABLED(CONFIG_BT_MESH_RPL_STORAGE_MODE_SETTINGS) && \
63-
RPL_STORE_TIMEOUT >= 0)
62+
#define RPL_OWN_TIMEOUT (RPL_STORE_TIMEOUT >= 0)
6463

6564
static struct k_work_q settings_work_q;
6665
static K_THREAD_STACK_DEFINE(settings_work_stack, SETTINGS_WORKQ_STACK_SIZE);
@@ -90,6 +89,7 @@ int bt_mesh_settings_set(settings_read_cb read_cb, void *cb_arg,
9089
return 0;
9190
}
9291

92+
#if defined(CONFIG_BT_SETTINGS)
9393
static int mesh_commit(void)
9494
{
9595
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_INIT)) {
@@ -123,12 +123,14 @@ static int mesh_commit(void)
123123

124124
SETTINGS_STATIC_HANDLER_DEFINE_WITH_CPRIO(bt_mesh, "bt/mesh", NULL, NULL, mesh_commit, NULL,
125125
BT_SETTINGS_CPRIO_2);
126+
#endif /* CONFIG_BT_SETTINGS */
126127

127128
/* Pending flags that use K_NO_WAIT as the storage timeout */
128129
#define NO_WAIT_PENDING_BITS (BIT(BT_MESH_SETTINGS_NET_PENDING) | \
129130
BIT(BT_MESH_SETTINGS_IV_PENDING) | \
130131
BIT(BT_MESH_SETTINGS_SEQ_PENDING) | \
131-
BIT(BT_MESH_SETTINGS_CDB_PENDING))
132+
BIT(BT_MESH_SETTINGS_CDB_PENDING) | \
133+
BIT(BT_MESH_SETTINGS_RPL_RESET_PENDING))
132134

133135
/* Pending flags that use CONFIG_BT_MESH_RPL_STORE_TIMEOUT. Both replay lists
134136
* share the deadline, and each is stored only if its own flag is set.
@@ -183,6 +185,9 @@ void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag)
183185
atomic_clear_bit(pending_flags, flag);
184186
}
185187

188+
/* Data other than the replay protection list is only stored through the settings subsystem. */
189+
#define SETTINGS_HANDLER(_func) (IS_ENABLED(CONFIG_BT_SETTINGS) ? (_func) : NULL)
190+
186191
static void store_pending_flags(uint32_t mask)
187192
{
188193
LOG_DBG("");
@@ -192,42 +197,52 @@ static void store_pending_flags(uint32_t mask)
192197
} handlers[BT_MESH_SETTINGS_FLAG_COUNT] = {
193198
[BT_MESH_SETTINGS_RPL_PENDING] = { bt_mesh_rpl_pending_store_all_nodes },
194199
[BT_MESH_SETTINGS_RPL_RESET_PENDING] = { bt_mesh_rpl_pending_store_all_nodes },
195-
[BT_MESH_SETTINGS_NET_KEYS_PENDING] = { bt_mesh_subnet_pending_store },
196-
[BT_MESH_SETTINGS_APP_KEYS_PENDING] = { bt_mesh_app_key_pending_store },
197-
[BT_MESH_SETTINGS_NET_PENDING] = { bt_mesh_net_pending_net_store },
198-
[BT_MESH_SETTINGS_IV_PENDING] = { bt_mesh_net_pending_iv_store },
199-
[BT_MESH_SETTINGS_SEQ_PENDING] = { bt_mesh_net_pending_seq_store },
200+
[BT_MESH_SETTINGS_NET_KEYS_PENDING] = {
201+
SETTINGS_HANDLER(bt_mesh_subnet_pending_store) },
202+
[BT_MESH_SETTINGS_APP_KEYS_PENDING] = {
203+
SETTINGS_HANDLER(bt_mesh_app_key_pending_store) },
204+
[BT_MESH_SETTINGS_NET_PENDING] = {
205+
SETTINGS_HANDLER(bt_mesh_net_pending_net_store) },
206+
[BT_MESH_SETTINGS_IV_PENDING] = {
207+
SETTINGS_HANDLER(bt_mesh_net_pending_iv_store) },
208+
[BT_MESH_SETTINGS_SEQ_PENDING] = {
209+
SETTINGS_HANDLER(bt_mesh_net_pending_seq_store) },
200210
[BT_MESH_SETTINGS_DEV_KEY_CAND_PENDING] = {
201-
bt_mesh_net_pending_dev_key_cand_store },
202-
[BT_MESH_SETTINGS_HB_PUB_PENDING] = { bt_mesh_hb_pub_pending_store },
203-
[BT_MESH_SETTINGS_CFG_PENDING] = { bt_mesh_cfg_pending_store },
204-
[BT_MESH_SETTINGS_COMP_PENDING] = { bt_mesh_comp_data_pending_clear },
205-
[BT_MESH_SETTINGS_MOD_PENDING] = { bt_mesh_model_pending_store },
206-
[BT_MESH_SETTINGS_VA_PENDING] = { bt_mesh_va_pending_store },
211+
SETTINGS_HANDLER(bt_mesh_net_pending_dev_key_cand_store) },
212+
[BT_MESH_SETTINGS_HB_PUB_PENDING] = {
213+
SETTINGS_HANDLER(bt_mesh_hb_pub_pending_store) },
214+
[BT_MESH_SETTINGS_CFG_PENDING] = {
215+
SETTINGS_HANDLER(bt_mesh_cfg_pending_store) },
216+
[BT_MESH_SETTINGS_COMP_PENDING] = {
217+
SETTINGS_HANDLER(bt_mesh_comp_data_pending_clear) },
218+
[BT_MESH_SETTINGS_MOD_PENDING] = {
219+
SETTINGS_HANDLER(bt_mesh_model_pending_store) },
220+
[BT_MESH_SETTINGS_VA_PENDING] = {
221+
SETTINGS_HANDLER(bt_mesh_va_pending_store) },
207222
[BT_MESH_SETTINGS_CDB_PENDING] = {
208223
IS_ENABLED(CONFIG_BT_MESH_CDB) ?
209-
bt_mesh_cdb_pending_store : NULL },
224+
SETTINGS_HANDLER(bt_mesh_cdb_pending_store) : NULL },
210225
[BT_MESH_SETTINGS_SRPL_PENDING] = {
211226
IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) ?
212-
bt_mesh_srpl_pending_store : NULL },
227+
SETTINGS_HANDLER(bt_mesh_srpl_pending_store) : NULL },
213228
[BT_MESH_SETTINGS_SSEQ_PENDING] = {
214229
IS_ENABLED(CONFIG_BT_MESH_PROXY_SOLICITATION) ?
215-
bt_mesh_sseq_pending_store : NULL },
230+
SETTINGS_HANDLER(bt_mesh_sseq_pending_store) : NULL },
216231
[BT_MESH_SETTINGS_BRG_PENDING] = {
217232
IS_ENABLED(CONFIG_BT_MESH_BRG_CFG_SRV) ?
218-
bt_mesh_brg_cfg_pending_store : NULL },
233+
SETTINGS_HANDLER(bt_mesh_brg_cfg_pending_store) : NULL },
219234
};
220235

221236
for (int i = 0; i < ARRAY_SIZE(handlers); i++) {
222-
if (handlers[i].handler == NULL) {
237+
if ((mask & BIT(i)) == 0) {
223238
continue;
224239
}
225240

226-
if ((mask & BIT(i)) == 0) {
241+
if (!atomic_test_and_clear_bit(pending_flags, i)) {
227242
continue;
228243
}
229244

230-
if (atomic_test_and_clear_bit(pending_flags, i)) {
245+
if (handlers[i].handler != NULL) {
231246
handlers[i].handler();
232247
}
233248
}

‎subsys/bluetooth/mesh/settings.h‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
enum bt_mesh_settings_flag {
99
BT_MESH_SETTINGS_RPL_PENDING,
1010
/* Replay list invalidated by an IV Index update, or IV index recovery.
11-
* Stored on CONFIG_BT_MESH_STORE_TIMEOUT rather than the replay list
12-
* timeout.
11+
* Stored immediately rather than on the replay list timeout.
1312
*/
1413
BT_MESH_SETTINGS_RPL_RESET_PENDING,
1514
BT_MESH_SETTINGS_NET_KEYS_PENDING,

‎tests/bluetooth/mesh/settings/CMakeLists.txt‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ target_compile_options(app
3333
-DCONFIG_BT_MESH_OD_PRIV_PROXY_SRV=1
3434
-DCONFIG_BT_MESH_PROXY_SOLICITATION=1
3535
-DCONFIG_BT_MESH_BRG_CFG_SRV=1
36-
-DCONFIG_BT_SETTINGS=1
3736
-DCONFIG_PSA_CRYPTO_PROVIDER_MBEDTLS
3837
)
38+
39+
if(NOT TEST_WITHOUT_BT_SETTINGS)
40+
target_compile_options(app PRIVATE -DCONFIG_BT_SETTINGS=1)
41+
endif()

0 commit comments

Comments
 (0)