1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/net_buf.h>
9 #include <zephyr/bluetooth/mesh.h>
10 
11 #include "settings.h"
12 #include "net.h"
13 #include "rpl.h"
14 
15 #define EMPTY_ENTRIES_CNT (CONFIG_BT_MESH_CRPL - ARRAY_SIZE(test_vector))
16 
17 /* Used for cleaning RPL without checking it. */
18 static bool skip_delete;
19 
20 /* Test function that should call bt_mesh_rpl_check(). */
21 static enum {
22 	SETTINGS_SAVE_ONE = 1,
23 	SETTINGS_DELETE
24 } settings_func;
25 /* Number of `settings_func` calls before calling bt_mesh_rpl_check() (1 means first call). */
26 static int settings_func_cnt;
27 /* Received message context. */
28 static struct bt_mesh_net_rx recv_msg;
29 
30 /* We will change test vector during the test as it is convenient to do so. Therefore, we need
31  * to keep default values separately.
32  */
33 static const struct test_rpl_entry {
34 	char *name;
35 	uint16_t src;
36 	bool old_iv;
37 	uint32_t seq;
38 } test_vector_default[] = {
39 	{ .name = "bt/mesh/RPL/1",  .src = 0x1,  .old_iv = false, .seq = 10, },
40 	{ .name = "bt/mesh/RPL/17", .src = 0x17, .old_iv = true,  .seq = 32, },
41 	{ .name = "bt/mesh/RPL/7c", .src = 0x7c, .old_iv = false, .seq = 20, },
42 	{ .name = "bt/mesh/RPL/2c", .src = 0x2c, .old_iv = true,  .seq = 5,  },
43 	{ .name = "bt/mesh/RPL/5a", .src = 0x5a, .old_iv = true,  .seq = 12, },
44 };
45 static struct test_rpl_entry test_vector[ARRAY_SIZE(test_vector_default)];
46 
47 /**** Helper functions ****/
48 
prepare_rpl_and_start_reset(void)49 static void prepare_rpl_and_start_reset(void)
50 {
51 	/* Add test vector to RPL. */
52 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
53 		struct bt_mesh_net_rx msg = {
54 			.local_match = true,
55 			.ctx.addr = test_vector[i].src,
56 			.old_iv = test_vector[i].old_iv,
57 			.seq = test_vector[i].seq,
58 		};
59 
60 		ztest_expect_value(bt_mesh_settings_store_schedule, flag,
61 				   BT_MESH_SETTINGS_RPL_PENDING);
62 		zassert_false(bt_mesh_rpl_check(&msg, NULL, false));
63 	}
64 
65 	/* settings_save_one() will be triggered for all new entries when
66 	 * bt_mesh_rpl_pending_store() is called.
67 	 */
68 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
69 		ztest_expect_data(settings_save_one, name, test_vector[i].name);
70 	}
71 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
72 
73 	/* Check that all added entries are in RPL. */
74 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
75 		struct bt_mesh_net_rx msg = {
76 			.local_match = true,
77 			.ctx.addr = test_vector[i].src,
78 			.old_iv = test_vector[i].old_iv,
79 			.seq = test_vector[i].seq,
80 		};
81 
82 		zassert_true(bt_mesh_rpl_check(&msg, NULL, false));
83 	}
84 
85 	/* Simulate IVI Update. This should only flip flags. The actual storing will happen
86 	 * when bt_mesh_rpl_pending_store() is called.
87 	 */
88 	ztest_expect_value(bt_mesh_settings_store_schedule, flag, BT_MESH_SETTINGS_RPL_PENDING);
89 	bt_mesh_rpl_reset();
90 }
91 
92 /* Should be called after the reset operation is finished. */
check_entries_from_test_vector(void)93 static void check_entries_from_test_vector(void)
94 {
95 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
96 		struct bt_mesh_net_rx msg = {
97 			.local_match = true,
98 			.ctx.addr = test_vector[i].src,
99 			/* Entries with old_iv == true should have been deleted. old_iv in entries
100 			 * is flipped, so to check this we can try to add the removed entries
101 			 * again. RPL should accept them.
102 			 */
103 			.old_iv = !test_vector[i].old_iv,
104 			.seq = test_vector[i].seq
105 		};
106 
107 		/* Removed entries can now be added again. */
108 		if (test_vector[i].old_iv) {
109 			ztest_expect_value(bt_mesh_settings_store_schedule, flag,
110 					   BT_MESH_SETTINGS_RPL_PENDING);
111 			zassert_false(bt_mesh_rpl_check(&msg, NULL, false));
112 		} else {
113 			zassert_true(bt_mesh_rpl_check(&msg, NULL, false));
114 		}
115 	}
116 }
117 
check_empty_entries(int cnt)118 static void check_empty_entries(int cnt)
119 {
120 	/* Check that RPL has the specified amount of empty entries. */
121 	for (int i = 0; i < cnt; i++) {
122 		struct bt_mesh_net_rx msg = {
123 			.local_match = true,
124 			.ctx.addr = 0x7fff - i,
125 			.old_iv = false,
126 			.seq = i,
127 		};
128 
129 		ztest_expect_value(bt_mesh_settings_store_schedule, flag,
130 				   BT_MESH_SETTINGS_RPL_PENDING);
131 		zassert_false(bt_mesh_rpl_check(&msg, NULL, false));
132 	}
133 
134 	/* Check that there are no more empty entries in RPL. */
135 	struct bt_mesh_net_rx msg = {
136 		.local_match = true,
137 		.ctx.addr = 0x1024,
138 		.old_iv = false,
139 		.seq = 1024,
140 	};
141 	zassert_true(bt_mesh_rpl_check(&msg, NULL, false));
142 }
143 
check_op(int op)144 static void check_op(int op)
145 {
146 	if (settings_func == op) {
147 		if (settings_func_cnt > 1) {
148 			settings_func_cnt--;
149 		} else {
150 			ztest_expect_value(bt_mesh_settings_store_schedule, flag,
151 					   BT_MESH_SETTINGS_RPL_PENDING);
152 			zassert_false(bt_mesh_rpl_check(&recv_msg, NULL, false));
153 
154 			settings_func_cnt--;
155 			settings_func = 0;
156 		}
157 	}
158 }
159 
call_rpl_check_on(int func,int cnt,struct test_rpl_entry * entry)160 static void call_rpl_check_on(int func, int cnt, struct test_rpl_entry *entry)
161 {
162 	settings_func = func;
163 	settings_func_cnt = cnt;
164 
165 	recv_msg.local_match = true;
166 	recv_msg.ctx.addr = entry->src;
167 	recv_msg.seq = entry->seq;
168 	recv_msg.old_iv = entry->old_iv;
169 }
170 
expect_pending_store(void)171 static void expect_pending_store(void)
172 {
173 	/* Entries with old_iv == true should be removed, others should be stored. */
174 	for (int i = 0; i < ARRAY_SIZE(test_vector); i++) {
175 		if (test_vector[i].old_iv) {
176 			ztest_expect_value(settings_delete, name, test_vector[i].name);
177 		} else {
178 			ztest_expect_data(settings_save_one, name, test_vector[i].name);
179 		}
180 	}
181 }
182 
is_rpl_check_called(void)183 static bool is_rpl_check_called(void)
184 {
185 	return settings_func_cnt == 0;
186 }
187 
verify_rpl(void)188 static void verify_rpl(void)
189 {
190 	check_entries_from_test_vector();
191 	check_empty_entries(EMPTY_ENTRIES_CNT);
192 }
193 
setup(void * f)194 static void setup(void *f)
195 {
196 	/* Restore test vector. */
197 	memcpy(test_vector, test_vector_default, sizeof(test_vector));
198 
199 	/* Clear RPL before every test. */
200 	skip_delete = true;
201 	ztest_expect_value(bt_mesh_settings_store_schedule, flag, BT_MESH_SETTINGS_RPL_PENDING);
202 	bt_mesh_rpl_clear();
203 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
204 	skip_delete = false;
205 
206 	settings_func = 0;
207 	settings_func_cnt = 0;
208 }
209 
210 /**** Mocked functions ****/
211 
bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)212 void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)
213 {
214 	ztest_check_expected_value(flag);
215 }
216 
bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag)217 void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag)
218 {
219 }
220 
settings_save_one(const char * name,const void * value,size_t val_len)221 int settings_save_one(const char *name, const void *value, size_t val_len)
222 {
223 	ztest_check_expected_data(name, strlen(name));
224 
225 	check_op(SETTINGS_SAVE_ONE);
226 
227 	return 0;
228 }
229 
settings_delete(const char * name)230 int settings_delete(const char *name)
231 {
232 	if (skip_delete) {
233 		return 0;
234 	}
235 
236 	ztest_check_expected_data(name, strlen(name));
237 
238 	check_op(SETTINGS_DELETE);
239 
240 	return 0;
241 }
242 
243 /**** Tests ****/
244 
245 ZTEST_SUITE(bt_mesh_rpl_reset, NULL, NULL, setup, NULL, NULL);
246 
247 /** Test that entries with old_iv == true are removed after the reset operation finished. */
ZTEST(bt_mesh_rpl_reset,test_reset_normal)248 ZTEST(bt_mesh_rpl_reset, test_reset_normal)
249 {
250 	prepare_rpl_and_start_reset();
251 	expect_pending_store();
252 
253 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
254 
255 	verify_rpl();
256 }
257 
258 /** Test that RPL accepts and stores a valid entry that was just deleted. The entry should be
259  * stored after the reset operation is finished.
260  */
ZTEST(bt_mesh_rpl_reset,test_rpl_check_on_delete_same_entry)261 ZTEST(bt_mesh_rpl_reset, test_rpl_check_on_delete_same_entry)
262 {
263 	prepare_rpl_and_start_reset();
264 	expect_pending_store();
265 
266 	/* Take the first entry with old_iv == true and simulate msg reception with same src
267 	 * address and correct IVI after the entry was deleted.
268 	 */
269 	struct test_rpl_entry *entry = &test_vector[1];
270 
271 	zassert_true(entry->old_iv);
272 	entry->old_iv = false;
273 	call_rpl_check_on(SETTINGS_DELETE, 1, entry);
274 
275 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
276 	zassert_true(is_rpl_check_called());
277 
278 	/* Call bt_mesh_rpl_pending_store() to store new entry. */
279 	ztest_expect_data(settings_save_one, name, entry->name);
280 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
281 
282 	verify_rpl();
283 }
284 
285 /** Test that RPL accepts and stores a valid entry that was just stored. The entry should be stored
286  * after the reset operation is finished.
287  */
ZTEST(bt_mesh_rpl_reset,test_rpl_check_on_save_same_entry)288 ZTEST(bt_mesh_rpl_reset, test_rpl_check_on_save_same_entry)
289 {
290 	prepare_rpl_and_start_reset();
291 	expect_pending_store();
292 
293 	/* Take the first entry with old_iv == false and simulate msg reception with same src
294 	 * address and correct IVI after the entry was stored.
295 	 */
296 	struct test_rpl_entry *entry = &test_vector[0];
297 
298 	zassert_false(entry->old_iv);
299 	call_rpl_check_on(SETTINGS_SAVE_ONE, 1, entry);
300 
301 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
302 	zassert_true(is_rpl_check_called());
303 
304 	/* Call bt_mesh_rpl_pending_store() to store new entry. */
305 	ztest_expect_data(settings_save_one, name, entry->name);
306 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
307 
308 	verify_rpl();
309 }
310 
311 /** Test that RPL accepts and stores a valid entry that has not yet been deleted. The entry should
312  * be stored during the reset operation.
313  */
ZTEST(bt_mesh_rpl_reset,test_rpl_check_on_delete_other_entry)314 ZTEST(bt_mesh_rpl_reset, test_rpl_check_on_delete_other_entry)
315 {
316 	prepare_rpl_and_start_reset();
317 
318 	/* Take the non-first entry with old_iv == true and simulate msg reception with same src
319 	 * address and correct IVI before the entry is deleted.
320 	 *
321 	 * Should be done before calling ztest_expect_data() because the expectation changes.
322 	 */
323 	struct test_rpl_entry *entry = &test_vector[3];
324 
325 	zassert_true(entry->old_iv);
326 	entry->old_iv = false;
327 	call_rpl_check_on(SETTINGS_DELETE, 1, entry);
328 
329 	expect_pending_store();
330 
331 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
332 	zassert_true(is_rpl_check_called());
333 
334 	/* The entry should have been deleted in previous bt_mesh_rpl_pending_store() call. Another
335 	 * call should not do anything.
336 	 */
337 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
338 
339 	verify_rpl();
340 }
341 
342 /* Test that RPL accepts and stores a valid entry that has not yet been stored. The entry should be
343  * stored during the reset operation.
344  */
ZTEST(bt_mesh_rpl_reset,test_rpl_check_on_save_other_entry)345 ZTEST(bt_mesh_rpl_reset, test_rpl_check_on_save_other_entry)
346 {
347 	prepare_rpl_and_start_reset();
348 
349 	/* Take RPL entry from test vector that has old_iv == false and is not stored yet after
350 	 * bt_mesh_reset() call and try to store it again. RPL has such entry with flipped old_iv,
351 	 * so this one can be accepted as is.
352 	 *
353 	 * Should be done before calling ztest_expect_data() because the expectation changes.
354 	 */
355 	struct test_rpl_entry *entry = &test_vector[2];
356 
357 	zassert_false(entry->old_iv);
358 	call_rpl_check_on(SETTINGS_SAVE_ONE, 1, entry);
359 
360 	expect_pending_store();
361 
362 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
363 	zassert_true(is_rpl_check_called());
364 
365 	/* The entry should have been stored in previous bt_mesh_rpl_pending_store() call. Another
366 	 * call should not do anything.
367 	 */
368 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
369 
370 	verify_rpl();
371 }
372 
373 /** Test that RPL accepts and stores a valid entry that has been deleted during the reset operation.
374  * The entry will be added at the end of RPL, therefore it should be stored during the reset
375  * operation.
376  */
ZTEST(bt_mesh_rpl_reset,test_rpl_check_on_delete_deleted_entry)377 ZTEST(bt_mesh_rpl_reset, test_rpl_check_on_delete_deleted_entry)
378 {
379 	prepare_rpl_and_start_reset();
380 	expect_pending_store();
381 
382 	/* Take the first entry with old_iv == true, wait until bt_mesh_rpl_pending_store() takes
383 	 * another entry after that one and simulate msg reception.
384 	 */
385 	struct test_rpl_entry *entry = &test_vector[1];
386 
387 	zassert_true(entry->old_iv);
388 	entry->old_iv = false;
389 	call_rpl_check_on(SETTINGS_DELETE, 2, entry);
390 	/* The entry will be stored during the reset operation as it will be added to the end of
391 	 * the RPL.
392 	 */
393 	ztest_expect_data(settings_save_one, name, entry->name);
394 
395 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
396 	zassert_true(is_rpl_check_called());
397 
398 	/* The new entry should have been stored already. Another bt_mesh_rpl_pending_store() call
399 	 * should not do anything.
400 	 */
401 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
402 
403 	verify_rpl();
404 }
405 
406 /** Test that RPL accepts and stores a valid entry that has been stored during the reset operation.
407  * Since the entry has been already in the list, it should be stored again after the reset
408  * operation is finished.
409  */
ZTEST(bt_mesh_rpl_reset,test_rpl_check_on_store_stored_entry)410 ZTEST(bt_mesh_rpl_reset, test_rpl_check_on_store_stored_entry)
411 {
412 	prepare_rpl_and_start_reset();
413 	expect_pending_store();
414 
415 	/* Take the first entry with old_iv == false, wait until bt_mesh_rpl_pending_store() takes
416 	 * another entry after that one and simulate msg reception.
417 	 */
418 	struct test_rpl_entry *entry = &test_vector[0];
419 
420 	zassert_false(entry->old_iv);
421 	entry->old_iv = true;
422 	entry->seq++;
423 	call_rpl_check_on(SETTINGS_SAVE_ONE, 2, entry);
424 
425 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
426 	zassert_true(is_rpl_check_called());
427 
428 	/* The entry was updated after bt_mesh_rpl_pending_store() checked it. So it should be
429 	 * stored again.
430 	 */
431 	ztest_expect_data(settings_save_one, name, entry->name);
432 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
433 
434 	verify_rpl();
435 }
436 
437 /** Test that RPL accepts and stores a new entry when the reset operation is not yet finished. */
ZTEST(bt_mesh_rpl_reset,test_rpl_check_on_save_new_entry)438 ZTEST(bt_mesh_rpl_reset, test_rpl_check_on_save_new_entry)
439 {
440 	prepare_rpl_and_start_reset();
441 	expect_pending_store();
442 
443 	/* Add a new entry to RPL during the reset operation. */
444 	struct test_rpl_entry entry = {
445 		.name = "bt/mesh/RPL/2b",
446 		.src = 43,
447 		.old_iv = false,
448 		.seq = 32,
449 	};
450 	ztest_expect_data(settings_save_one, name, entry.name);
451 	call_rpl_check_on(SETTINGS_SAVE_ONE, 1, &entry);
452 
453 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
454 	zassert_true(is_rpl_check_called());
455 
456 	/* The entry should have been stored in previous bt_mesh_rpl_pending_store() call. Another
457 	 * call should not do anything.
458 	 */
459 	bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES);
460 
461 	check_entries_from_test_vector();
462 	/* Check that added entry in the RPL. */
463 	struct bt_mesh_net_rx msg = {
464 		.local_match = true,
465 		.ctx.addr = entry.src,
466 		.old_iv = entry.old_iv,
467 		.seq = entry.seq
468 	};
469 	zassert_true(bt_mesh_rpl_check(&msg, NULL, false));
470 	check_empty_entries(EMPTY_ENTRIES_CNT - 1);
471 }
472