1 /*
2 * Copyright (c) 2024 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 #include <stdlib.h>
11
12 #include "settings.h"
13 #include "brg_cfg.h"
14 #include "foundation.h"
15
16 #define TEST_VECT_SZ (CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX + 1)
17
18 static struct test_brg_cfg_row {
19 uint8_t direction;
20 uint16_t net_idx1;
21 uint16_t net_idx2;
22 uint16_t addr1;
23 uint16_t addr2;
24 } test_vector[TEST_VECT_SZ];
25
26 #define ADDR1_BASE (1)
27 #define ADDR2_BASE (100)
28
29 /**** Helper functions ****/
setup(void * f)30 static void setup(void *f)
31 {
32 /* create test vector */
33 for (int i = 0; i < TEST_VECT_SZ; i++) {
34 test_vector[i].direction = i < (TEST_VECT_SZ / 2) ? 1 : 2;
35 test_vector[i].net_idx1 = (i / 8);
36 test_vector[i].addr1 = ADDR1_BASE + i;
37 test_vector[i].net_idx2 = (i / 8) + 16;
38 test_vector[i].addr2 = ADDR2_BASE + i;
39 }
40 }
41
42 /**** Mocked functions ****/
43
bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)44 void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)
45 {
46 ztest_check_expected_value(flag);
47 }
48
settings_save_one(const char * name,const void * value,size_t val_len)49 int settings_save_one(const char *name, const void *value, size_t val_len)
50 {
51 ztest_check_expected_data(name, strlen(name));
52 ztest_check_expected_value(val_len);
53 ztest_check_expected_data(value, val_len);
54 return 0;
55 }
56
settings_delete(const char * name)57 int settings_delete(const char *name)
58 {
59 ztest_check_expected_data(name, strlen(name));
60 return 0;
61 }
62
bt_mesh_subnet_get(uint16_t net_idx)63 struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx)
64 {
65 /* Return anything non-zero. */
66 return (struct bt_mesh_subnet *)1;
67 }
68
69 /**** Mocked functions - end ****/
70
check_fill_all_bt_entries(void)71 static void check_fill_all_bt_entries(void)
72 {
73 uint8_t status;
74 int err;
75
76 for (int i = 0; i < TEST_VECT_SZ; i++) {
77
78 if (i < CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
79 ztest_expect_value(bt_mesh_settings_store_schedule, flag,
80 BT_MESH_SETTINGS_BRG_PENDING);
81 }
82
83 err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction, test_vector[i].net_idx1,
84 test_vector[i].net_idx2, test_vector[i].addr1,
85 test_vector[i].addr2, &status);
86
87 zassert_equal(err, 0);
88
89 if (i != CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
90 zassert_equal(status, STATUS_SUCCESS);
91 } else {
92 zassert_equal(status, STATUS_INSUFF_RESOURCES);
93 }
94 }
95 }
96
check_delete_all_bt_entries(void)97 static void check_delete_all_bt_entries(void)
98 {
99 uint8_t status;
100
101 for (int i = 0; i < TEST_VECT_SZ; i++) {
102
103 if (i < CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
104 ztest_expect_value(bt_mesh_settings_store_schedule, flag,
105 BT_MESH_SETTINGS_BRG_PENDING);
106 }
107
108 int err = bt_mesh_brg_cfg_tbl_remove(test_vector[i].net_idx1,
109 test_vector[i].net_idx2, test_vector[i].addr1,
110 test_vector[i].addr2, &status);
111
112 zassert_equal(err, 0);
113 zassert_equal(status, STATUS_SUCCESS);
114 }
115 }
116
check_bt_mesh_brg_cfg_tbl_reset(void)117 static void check_bt_mesh_brg_cfg_tbl_reset(void)
118 {
119 int err;
120
121 ztest_expect_data(settings_delete, name, "bt/mesh/brg_en");
122 ztest_expect_data(settings_delete, name, "bt/mesh/brg_tbl");
123 err = bt_mesh_brg_cfg_tbl_reset();
124 zassert_equal(err, 0);
125 }
126
127 /**** Tests ****/
128
129 ZTEST_SUITE(bt_mesh_brg_cfg, NULL, NULL, setup, NULL, NULL);
130
131 /* Test if basic functionality (add and remove entries) works correctly. */
ZTEST(bt_mesh_brg_cfg,test_basic_functionality_storage)132 ZTEST(bt_mesh_brg_cfg, test_basic_functionality_storage)
133 {
134 check_bt_mesh_brg_cfg_tbl_reset();
135
136 /* Test add entries to bridging table. */
137 check_fill_all_bt_entries();
138
139 /* Test remove entries from bridging table, and then fill it again. */
140 check_delete_all_bt_entries();
141 check_fill_all_bt_entries();
142
143 /* Test resetting of the table, and then fill it again. */
144 check_bt_mesh_brg_cfg_tbl_reset();
145 check_fill_all_bt_entries();
146
147 uint8_t status;
148 int err;
149 uint16_t net_idx1 = test_vector[TEST_VECT_SZ - 1].net_idx1;
150 uint16_t net_idx2 = test_vector[TEST_VECT_SZ - 1].net_idx2;
151 uint16_t addr1 = BT_MESH_ADDR_UNASSIGNED;
152
153 /* Try removing entries with invalid params */
154 uint16_t addr2 = BT_MESH_ADDR_ALL_NODES;
155
156 err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
157 zassert_equal(err, -EINVAL);
158
159 addr2 = BT_MESH_ADDR_UNASSIGNED;
160 addr1 = BT_MESH_ADDR_RELAYS;
161 err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
162 zassert_equal(err, -EINVAL);
163
164 addr1 = BT_MESH_ADDR_UNASSIGNED;
165 net_idx1 = 4096;
166 err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
167 zassert_equal(err, -EINVAL);
168
169 net_idx1 = test_vector[TEST_VECT_SZ - 1].net_idx1;
170 net_idx2 = 4096;
171 err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
172 zassert_equal(err, -EINVAL);
173
174 /* Test remove entries matching netkey1, and netkey2 */
175 net_idx2 = test_vector[TEST_VECT_SZ - 1].net_idx2;
176 err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
177 zassert_equal(err, 0);
178
179 const struct bt_mesh_brg_cfg_row *brg_tbl;
180 int n = bt_mesh_brg_cfg_tbl_get(&brg_tbl);
181
182 zassert_true(n > 0);
183
184 for (int i = 0; i < n; i++) {
185 zassert_true(brg_tbl[i].net_idx1 != net_idx1);
186 zassert_true(brg_tbl[i].net_idx2 != net_idx2);
187 }
188
189 check_bt_mesh_brg_cfg_tbl_reset();
190 check_fill_all_bt_entries();
191
192 /* Test remove entries matching netkey1, and netkey2, and addr1 */
193 addr1 = test_vector[TEST_VECT_SZ - 1].addr1;
194 n = bt_mesh_brg_cfg_tbl_get(&brg_tbl);
195
196 zassert_true(n > 0);
197
198 for (int i = 0; i < n; i++) {
199 zassert_true(brg_tbl[i].net_idx1 != net_idx1);
200 zassert_true(brg_tbl[i].net_idx2 != net_idx2);
201 zassert_true(brg_tbl[i].addr1 != addr1);
202 }
203
204 check_bt_mesh_brg_cfg_tbl_reset();
205 check_fill_all_bt_entries();
206
207 /* Test remove entries matching netkey1, and netkey2, and addr2 */
208 addr1 = BT_MESH_ADDR_UNASSIGNED;
209 addr2 = test_vector[TEST_VECT_SZ - 1].addr2;
210 n = bt_mesh_brg_cfg_tbl_get(&brg_tbl);
211
212 zassert_true(n > 0);
213
214 for (int i = 0; i < n; i++) {
215 zassert_true(brg_tbl[i].net_idx1 != net_idx1);
216 zassert_true(brg_tbl[i].net_idx2 != net_idx2);
217 zassert_true(brg_tbl[i].addr2 != addr2);
218 }
219 }
220
check_bt_mesh_brg_cfg_tbl_multiple_delete(int expect_left)221 static void check_bt_mesh_brg_cfg_tbl_multiple_delete(int expect_left)
222 {
223 uint8_t status;
224 int err;
225 int n;
226 const struct bt_mesh_brg_cfg_row *brg_tbl;
227
228 n = bt_mesh_brg_cfg_tbl_get(&brg_tbl);
229 zassert_equal(n, TEST_VECT_SZ - 1);
230
231 ztest_expect_value(bt_mesh_settings_store_schedule, flag, BT_MESH_SETTINGS_BRG_PENDING);
232 err = bt_mesh_brg_cfg_tbl_remove(test_vector[1].net_idx1, test_vector[1].net_idx2,
233 test_vector[1].addr1, BT_MESH_ADDR_UNASSIGNED, &status);
234 zassert_equal(err, 0);
235
236 n = bt_mesh_brg_cfg_tbl_get(&brg_tbl);
237 zassert_equal(n, expect_left);
238
239 for (int i = 0; i < n; i++) {
240 zassert_true(brg_tbl[i].net_idx1 == test_vector[0].net_idx1);
241 zassert_true(brg_tbl[i].net_idx2 == test_vector[0].net_idx2);
242 zassert_true(brg_tbl[i].addr1 == test_vector[0].addr1);
243 zassert_true(brg_tbl[i].addr2 == test_vector[i * 2].addr2);
244 }
245 }
246
ZTEST(bt_mesh_brg_cfg,test_removal_multiple_entries)247 ZTEST(bt_mesh_brg_cfg, test_removal_multiple_entries)
248 {
249 check_bt_mesh_brg_cfg_tbl_reset();
250
251 uint8_t status;
252 int err;
253
254 /* Test removal of every second entry */
255 for (int i = 0; i < TEST_VECT_SZ - 1; i++) {
256 ztest_expect_value(bt_mesh_settings_store_schedule, flag,
257 BT_MESH_SETTINGS_BRG_PENDING);
258 err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction, test_vector[i % 2].net_idx1,
259 test_vector[i % 2].net_idx2, test_vector[i % 2].addr1,
260 test_vector[i].addr2, &status);
261 zassert_equal(err, 0);
262 zassert_equal(status, STATUS_SUCCESS);
263 }
264
265 check_bt_mesh_brg_cfg_tbl_multiple_delete((TEST_VECT_SZ - 1) / 2);
266 check_bt_mesh_brg_cfg_tbl_reset();
267
268 /* Test removal of all entries, except first */
269 for (int i = 0; i < TEST_VECT_SZ - 1; i++) {
270 ztest_expect_value(bt_mesh_settings_store_schedule, flag,
271 BT_MESH_SETTINGS_BRG_PENDING);
272 if (i == 0) {
273 err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction,
274 test_vector[i].net_idx1,
275 test_vector[i].net_idx2, test_vector[i].addr1,
276 test_vector[i].addr2, &status);
277 } else {
278 err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction,
279 test_vector[1].net_idx1,
280 test_vector[1].net_idx2, test_vector[1].addr1,
281 test_vector[i].addr2, &status);
282 }
283 zassert_equal(err, 0);
284 zassert_equal(status, STATUS_SUCCESS);
285 }
286
287 check_bt_mesh_brg_cfg_tbl_multiple_delete(1);
288 check_bt_mesh_brg_cfg_tbl_reset();
289
290 /* Test removal of all entries, except last */
291 for (int i = TEST_VECT_SZ - 2; i >= 0; i--) {
292 ztest_expect_value(bt_mesh_settings_store_schedule, flag,
293 BT_MESH_SETTINGS_BRG_PENDING);
294 if (i == 0) {
295 err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction,
296 test_vector[i].net_idx1,
297 test_vector[i].net_idx2, test_vector[i].addr1,
298 test_vector[i].addr2, &status);
299 } else {
300 err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction,
301 test_vector[1].net_idx1,
302 test_vector[1].net_idx2, test_vector[1].addr1,
303 test_vector[i].addr2, &status);
304 }
305 zassert_equal(err, 0);
306 zassert_equal(status, STATUS_SUCCESS);
307 }
308
309 check_bt_mesh_brg_cfg_tbl_multiple_delete(1);
310 check_bt_mesh_brg_cfg_tbl_reset();
311
312 /* Test removal of all entries */
313 for (int i = 0; i < TEST_VECT_SZ - 1; i++) {
314 ztest_expect_value(bt_mesh_settings_store_schedule, flag,
315 BT_MESH_SETTINGS_BRG_PENDING);
316 err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction, test_vector[1].net_idx1,
317 test_vector[1].net_idx2, test_vector[1].addr1,
318 test_vector[i].addr2, &status);
319 zassert_equal(err, 0);
320 zassert_equal(status, STATUS_SUCCESS);
321 }
322
323 check_bt_mesh_brg_cfg_tbl_multiple_delete(0);
324 }
325
pending_store_enable_create_expectations(bool * enable_val)326 static void pending_store_enable_create_expectations(bool *enable_val)
327 {
328 if (*enable_val) {
329 ztest_expect_data(settings_save_one, name, "bt/mesh/brg_en");
330 ztest_expect_value(settings_save_one, val_len, 1);
331 ztest_expect_data(settings_save_one, value, enable_val);
332 } else {
333 ztest_expect_data(settings_delete, name, "bt/mesh/brg_en");
334 }
335 }
336
pending_store_tbl_create_expectations(int n,const struct bt_mesh_brg_cfg_row * tbl_val)337 static void pending_store_tbl_create_expectations(int n, const struct bt_mesh_brg_cfg_row *tbl_val)
338 {
339 if (n > 0) {
340 ztest_expect_data(settings_save_one, name, "bt/mesh/brg_tbl");
341 ztest_expect_value(settings_save_one, val_len,
342 n * sizeof(struct bt_mesh_brg_cfg_row));
343 ztest_expect_data(settings_save_one, value, tbl_val);
344 } else {
345 ztest_expect_data(settings_delete, name, "bt/mesh/brg_tbl");
346 }
347 }
348
349 /* Test if enable flag is stored correctly. */
ZTEST(bt_mesh_brg_cfg,test_brg_cfg_en)350 ZTEST(bt_mesh_brg_cfg, test_brg_cfg_en)
351 {
352 int err;
353 bool val;
354
355 check_bt_mesh_brg_cfg_tbl_reset();
356 val = bt_mesh_brg_cfg_enable_get();
357 zassert_equal(val, false, NULL);
358 /* No changed to the states, nothing to check. */
359
360 ztest_expect_value(bt_mesh_settings_store_schedule, flag, BT_MESH_SETTINGS_BRG_PENDING);
361 err = bt_mesh_brg_cfg_enable_set(true);
362 zassert_equal(err, 0, NULL);
363 val = bt_mesh_brg_cfg_enable_get();
364 pending_store_enable_create_expectations(&val);
365 bt_mesh_brg_cfg_pending_store();
366
367 zassert_equal(bt_mesh_brg_cfg_enable_get(), true, NULL);
368 }
369
370 /* Test if pending store works correctly by adding one entry to the table. */
ZTEST(bt_mesh_brg_cfg,test_brg_tbl_pending_store)371 ZTEST(bt_mesh_brg_cfg, test_brg_tbl_pending_store)
372 {
373 uint8_t status;
374 int n, err;
375 struct bt_mesh_brg_cfg_row test_vec = {
376 .direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
377 .net_idx1 = 1,
378 .net_idx2 = 2,
379 .addr1 = 3,
380 .addr2 = 4,
381 };
382
383 check_bt_mesh_brg_cfg_tbl_reset();
384 ztest_expect_value(bt_mesh_settings_store_schedule, flag, BT_MESH_SETTINGS_BRG_PENDING);
385 err = bt_mesh_brg_cfg_tbl_add(test_vec.direction, test_vec.net_idx1, test_vec.net_idx2,
386 test_vec.addr1, test_vec.addr2, &status);
387 zassert_equal(err, 0);
388 zassert_equal(status, STATUS_SUCCESS);
389
390 const struct bt_mesh_brg_cfg_row *tbl;
391
392 n = bt_mesh_brg_cfg_tbl_get(&tbl);
393
394 zassert_equal(n, 1);
395 zassert_true(tbl);
396
397 pending_store_tbl_create_expectations(1, &test_vec);
398 bt_mesh_brg_cfg_pending_store();
399 }
400
401 /* Value is prohibited. */
402 #define BT_MESH_BRG_CFG_DIR_PROHIBITED 0
403 /* Values above and including this is prohibited. */
404 #define BT_MESH_BRG_CFG_DIR_MAX 3
405
406 /* Test if invalid entries are not added to the table. */
ZTEST(bt_mesh_brg_cfg,test_tbl_add_invalid_ip)407 ZTEST(bt_mesh_brg_cfg, test_tbl_add_invalid_ip)
408 {
409 uint8_t status;
410 int err;
411 /* Create test vector array of test_brg_cfg_row iteams with invalid values.
412 * Each vector has only one invalid field value, rest all are valid values.
413 */
414 const struct test_brg_cfg_row inv_test_vector[] = {
415 /* Direction has invalid values */
416 {.direction = BT_MESH_BRG_CFG_DIR_PROHIBITED,
417 .net_idx1 = 0,
418 .net_idx2 = 1,
419 .addr1 = 1,
420 .addr2 = 2},
421 {.direction = BT_MESH_BRG_CFG_DIR_MAX,
422 .net_idx1 = 0,
423 .net_idx2 = 1,
424 .addr1 = 1,
425 .addr2 = 2},
426 /* Out of range netidx values */
427 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
428 .net_idx1 = 4096,
429 .net_idx2 = 1,
430 .addr1 = 1,
431 .addr2 = 2},
432 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
433 .net_idx1 = 0,
434 .net_idx2 = 4096,
435 .addr1 = 1,
436 .addr2 = 2},
437 /* Same netidx values */
438 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
439 .net_idx1 = 0,
440 .net_idx2 = 0,
441 .addr1 = 1,
442 .addr2 = 2},
443 /* Same addr values */
444 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
445 .net_idx1 = 0,
446 .net_idx2 = 1,
447 .addr1 = 1,
448 .addr2 = 1},
449 /* Invalid address1 value */
450 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
451 .net_idx1 = 0,
452 .net_idx2 = 1,
453 .addr1 = 0,
454 .addr2 = 1},
455 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
456 .net_idx1 = 0,
457 .net_idx2 = 1,
458 .addr1 = 0x8000,
459 .addr2 = 1},
460 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
461 .net_idx1 = 0,
462 .net_idx2 = 1,
463 .addr1 = 0xC000,
464 .addr2 = 1},
465 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
466 .net_idx1 = 0,
467 .net_idx2 = 1,
468 .addr1 = 0xFFFE,
469 .addr2 = 1},
470 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
471 .net_idx1 = 0,
472 .net_idx2 = 1,
473 .addr1 = 0xFFFF,
474 .addr2 = 1},
475 /* Invalid address2 values */
476 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
477 .net_idx1 = 0,
478 .net_idx2 = 1,
479 .addr1 = 1,
480 .addr2 = 0},
481 {.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
482 .net_idx1 = 0,
483 .net_idx2 = 1,
484 .addr1 = 1,
485 .addr2 = 0xFFFF},
486 {.direction = BT_MESH_BRG_CFG_DIR_TWOWAY,
487 .net_idx1 = 0,
488 .net_idx2 = 1,
489 .addr1 = 1,
490 .addr2 = 0x8000},
491 {.direction = BT_MESH_BRG_CFG_DIR_TWOWAY,
492 .net_idx1 = 0,
493 .net_idx2 = 1,
494 .addr1 = 1,
495 .addr2 = 0xC000},
496 {.direction = BT_MESH_BRG_CFG_DIR_TWOWAY,
497 .net_idx1 = 0,
498 .net_idx2 = 1,
499 .addr1 = 1,
500 .addr2 = 0xFFFE},
501 {.direction = BT_MESH_BRG_CFG_DIR_TWOWAY,
502 .net_idx1 = 0,
503 .net_idx2 = 1,
504 .addr1 = 1,
505 .addr2 = 0xFFFF},
506 };
507
508 check_bt_mesh_brg_cfg_tbl_reset();
509
510 for (int i = 0; i < ARRAY_SIZE(inv_test_vector); i++) {
511 err = bt_mesh_brg_cfg_tbl_add(inv_test_vector[i].direction,
512 inv_test_vector[i].net_idx1,
513 inv_test_vector[i].net_idx2, inv_test_vector[i].addr1,
514 inv_test_vector[i].addr2, &status);
515 zassert_equal(err, -EINVAL, "Test vector index: %zu", i);
516 }
517 }
518
519 /* Following are helper functions for the test that checks the iteration logic */
520 #define NUM_MSGS (10000)
521
print_brg_tbl(void)522 static void print_brg_tbl(void)
523 {
524 const struct bt_mesh_brg_cfg_row *tbl;
525 int n = bt_mesh_brg_cfg_tbl_get(&tbl);
526
527 zassert_true(n <= CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX);
528
529 for (int i = 0; i < n; i++) {
530 printk("entry: %3d # dir: %d, net_idx1: %3d, addr1: %3d, net_idx2: %3d, addr2: "
531 "%3d\n",
532 i, tbl[i].direction, tbl[i].net_idx1, tbl[i].addr1, tbl[i].net_idx2,
533 tbl[i].addr2);
534 }
535 }
536
check_fill_all_bt_entries_reversed(void)537 static void check_fill_all_bt_entries_reversed(void)
538 {
539 uint8_t status;
540 int err;
541
542 for (int i = TEST_VECT_SZ - 2; i >= 0; i--) {
543 ztest_expect_value(bt_mesh_settings_store_schedule, flag,
544 BT_MESH_SETTINGS_BRG_PENDING);
545 err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction, test_vector[i].net_idx1,
546 test_vector[i].net_idx2, test_vector[i].addr1,
547 test_vector[i].addr2, &status);
548 zassert_equal(err, 0);
549 }
550
551 int last = TEST_VECT_SZ - 1;
552
553 err = bt_mesh_brg_cfg_tbl_add(test_vector[last].direction, test_vector[last].net_idx1,
554 test_vector[last].net_idx2, test_vector[last].addr1,
555 test_vector[last].addr2, &status);
556 zassert_equal(err, 0);
557 zassert_equal(status, STATUS_INSUFF_RESOURCES);
558 }
559
560 static struct test_brg_cfg_row test_vector_copy[TEST_VECT_SZ - 1];
561
check_fill_all_bt_entries_randomly(void)562 static void check_fill_all_bt_entries_randomly(void)
563 {
564 uint8_t status;
565 int err;
566 int copy_cnt = ARRAY_SIZE(test_vector_copy);
567
568 memcpy(test_vector_copy, test_vector, sizeof(test_vector_copy));
569
570 for (int i = 0; i < copy_cnt; i++) {
571 int idx = rand() % copy_cnt;
572 struct test_brg_cfg_row tmp = test_vector_copy[i];
573
574 test_vector_copy[i] = test_vector_copy[idx];
575 test_vector_copy[idx] = tmp;
576 }
577
578 for (int i = 0; i < copy_cnt; i++) {
579 ztest_expect_value(bt_mesh_settings_store_schedule, flag,
580 BT_MESH_SETTINGS_BRG_PENDING);
581 err = bt_mesh_brg_cfg_tbl_add(
582 test_vector_copy[i].direction, test_vector_copy[i].net_idx1,
583 test_vector_copy[i].net_idx2, test_vector_copy[i].addr1,
584 test_vector_copy[i].addr2, &status);
585 zassert_equal(err, 0);
586 zassert_equal(status, STATUS_SUCCESS);
587 }
588
589 int last = TEST_VECT_SZ - 1;
590
591 err = bt_mesh_brg_cfg_tbl_add(test_vector[last].direction, test_vector[last].net_idx1,
592 test_vector[last].net_idx2, test_vector[last].addr1,
593 test_vector[last].addr2, &status);
594 zassert_equal(err, 0);
595 zassert_equal(status, STATUS_INSUFF_RESOURCES);
596 }
597
subnet_relay_cb_check(uint16_t new_net_idx,void * user_data)598 static void subnet_relay_cb_check(uint16_t new_net_idx, void *user_data)
599 {
600 int idx = *(int *)user_data;
601
602 zassert_equal(new_net_idx, test_vector[idx].net_idx2);
603 }
604
subnet_relay_cb_check_rev(uint16_t new_net_idx,void * user_data)605 static void subnet_relay_cb_check_rev(uint16_t new_net_idx, void *user_data)
606 {
607 int idx = *(int *)user_data;
608
609 if (test_vector[idx].direction == 2) {
610 zassert_equal(new_net_idx, test_vector[idx].net_idx1);
611 } else {
612 /* Should never assert. Test vector created in setup(). */
613 zassert_true(false);
614 }
615 }
616
test_bridging_performance(bool test_one_way)617 static void test_bridging_performance(bool test_one_way)
618 {
619 int idx;
620 uint32_t tick1;
621 uint32_t ticks = 0;
622
623 for (int i = 0; i < NUM_MSGS; i++) {
624 /* randomly pick an entry from the test vector */
625 idx = rand() % TEST_VECT_SZ;
626
627 /* check src to dst bridging*/
628 const struct bt_mesh_brg_cfg_row *tbl_row = NULL;
629
630 tick1 = k_uptime_ticks();
631 bt_mesh_brg_cfg_tbl_foreach_subnet(test_vector[idx].addr1, test_vector[idx].addr2,
632 test_vector[idx].net_idx1, subnet_relay_cb_check,
633 &idx);
634 ticks += k_uptime_ticks() - tick1;
635
636 if (test_one_way) {
637 continue;
638 }
639
640 /* check dst to src bridging - for the same test vector src-dst pairs
641 * but now, reverse them and consider packets are arriving on net_idx2
642 */
643 tbl_row = NULL;
644 tick1 = k_uptime_ticks();
645 bt_mesh_brg_cfg_tbl_foreach_subnet(test_vector[idx].addr2, test_vector[idx].addr1,
646 test_vector[idx].net_idx2,
647 subnet_relay_cb_check_rev, &idx);
648 ticks += k_uptime_ticks() - tick1;
649 }
650 printk("ticks: %8u us: %u\n", ticks, k_ticks_to_us_floor32(ticks));
651 }
652
653 /* Test checks iteration logic and performance when run on real devices. */
ZTEST(bt_mesh_brg_cfg,test_zcheck_entry_randomly_sorting)654 ZTEST(bt_mesh_brg_cfg, test_zcheck_entry_randomly_sorting)
655 {
656 printk("num msgs: %d\n\n", NUM_MSGS);
657
658 /* Test performance when packets are flowing in one directions */
659 /* Fill bridging table in sorted order */
660 printk("\n\nPackets going only in one direction (from outside towards the subnet)\n");
661 printk("\nBridging table is pre-filled in sorted order\n");
662
663 check_bt_mesh_brg_cfg_tbl_reset();
664 check_fill_all_bt_entries();
665 print_brg_tbl();
666 test_bridging_performance(true);
667
668 /* Fill bridging table in reversed order */
669 printk("\nBridging table is pre-filled in reversed order\n");
670
671 check_bt_mesh_brg_cfg_tbl_reset();
672 check_fill_all_bt_entries_reversed();
673 print_brg_tbl();
674 test_bridging_performance(true);
675
676 /* Fill bridging table in random order */
677 printk("\nBridging table is pre-filled in random order\n");
678
679 check_bt_mesh_brg_cfg_tbl_reset();
680 check_fill_all_bt_entries_randomly();
681 print_brg_tbl();
682 test_bridging_performance(true);
683
684 /* Test performance when packets are flowing in both directions - use same dataset. */
685 printk("\n\nPackets going in both directions (same data set, flip src and dst pairs)\n");
686 printk("\nBridging table is pre-filled in sorted order\n");
687
688 check_bt_mesh_brg_cfg_tbl_reset();
689 check_fill_all_bt_entries();
690 print_brg_tbl();
691 test_bridging_performance(false);
692
693 /* Fill bridging table in reversed order */
694 printk("\nBridging table is pre-filled in reversed order\n");
695
696 check_bt_mesh_brg_cfg_tbl_reset();
697 check_fill_all_bt_entries_reversed();
698 print_brg_tbl();
699 test_bridging_performance(false);
700
701 /* Fill bridging table in random order */
702 printk("\nBridging table is pre-filled in random order\n");
703
704 check_bt_mesh_brg_cfg_tbl_reset();
705 check_fill_all_bt_entries_randomly();
706 print_brg_tbl();
707 test_bridging_performance(false);
708 }
709