1 /*
2 * Copyright (c) 2024 Nordic Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Subnet bridge test
7 */
8
9 #include "mesh_test.h"
10 #include <zephyr/bluetooth/mesh.h>
11 #include "mesh/net.h"
12 #include "mesh/keys.h"
13 #include "mesh/va.h"
14 #include "bsim_args_runner.h"
15 #include "common/bt_str.h"
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(test_brg, LOG_LEVEL_INF);
19
20 #define WAIT_TIME 32 /*seconds*/
21 #define WAIT_TIME_IVU_TEST 240 /* seconds */
22 #define BEACON_INTERVAL 10 /*seconds */
23
24 #define PROV_ADDR 0x0001
25 /* Bridge address must be less than DEVICE_ADDR_START */
26 #define BRIDGE_ADDR 0x0002
27 #define DEVICE_ADDR_START 0x0003
28 #define GROUP_ADDR 0xc000
29
30 #define REMOTE_NODES_MULTICAST 3
31
32 static const uint8_t prov_dev_key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
33 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
34
35 static const uint8_t subnet_keys[][16] = {
36 {0xaa, 0xbb, 0xcc},
37 {0xdd, 0xee, 0xff},
38 {0x11, 0x22, 0x33},
39 {0x12, 0x34, 0x56},
40 };
41
42 static uint8_t prov_uuid[16] = {0x6c, 0x69, 0x6e, 0x67, 0x61, 0xaa};
43 static uint8_t bridge_uuid[16] = {0x6c, 0x69, 0x6e, 0x67, 0x61, 0xbb};
44 static uint8_t dev_uuid[16] = {0x6c, 0x69, 0x6e, 0x67, 0x61, 0xcc};
45
46 static int test_ividx = 0x123456;
47
48 extern const struct bt_mesh_comp comp;
49 static bool tester_ready;
50
51 enum {
52 MSG_TYPE_DATA = 0,
53 MSG_TYPE_GET = 1,
54 MSG_TYPE_STATUS = 2,
55 };
56
57 static uint8_t recvd_msgs[10];
58 static uint8_t recvd_msgs_cnt;
59
60 const struct bt_mesh_va *va_entry;
61
62 /*
63 * The number of remote nodes participating in the test. Initialized to 2 because most tests use 2
64 * remote nodes.
65 */
66 static int remote_nodes = 2;
67
68 BUILD_ASSERT((2 /* opcode */ + 1 /* type */ + 1 /* msgs cnt */ + sizeof(recvd_msgs) +
69 BT_MESH_MIC_SHORT) <= BT_MESH_RX_SDU_MAX,
70 "Status message does not fit into the maximum incoming SDU size.");
71 BUILD_ASSERT((2 /* opcode */ + 1 /* type */ + 1 /* msgs cnt */ + sizeof(recvd_msgs) +
72 BT_MESH_MIC_SHORT) <= BT_MESH_TX_SDU_MAX,
73 "Status message does not fit into the maximum outgoing SDU size.");
74
75 static K_SEM_DEFINE(status_msg_recvd_sem, 0, 1);
76 static K_SEM_DEFINE(prov_sem, 0, 1);
77
test_tester_init(void)78 static void test_tester_init(void)
79 {
80 /* Stub */
81 }
82
test_bridge_init(void)83 static void test_bridge_init(void)
84 {
85 /* Bridge device must always be the second device. */
86 ASSERT_EQUAL(1, get_device_nbr());
87 }
88
test_device_init(void)89 static void test_device_init(void)
90 {
91 ASSERT_TRUE_MSG(get_device_nbr() >= 2, "Regular devices must be initialized after "
92 "tester and Bridge devices.");
93
94 /* Regular devices addresses starts from address 0x0003.*/
95 dev_uuid[6] = get_device_nbr() + 1;
96
97 /* Regular devices are provisioned into subnets starting with idx 1. */
98 dev_uuid[8] = get_device_nbr() - 1;
99 }
100
unprovisioned_beacon(uint8_t uuid[16],bt_mesh_prov_oob_info_t oob_info,uint32_t * uri_hash)101 static void unprovisioned_beacon(uint8_t uuid[16], bt_mesh_prov_oob_info_t oob_info,
102 uint32_t *uri_hash)
103 {
104 int err;
105
106 /* Subnet may not be ready yet when tester receives a beacon. */
107 if (!tester_ready) {
108 LOG_INF("tester is not ready yet");
109 return;
110 }
111
112 LOG_INF("Received unprovisioned beacon, uuid %s", bt_hex(uuid, 16));
113
114 if (!memcmp(uuid, bridge_uuid, 16)) {
115 err = bt_mesh_provision_adv(uuid, 0, BRIDGE_ADDR, 0);
116 if (!err) {
117 LOG_INF("Provisioning bridge at address 0x%04x", BRIDGE_ADDR);
118 }
119
120 return;
121 }
122
123 /* UUID[6] - address to be used for provisioning.
124 * UUID[8] - subnet to be used for provisioning.
125 */
126 uint16_t addr = uuid[6];
127 int subnet_idx = uuid[8];
128
129 err = bt_mesh_provision_adv(uuid, subnet_idx, addr, 0);
130 if (!err) {
131 LOG_INF("Provisioning device at address 0x%04x with NetKeyIdx 0x%04x", addr,
132 subnet_idx);
133 }
134 }
135
prov_node_added(uint16_t net_idx,uint8_t uuid[16],uint16_t addr,uint8_t num_elem)136 static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr, uint8_t num_elem)
137 {
138 LOG_INF("Device 0x%04x provisioned, NetKeyIdx 0x%04x", addr, net_idx);
139 k_sem_give(&prov_sem);
140 }
141
142 static struct bt_mesh_prov tester_prov = {.uuid = prov_uuid,
143 .unprovisioned_beacon = unprovisioned_beacon,
144 .node_added = prov_node_added};
145
prov_complete(uint16_t net_idx,uint16_t addr)146 static void prov_complete(uint16_t net_idx, uint16_t addr)
147 {
148 LOG_INF("Device 0x%04x provisioning is complete, NetKeyIdx 0x%04x", addr, net_idx);
149 k_sem_give(&prov_sem);
150 }
151
152 static struct bt_mesh_prov device_prov = {
153 .uuid = dev_uuid,
154 .complete = prov_complete,
155 };
156
157 static struct bt_mesh_prov bridge_prov = {
158 .uuid = bridge_uuid,
159 .complete = prov_complete,
160 };
161
tester_setup(void)162 static void tester_setup(void)
163 {
164 uint8_t status;
165 int err;
166
167 ASSERT_OK(bt_mesh_cdb_create(test_net_key));
168 ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, test_ividx, PROV_ADDR, prov_dev_key));
169
170 err = bt_mesh_cfg_cli_app_key_add(0, PROV_ADDR, 0, 0, test_app_key, &status);
171 if (err || status) {
172 FAIL("AppKey add failed (err %d, status %u)", err, status);
173 return;
174 }
175
176 err = bt_mesh_cfg_cli_mod_app_bind(0, PROV_ADDR, PROV_ADDR, 0, TEST_MOD_ID, &status);
177 if (err || status) {
178 FAIL("Mod app bind failed (err %d, status %u)", err, status);
179 return;
180 }
181
182 for (int i = 0; i < remote_nodes; i++) {
183 LOG_INF("Creating subnet idx %d", i);
184
185 ASSERT_OK(
186 bt_mesh_cfg_cli_net_key_add(0, PROV_ADDR, i + 1, subnet_keys[i], &status));
187 if (status) {
188 FAIL("NetKey add failed (status %u)", status);
189 return;
190 }
191
192 struct bt_mesh_cdb_subnet *subnet = bt_mesh_cdb_subnet_alloc(i + 1);
193
194 ASSERT_TRUE(subnet != NULL);
195
196 ASSERT_OK(bt_mesh_cdb_subnet_key_import(subnet, 0, subnet_keys[i]));
197
198 bt_mesh_cdb_subnet_store(subnet);
199 }
200
201 uint8_t transmit;
202
203 ASSERT_OK(bt_mesh_cfg_cli_relay_set(0, PROV_ADDR, BT_MESH_RELAY_DISABLED,
204 BT_MESH_TRANSMIT(2, 20), &status, &transmit));
205 if (status) {
206 FAIL("Relay set failed (status %u)", status);
207 return;
208 }
209
210 tester_ready = true;
211 }
212
bridge_entry_add(uint16_t src,uint16_t dst,uint16_t net_idx1,uint16_t net_idx2,uint8_t dir)213 static void bridge_entry_add(uint16_t src, uint16_t dst, uint16_t net_idx1, uint16_t net_idx2,
214 uint8_t dir)
215 {
216 struct bt_mesh_brg_cfg_table_entry entry;
217 struct bt_mesh_brg_cfg_table_status rsp;
218 int err;
219
220 entry.directions = dir;
221 entry.net_idx1 = net_idx1;
222 entry.net_idx2 = net_idx2;
223 entry.addr1 = src;
224 entry.addr2 = dst;
225
226 err = bt_mesh_brg_cfg_cli_table_add(0, BRIDGE_ADDR, &entry, &rsp);
227 if (err || rsp.status || rsp.entry.directions != dir || rsp.entry.net_idx1 != net_idx1 ||
228 rsp.entry.net_idx2 != net_idx2 || rsp.entry.addr1 != src || rsp.entry.addr2 != dst) {
229 FAIL("Bridging table add failed (err %d) (status %u)", err, rsp.status);
230 return;
231 }
232 }
233
bridge_entry_remove(uint16_t src,uint16_t dst,uint16_t net_idx1,uint16_t net_idx2)234 static void bridge_entry_remove(uint16_t src, uint16_t dst, uint16_t net_idx1, uint16_t net_idx2)
235 {
236 struct bt_mesh_brg_cfg_table_status rsp;
237
238 ASSERT_OK(bt_mesh_brg_cfg_cli_table_remove(0, BRIDGE_ADDR, net_idx1, net_idx2, src, dst,
239 &rsp));
240 if (rsp.status) {
241 FAIL("Bridging table remove failed (status %u)", rsp.status);
242 return;
243 }
244 }
245
tester_bridge_configure(void)246 static void tester_bridge_configure(void)
247 {
248 uint8_t status;
249 int err;
250
251 LOG_INF("Configuring bridge...");
252
253 for (int i = 0; i < remote_nodes; i++) {
254 err = bt_mesh_cfg_cli_net_key_add(0, BRIDGE_ADDR, i + 1, subnet_keys[i], &status);
255 if (err || status) {
256 FAIL("NetKey add failed (err %d, status %u)", err, status);
257 return;
258 }
259 }
260
261 ASSERT_OK(bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_ENABLED, &status));
262 if (status != BT_MESH_BRG_CFG_ENABLED) {
263 FAIL("Subnet bridge set failed (status %u)", status);
264 return;
265 }
266
267 /* Disable Relay feature to avoid interference in the test. */
268 uint8_t transmit;
269
270 ASSERT_OK(bt_mesh_cfg_cli_relay_set(0, BRIDGE_ADDR, BT_MESH_RELAY_DISABLED,
271 BT_MESH_TRANSMIT(2, 20), &status, &transmit));
272 if (status) {
273 FAIL("Relay set failed (status %u)", status);
274 return;
275 }
276
277 LOG_INF("Bridge configured");
278 }
279
tester_device_configure(uint16_t net_key_idx,uint16_t addr)280 static void tester_device_configure(uint16_t net_key_idx, uint16_t addr)
281 {
282 int err;
283 uint8_t status;
284
285 err = bt_mesh_cfg_cli_app_key_add(net_key_idx, addr, net_key_idx, 0, test_app_key, &status);
286 if (err || status) {
287 FAIL("AppKey add failed (err %d, status %u)", err, status);
288 return;
289 }
290
291 err = bt_mesh_cfg_cli_mod_app_bind(net_key_idx, addr, addr, 0, TEST_MOD_ID, &status);
292 if (err || status) {
293 FAIL("Mod app bind failed (err %d, status %u)", err, status);
294 return;
295 }
296
297 /* Disable SNB on devices to let Subnet Bridge propagate new IV index value. */
298 err = bt_mesh_cfg_cli_beacon_set(net_key_idx, addr, BT_MESH_BEACON_DISABLED, &status);
299 if (err || status) {
300 FAIL("Beacon set failed (err %d, status %u)", err, status);
301 return;
302 }
303
304 LOG_INF("Device 0x%04x configured", addr);
305 }
306
tester_data_cb(uint8_t * data,size_t length)307 static void tester_data_cb(uint8_t *data, size_t length)
308 {
309 uint8_t type = data[0];
310
311 LOG_HEXDUMP_DBG(data, length, "tester received message");
312
313 ASSERT_TRUE_MSG(length > 1, "Too short message");
314 ASSERT_EQUAL(type, MSG_TYPE_STATUS);
315
316 recvd_msgs_cnt = data[1];
317 ASSERT_EQUAL(recvd_msgs_cnt * sizeof(recvd_msgs[0]), length - 2);
318 memcpy(recvd_msgs, &data[2], recvd_msgs_cnt * sizeof(recvd_msgs[0]));
319
320 k_sem_give(&status_msg_recvd_sem);
321 }
322
send_data(uint16_t dst,uint8_t payload,const uint8_t * uuid)323 static int send_data(uint16_t dst, uint8_t payload, const uint8_t *uuid)
324 {
325 uint8_t data[2] = {MSG_TYPE_DATA, payload};
326
327 return bt_mesh_test_send_data(dst, uuid, data, sizeof(data), NULL, NULL);
328 }
329
send_get(uint16_t dst,const uint8_t * uuid)330 static int send_get(uint16_t dst, const uint8_t *uuid)
331 {
332 uint8_t data[1] = {MSG_TYPE_GET};
333
334 return bt_mesh_test_send_data(dst, uuid, data, sizeof(data), NULL, NULL);
335 }
336
337 struct bridged_addresses_entry {
338 uint16_t addr1;
339 uint16_t addr2;
340 uint8_t dir;
341 };
342
bridge_table_verify(uint16_t net_idx1,uint16_t net_idx2,uint16_t start_idx,struct bridged_addresses_entry * list,size_t list_len)343 static void bridge_table_verify(uint16_t net_idx1, uint16_t net_idx2, uint16_t start_idx,
344 struct bridged_addresses_entry *list, size_t list_len)
345 {
346 struct bt_mesh_brg_cfg_table_list rsp = {
347 .list = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX),
348 };
349
350 net_buf_simple_init(rsp.list, 0);
351
352 ASSERT_OK(
353 bt_mesh_brg_cfg_cli_table_get(0, BRIDGE_ADDR, net_idx1, net_idx2, start_idx, &rsp));
354 ASSERT_EQUAL(rsp.status, 0);
355 ASSERT_EQUAL(rsp.net_idx1, net_idx1);
356 ASSERT_EQUAL(rsp.net_idx2, net_idx2);
357 ASSERT_EQUAL(rsp.start_idx, start_idx);
358
359 LOG_HEXDUMP_DBG(rsp.list->data, rsp.list->len, "Received table");
360
361 ASSERT_EQUAL(rsp.list->len / 5, list_len);
362 ASSERT_EQUAL(rsp.list->len % 5, 0);
363
364 for (int i = 0; i < list_len; i++) {
365 struct bridged_addresses_entry entry;
366
367 entry.addr1 = net_buf_simple_pull_le16(rsp.list);
368 entry.addr2 = net_buf_simple_pull_le16(rsp.list);
369 entry.dir = net_buf_simple_pull_u8(rsp.list);
370
371 ASSERT_EQUAL(entry.addr1, list[i].addr1);
372 ASSERT_EQUAL(entry.addr2, list[i].addr2);
373 ASSERT_EQUAL(entry.dir, list[i].dir);
374 }
375 }
376
device_data_cb(uint8_t * data,size_t length)377 static void device_data_cb(uint8_t *data, size_t length)
378 {
379 uint8_t type = data[0];
380
381 /* For group/va tests: There is no bridge entry for the subnet that the final device
382 * belongs to. If it receives a message from the tester, fail.
383 */
384 ASSERT_TRUE_MSG(get_device_nbr() != REMOTE_NODES_MULTICAST + 1,
385 "Unbridged device received message");
386
387 LOG_HEXDUMP_DBG(data, length, "Device received message");
388
389 switch (type) {
390 case MSG_TYPE_DATA:
391 ASSERT_EQUAL(2, length);
392 ASSERT_TRUE_MSG(recvd_msgs_cnt < ARRAY_SIZE(recvd_msgs), "Too many messages");
393
394 recvd_msgs[recvd_msgs_cnt] = data[1];
395 recvd_msgs_cnt++;
396
397 break;
398
399 case MSG_TYPE_GET: {
400 uint8_t test_data[1 /*type */ + 1 /* msgs cnt */ + sizeof(recvd_msgs)] = {
401 MSG_TYPE_STATUS, recvd_msgs_cnt};
402
403 memcpy(&test_data[2], recvd_msgs, recvd_msgs_cnt * sizeof(recvd_msgs[0]));
404
405 ASSERT_OK(bt_mesh_test_send_data(PROV_ADDR, NULL, test_data,
406 2 + recvd_msgs_cnt * sizeof(recvd_msgs[0]), NULL,
407 NULL));
408
409 memset(recvd_msgs, 0, sizeof(recvd_msgs));
410 recvd_msgs_cnt = 0;
411
412 break;
413 }
414
415 case MSG_TYPE_STATUS:
416 ASSERT_TRUE_MSG(false, "Unexpected message");
417 break;
418 }
419 }
420
421 /**
422 * This is a workaround that removes secondary subnets from the tester to avoid message cache
423 * hit when the devices send STATUS message encrypted with the subnet key known by the tester,
424 * but with different app key pair (app key is the same, but net key <-> app key pair is different).
425 */
tester_workaround(void)426 static void tester_workaround(void)
427 {
428 uint8_t status;
429 int err;
430
431 LOG_INF("Applying subnet's workaround for tester...");
432
433 for (int i = 0; i < remote_nodes; i++) {
434 err = bt_mesh_cfg_cli_net_key_del(0, PROV_ADDR, i + 1, &status);
435 if (err || status) {
436 FAIL("NetKey del failed (err %d, status %u)", err, status);
437 return;
438 }
439 }
440 }
441
tester_init_common(void)442 static void tester_init_common(void)
443 {
444 bt_mesh_device_setup(&tester_prov, &comp);
445 tester_setup();
446
447 for (int i = 0; i < 1 /* bridge */ + remote_nodes; i++) {
448 LOG_INF("Waiting for a device to provision...");
449 ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));
450 }
451
452 tester_bridge_configure();
453
454 for (int i = 0; i < remote_nodes; i++) {
455 tester_device_configure(i + 1, DEVICE_ADDR_START + i);
456 }
457
458 bt_mesh_test_data_cb_setup(tester_data_cb);
459 }
460
setup_basic_bridge(void)461 static void setup_basic_bridge(void)
462 {
463 /* Adding devices to bridge table */
464 for (int i = 0; i < remote_nodes; i++) {
465 bridge_entry_add(PROV_ADDR, DEVICE_ADDR_START + i, 0, i + 1,
466 BT_MESH_BRG_CFG_DIR_TWOWAY);
467 }
468 }
469
send_and_receive(void)470 static void send_and_receive(void)
471 {
472 const int msgs_cnt = 3;
473
474 LOG_INF("Sending data...");
475
476 for (int i = 0; i < remote_nodes; i++) {
477 uint8_t payload = i | i << 4;
478
479 for (int j = 0; j < msgs_cnt; j++) {
480 ASSERT_OK(send_data(DEVICE_ADDR_START + i, payload + j, NULL));
481 }
482 }
483
484 LOG_INF("Checking data...");
485
486 for (int i = 0; i < remote_nodes; i++) {
487 uint8_t payload = i | i << 4;
488
489 ASSERT_OK(send_get(DEVICE_ADDR_START + i, NULL));
490 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
491
492 ASSERT_EQUAL(recvd_msgs_cnt, msgs_cnt);
493 for (int j = 0; j < recvd_msgs_cnt; j++) {
494 ASSERT_EQUAL(recvd_msgs[j], payload + j);
495 }
496 }
497 }
498
test_tester_simple(void)499 static void test_tester_simple(void)
500 {
501 uint8_t status;
502 int err;
503
504 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
505 tester_init_common();
506 setup_basic_bridge();
507 tester_workaround();
508
509 LOG_INF("Step 1: Checking bridging table...");
510
511 send_and_receive();
512
513 LOG_INF("Step 2: Disabling bridging...");
514
515 err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_DISABLED, &status);
516 if (err || status != BT_MESH_BRG_CFG_DISABLED) {
517 FAIL("Subnet bridge set failed (err %d) (status %u)", err, status);
518 return;
519 }
520
521 LOG_INF("Sending data...");
522 for (int i = 0; i < remote_nodes; i++) {
523 uint8_t payload = i | i << 4;
524
525 for (int j = 0; j < 3; j++) {
526 ASSERT_OK(send_data(DEVICE_ADDR_START + i, payload + j, NULL));
527 }
528 }
529
530 LOG_INF("Step3: Enabling bridging...");
531 err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_ENABLED, &status);
532 if (err || status != BT_MESH_BRG_CFG_ENABLED) {
533 FAIL("Subnet bridge set failed (err %d) (status %u)", err, status);
534 return;
535 }
536
537 LOG_INF("Checking data...");
538 for (int i = 0; i < remote_nodes; i++) {
539 ASSERT_OK(send_get(DEVICE_ADDR_START + i, NULL));
540 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
541
542 ASSERT_EQUAL(recvd_msgs_cnt, 0);
543 }
544
545 PASS();
546 }
547
tester_simple_multicast(uint16_t addr,const uint8_t * uuid)548 static void tester_simple_multicast(uint16_t addr, const uint8_t *uuid)
549 {
550 uint8_t status;
551 int err;
552 const int msgs_cnt = 3;
553
554 /* Adding devices to bridge table */
555 for (int i = 0; i < remote_nodes; i++) {
556 /* Bridge messages from tester to multicast addr, for each subnet expect the last */
557 if (i != remote_nodes - 1) {
558 bridge_entry_add(PROV_ADDR, addr, 0, i + 1, BT_MESH_BRG_CFG_DIR_ONEWAY);
559 }
560
561 /* Bridge messages from remote nodes to tester */
562 bridge_entry_add(DEVICE_ADDR_START + i, PROV_ADDR, i + 1, 0,
563 BT_MESH_BRG_CFG_DIR_ONEWAY);
564 }
565
566 tester_workaround();
567
568 bt_mesh_test_data_cb_setup(tester_data_cb);
569
570 LOG_INF("Step 1: Checking bridging table...");
571
572 LOG_INF("Sending data...");
573
574 for (int i = 0; i < msgs_cnt; i++) {
575 ASSERT_OK(send_data(addr, i, uuid));
576 }
577
578 LOG_INF("Checking data...");
579
580 ASSERT_OK(send_get(addr, uuid));
581 for (int i = 0; i < remote_nodes - 1; i++) {
582 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
583
584 ASSERT_EQUAL(recvd_msgs_cnt, msgs_cnt);
585 for (int j = 0; j < recvd_msgs_cnt; j++) {
586 ASSERT_EQUAL(recvd_msgs[j], j);
587 }
588 }
589
590 LOG_INF("Step 2: Disabling bridging...");
591
592 err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_DISABLED, &status);
593 if (err || status != BT_MESH_BRG_CFG_DISABLED) {
594 FAIL("Subnet bridge set failed (err %d) (status %u)", err, status);
595 return;
596 }
597
598 LOG_INF("Sending data...");
599 for (int i = 0; i < msgs_cnt; i++) {
600 ASSERT_OK(send_data(addr, i, uuid));
601 }
602
603 LOG_INF("Step 3: Enabling bridging...");
604 err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_ENABLED, &status);
605 if (err || status != BT_MESH_BRG_CFG_ENABLED) {
606 FAIL("Subnet bridge set failed (err %d) (status %u)", err, status);
607 return;
608 }
609
610 LOG_INF("Checking data...");
611 ASSERT_OK(send_get(addr, uuid));
612 for (int i = 0; i < remote_nodes - 1; i++) {
613 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
614 ASSERT_EQUAL(recvd_msgs_cnt, 0);
615 }
616 }
617
test_tester_simple_group(void)618 static void test_tester_simple_group(void)
619 {
620 int err;
621 uint8_t status;
622
623 remote_nodes = REMOTE_NODES_MULTICAST;
624 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
625 tester_init_common();
626
627 for (int i = 0; i < remote_nodes; i++) {
628 err = bt_mesh_cfg_cli_mod_sub_add(i + 1, DEVICE_ADDR_START + i,
629 DEVICE_ADDR_START + i, GROUP_ADDR, TEST_MOD_ID,
630 &status);
631 if (err || status) {
632 FAIL("Mod sub add failed (err %d, status %u)", err, status);
633 return;
634 }
635 }
636
637 tester_simple_multicast(GROUP_ADDR, NULL);
638 PASS();
639 }
640
test_tester_simple_va(void)641 static void test_tester_simple_va(void)
642 {
643 int err;
644 uint8_t status;
645 uint16_t vaddr;
646
647 remote_nodes = REMOTE_NODES_MULTICAST;
648 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
649
650 ASSERT_OK(bt_mesh_va_add(test_va_uuid, &va_entry));
651 ASSERT_TRUE(va_entry != NULL);
652
653 tester_init_common();
654
655 for (int i = 0; i < remote_nodes; i++) {
656 err = bt_mesh_cfg_cli_mod_sub_va_add(i + 1, DEVICE_ADDR_START + i,
657 DEVICE_ADDR_START + i, test_va_uuid,
658 TEST_MOD_ID, &vaddr, &status);
659 if (err || status) {
660 FAIL("Mod sub VA add failed (err %d, status %u)", err, status);
661 return;
662 }
663 ASSERT_EQUAL(vaddr, va_entry->addr);
664 }
665
666 tester_simple_multicast(va_entry->addr, va_entry->uuid);
667 PASS();
668 }
669
test_tester_table_state_change(void)670 static void test_tester_table_state_change(void)
671 {
672 int err;
673
674 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
675 tester_init_common();
676 tester_workaround();
677
678 /* Bridge Table is empty, will not get any message back. */
679 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
680 err = k_sem_take(&status_msg_recvd_sem, K_SECONDS(5));
681 ASSERT_EQUAL(err, -EAGAIN);
682
683 /* DATA and GET messages should reach Device 1, but STATUS message won't be received. */
684 bridge_entry_add(PROV_ADDR, DEVICE_ADDR_START, 0, 1, BT_MESH_BRG_CFG_DIR_ONEWAY);
685
686 ASSERT_OK(send_data(DEVICE_ADDR_START, 0xAA, NULL));
687
688 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
689 err = k_sem_take(&status_msg_recvd_sem, K_SECONDS(5));
690 ASSERT_EQUAL(err, -EAGAIN);
691
692 /* Sending DATA message again before adding a new entry as the previous GET message resets
693 * received messages counter on Devices
694 */
695 ASSERT_OK(send_data(DEVICE_ADDR_START, 0xAA, NULL));
696 /* Adding a reverse entry. This should be added to the bridge table as a separate entry as
697 * the addresses and net keys indexs are provided in the opposite order.
698 */
699 bridge_entry_add(DEVICE_ADDR_START, PROV_ADDR, 1, 0, BT_MESH_BRG_CFG_DIR_ONEWAY);
700 bridge_table_verify(0, 1, 0,
701 (struct bridged_addresses_entry[]){
702 {PROV_ADDR, DEVICE_ADDR_START, BT_MESH_BRG_CFG_DIR_ONEWAY},
703 },
704 1);
705 bridge_table_verify(1, 0, 0,
706 (struct bridged_addresses_entry[]){
707 {DEVICE_ADDR_START, PROV_ADDR, BT_MESH_BRG_CFG_DIR_ONEWAY},
708 },
709 1);
710
711 k_sleep(K_SECONDS(1));
712
713 /* Now we should receive STATUS message. */
714 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
715 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
716
717 ASSERT_EQUAL(recvd_msgs_cnt, 1);
718 ASSERT_EQUAL(recvd_msgs[0], 0xAA);
719
720 /* Removing the reverse entry and changing direction on the first entry.
721 * tester should still receive STATUS message.
722 */
723 bridge_entry_remove(DEVICE_ADDR_START, PROV_ADDR, 1, 0);
724 bridge_entry_add(PROV_ADDR, DEVICE_ADDR_START, 0, 1, BT_MESH_BRG_CFG_DIR_TWOWAY);
725 bridge_table_verify(0, 1, 0,
726 (struct bridged_addresses_entry[]){
727 {PROV_ADDR, DEVICE_ADDR_START, BT_MESH_BRG_CFG_DIR_TWOWAY},
728 },
729 1);
730 bridge_table_verify(1, 0, 0, NULL, 0);
731
732 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
733 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
734 ASSERT_EQUAL(recvd_msgs_cnt, 0);
735
736 PASS();
737 }
738
net_key_remove(uint16_t dst,uint16_t net_idx,uint16_t net_idx_to_remove)739 static void net_key_remove(uint16_t dst, uint16_t net_idx, uint16_t net_idx_to_remove)
740 {
741 uint8_t status;
742 int err;
743
744 err = bt_mesh_cfg_cli_net_key_del(net_idx, dst, net_idx_to_remove, &status);
745 if (err || status) {
746 FAIL("NetKey del failed (err %d, status %u)", err, status);
747 return;
748 }
749 }
750
test_tester_net_key_remove(void)751 static void test_tester_net_key_remove(void)
752 {
753 int err;
754
755 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
756 tester_init_common();
757 setup_basic_bridge();
758 tester_workaround();
759
760 ASSERT_OK(send_data(DEVICE_ADDR_START, 0xAA, NULL));
761 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
762 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
763 ASSERT_EQUAL(recvd_msgs_cnt, 1);
764 ASSERT_EQUAL(recvd_msgs[0], 0xAA);
765
766 /* Removing subnet 1 from Subnet Bridge. */
767 net_key_remove(BRIDGE_ADDR, 0, 1);
768
769 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
770 err = k_sem_take(&status_msg_recvd_sem, K_SECONDS(5));
771 ASSERT_EQUAL(err, -EAGAIN);
772
773 bridge_table_verify(0, 2, 0,
774 (struct bridged_addresses_entry[]){
775 {PROV_ADDR, DEVICE_ADDR_START + 1, BT_MESH_BRG_CFG_DIR_TWOWAY},
776 },
777 1);
778
779 /* Bridging Table Get message will return Invalid NetKey Index error because Subnet 1 is
780 * removed.
781 */
782 struct bt_mesh_brg_cfg_table_list rsp = {
783 .list = NULL,
784 };
785
786 ASSERT_OK(bt_mesh_brg_cfg_cli_table_get(0, BRIDGE_ADDR, 0, 1, 0, &rsp));
787 ASSERT_EQUAL(rsp.status, 4);
788
789 PASS();
790 }
791
792 #if CONFIG_BT_SETTINGS
test_tester_persistence(void)793 static void test_tester_persistence(void)
794 {
795 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
796
797 bt_mesh_device_setup(&tester_prov, &comp);
798
799 if (bt_mesh_is_provisioned()) {
800 uint8_t status;
801
802 LOG_INF("Already provisioned, skipping provisioning");
803
804 ASSERT_OK(bt_mesh_brg_cfg_cli_get(0, BRIDGE_ADDR, &status));
805 if (status != BT_MESH_BRG_CFG_ENABLED) {
806 FAIL("Subnet bridge set failed (status %u)", status);
807 return;
808 }
809
810 bridge_table_verify(
811 0, 1, 0,
812 (struct bridged_addresses_entry[]){
813 {PROV_ADDR, DEVICE_ADDR_START, BT_MESH_BRG_CFG_DIR_TWOWAY},
814 },
815 1);
816
817 bridge_table_verify(
818 0, 2, 0,
819 (struct bridged_addresses_entry[]){
820 {PROV_ADDR, DEVICE_ADDR_START + 1, BT_MESH_BRG_CFG_DIR_TWOWAY},
821 },
822 1);
823
824 bridge_table_verify(
825 1, 0, 0,
826 (struct bridged_addresses_entry[]){
827 {DEVICE_ADDR_START, PROV_ADDR, BT_MESH_BRG_CFG_DIR_ONEWAY},
828 },
829 1);
830
831 bridge_table_verify(
832 2, 0, 0,
833 (struct bridged_addresses_entry[]){
834 {DEVICE_ADDR_START + 1, PROV_ADDR, BT_MESH_BRG_CFG_DIR_ONEWAY},
835 },
836 1);
837 } else {
838 tester_setup();
839
840 LOG_INF("Waiting for a bridge to provision...");
841 ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));
842
843 LOG_INF("Configuring bridge...");
844 tester_bridge_configure();
845
846 /* Adding devices to bridge table */
847 for (int i = 0; i < remote_nodes; i++) {
848 bridge_entry_add(PROV_ADDR, DEVICE_ADDR_START + i, 0, i + 1,
849 BT_MESH_BRG_CFG_DIR_TWOWAY);
850 bridge_entry_add(DEVICE_ADDR_START + i, PROV_ADDR, i + 1, 0,
851 BT_MESH_BRG_CFG_DIR_ONEWAY);
852 }
853
854 k_sleep(K_SECONDS(CONFIG_BT_MESH_STORE_TIMEOUT));
855 }
856
857 PASS();
858 }
859 #endif
860
861 /* When testing IV Index update, after the IV Index incremented devices starts sending messages
862 * with SEQ number 0 that is lower than the SEQ number of the last message received before IV Index.
863 * The Network Message Cache is not cleared and thus will drop these messages.
864 *
865 * The workaround is to send GET message to each device to bump SEQ number and overflow the cache so
866 * that after IV Index update there is no message with SEQ 0 in the cache.
867 */
msg_cache_workaround(void)868 static void msg_cache_workaround(void)
869 {
870 LOG_INF("Applying Msg Cache workaround...");
871
872 for (int i = 0; i < remote_nodes; i++) {
873 for (int j = 0; j < CONFIG_BT_MESH_MSG_CACHE_SIZE; j++) {
874 ASSERT_OK(send_get(DEVICE_ADDR_START + i, NULL));
875 /* k_sem_take is needed to not overflow network buffer pool. The result
876 * of the semaphor is not important as we just need to bump sequence number
877 * enough to bypass message cache.
878 */
879 (void)k_sem_take(&status_msg_recvd_sem, K_SECONDS(1));
880 }
881 }
882
883 LOG_INF("Msg Cache workaround applied");
884 k_sleep(K_SECONDS(10));
885 }
886
beacon_set(uint16_t dst,uint8_t val)887 static int beacon_set(uint16_t dst, uint8_t val)
888 {
889 uint8_t status;
890 int err;
891
892 err = bt_mesh_cfg_cli_beacon_set(0, dst, val, &status);
893 if (err || status != val) {
894 FAIL("Beacon set failed (err %d, status %u)", err, status);
895 return -EINVAL;
896 }
897
898 return 0;
899 }
900
901 /* This function guarantees that IV Update procedure state is propagated to all nodes by togging off
902 * Beacon features on Subnet Bridge and Tester nodes. When Beacon feature is disabled on Subnet
903 * Bridge, Tester will be able to send beacon with new IVI flag and vice versa.
904 *
905 * Beacon feature is disabled on other nodes at the setup.
906 */
propagate_ivi_update_state(void)907 static void propagate_ivi_update_state(void)
908 {
909 /* Disable Beacon feature on subnet bridge to let tester send beacon first. */
910 ASSERT_OK(beacon_set(BRIDGE_ADDR, BT_MESH_BEACON_DISABLED));
911
912 LOG_INF("Waiting for IV Update state to propagate to Subnet Bridge");
913 k_sleep(K_SECONDS(BEACON_INTERVAL * 2));
914
915 /* Disable Beacon feature on tester and enable it on subnet bridge to let it send beacon. */
916 ASSERT_OK(beacon_set(PROV_ADDR, BT_MESH_BEACON_DISABLED));
917 ASSERT_OK(beacon_set(BRIDGE_ADDR, BT_MESH_BEACON_ENABLED));
918
919 LOG_INF("Waiting for IV Update state to propagate to other nodes");
920 k_sleep(K_SECONDS(BEACON_INTERVAL * 2));
921
922 /* Restore Beacon feature on tester. */
923 ASSERT_OK(beacon_set(PROV_ADDR, BT_MESH_BEACON_ENABLED));
924 }
925
test_tester_ivu(void)926 static void test_tester_ivu(void)
927 {
928 bt_mesh_test_cfg_set(NULL, WAIT_TIME_IVU_TEST);
929 bt_mesh_iv_update_test(true);
930 tester_init_common();
931 setup_basic_bridge();
932 tester_workaround();
933
934 ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
935 ASSERT_TRUE(bt_mesh.iv_index == test_ividx);
936
937 LOG_INF("IV Update procedure state: Normal");
938
939 k_sleep(K_SECONDS(BEACON_INTERVAL));
940
941 send_and_receive();
942
943 for (int i = 0; i < 2; i++) {
944 uint32_t iv_index = bt_mesh.iv_index;
945
946 LOG_INF("Round: %d", i);
947
948 msg_cache_workaround();
949
950 LOG_INF("Starting IV Update procedure, IVI %d -> %d", bt_mesh.iv_index,
951 bt_mesh.iv_index + 1);
952
953 iv_index = bt_mesh.iv_index;
954
955 ASSERT_TRUE(bt_mesh_iv_update());
956 ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
957 ASSERT_TRUE(bt_mesh.iv_index == iv_index + 1);
958
959 send_and_receive();
960
961 propagate_ivi_update_state();
962
963 LOG_INF("Finishing IV Update procedure");
964
965 ASSERT_TRUE(!bt_mesh_iv_update());
966 ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
967 ASSERT_TRUE(bt_mesh.iv_index == iv_index + 1);
968
969 propagate_ivi_update_state();
970
971 /* Sleep here to avoid packet collision. */
972 k_sleep(K_MSEC(300));
973
974 send_and_receive();
975 }
976
977 PASS();
978 }
979
start_krp(uint16_t addr,const uint8_t * key)980 static void start_krp(uint16_t addr, const uint8_t *key)
981 {
982 uint8_t status;
983 uint16_t net_idx = (addr == PROV_ADDR) ? 0 : (addr - DEVICE_ADDR_START + 1);
984
985 ASSERT_OK(bt_mesh_cfg_cli_net_key_update(0, BRIDGE_ADDR, net_idx, key, &status));
986 if (status) {
987 FAIL("Could not update net key (status %u)", status);
988 return;
989 }
990
991 ASSERT_OK(bt_mesh_cfg_cli_net_key_update(0, addr, net_idx, key, &status));
992 if (status) {
993 FAIL("Could not update net key (status %u)", status);
994 return;
995 }
996 }
997
set_krp_phase(uint16_t addr,uint8_t transition)998 static void set_krp_phase(uint16_t addr, uint8_t transition)
999 {
1000 uint8_t status;
1001 uint8_t phase;
1002 uint16_t net_idx = (addr == PROV_ADDR) ? 0 : (addr - DEVICE_ADDR_START + 1);
1003
1004 ASSERT_OK(bt_mesh_cfg_cli_krp_set(0, BRIDGE_ADDR, net_idx, transition, &status, &phase));
1005 if (status || (phase != (transition == 0x02 ? 0x02 : 0x00))) {
1006 FAIL("Could not update KRP (status %u, transition %u, phase %u)", status,
1007 transition, phase);
1008 return;
1009 }
1010
1011 ASSERT_OK(bt_mesh_cfg_cli_krp_set(0, addr, net_idx, transition, &status, &phase));
1012 if (status || (phase != (transition == 0x02 ? 0x02 : 0x00))) {
1013 FAIL("Could not update KRP (status %u, transition %u, phase %u)", status,
1014 transition, phase);
1015 return;
1016 }
1017 }
1018
test_tester_key_refresh(void)1019 static void test_tester_key_refresh(void)
1020 {
1021 const uint8_t new_net_keys[][16] = {
1022 {0x12, 0x34, 0x56},
1023 {0x78, 0x9a, 0xbc},
1024 {0xde, 0xf0, 0x12},
1025 {0x34, 0x56, 0x78}
1026 };
1027
1028 remote_nodes = 1;
1029 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
1030
1031 tester_init_common();
1032 setup_basic_bridge();
1033 tester_workaround();
1034
1035 LOG_INF("Step 1: Run KRP for tester net and check messaging");
1036 start_krp(PROV_ADDR, new_net_keys[0]);
1037 send_and_receive();
1038 set_krp_phase(PROV_ADDR, 0x02);
1039 send_and_receive();
1040 set_krp_phase(PROV_ADDR, 0x03);
1041 send_and_receive();
1042
1043 LOG_INF("Step 2: Run KRP for device net and check messaging");
1044 start_krp(DEVICE_ADDR_START, new_net_keys[1]);
1045 send_and_receive();
1046 set_krp_phase(DEVICE_ADDR_START, 0x02);
1047 send_and_receive();
1048 set_krp_phase(DEVICE_ADDR_START, 0x03);
1049 send_and_receive();
1050
1051 LOG_INF("Step 3: Run KRP in parallell for both device and tester");
1052 start_krp(PROV_ADDR, new_net_keys[2]);
1053 send_and_receive();
1054 start_krp(DEVICE_ADDR_START, new_net_keys[3]);
1055 send_and_receive();
1056 set_krp_phase(PROV_ADDR, 0x02);
1057 send_and_receive();
1058 set_krp_phase(DEVICE_ADDR_START, 0x02);
1059 send_and_receive();
1060 set_krp_phase(PROV_ADDR, 0x03);
1061 send_and_receive();
1062 set_krp_phase(DEVICE_ADDR_START, 0x03);
1063 send_and_receive();
1064
1065 PASS();
1066 }
1067
bridge_setup(void)1068 static void bridge_setup(void)
1069 {
1070 bt_mesh_device_setup(&bridge_prov, &comp);
1071
1072 if (IS_ENABLED(CONFIG_BT_SETTINGS) && bt_mesh_is_provisioned()) {
1073 LOG_INF("Already provisioned, skipping provisioning");
1074 } else {
1075 ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV));
1076 LOG_INF("Waiting for being provisioned...");
1077 ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));
1078 LOG_INF("Bridge is provisioned");
1079 }
1080 }
1081
test_bridge_simple(void)1082 static void test_bridge_simple(void)
1083 {
1084 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
1085
1086 bridge_setup();
1087
1088 PASS();
1089 }
1090
test_bridge_simple_iv_test_mode(void)1091 static void test_bridge_simple_iv_test_mode(void)
1092 {
1093 bt_mesh_test_cfg_set(NULL, WAIT_TIME_IVU_TEST);
1094 bt_mesh_iv_update_test(true);
1095
1096 bridge_setup();
1097
1098 PASS();
1099 }
1100
device_setup(void)1101 static void device_setup(void)
1102 {
1103 bt_mesh_device_setup(&device_prov, &comp);
1104
1105 ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV));
1106
1107 LOG_INF("Waiting for being provisioned...");
1108 ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));
1109 LOG_INF("Node is provisioned");
1110
1111 bt_mesh_test_data_cb_setup(device_data_cb);
1112 }
1113
test_device_simple(void)1114 static void test_device_simple(void)
1115 {
1116 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
1117
1118 device_setup();
1119
1120 PASS();
1121 }
1122
test_device_simple_iv_test_mode(void)1123 static void test_device_simple_iv_test_mode(void)
1124 {
1125 bt_mesh_test_cfg_set(NULL, WAIT_TIME_IVU_TEST);
1126 bt_mesh_iv_update_test(true);
1127
1128 device_setup();
1129
1130 PASS();
1131 }
1132
1133 #define TEST_CASE(role, name, description) \
1134 { \
1135 .test_id = "brg_" #role "_" #name, \
1136 .test_post_init_f = test_##role##_init, \
1137 .test_descr = description, \
1138 .test_tick_f = bt_mesh_test_timeout, \
1139 .test_main_f = test_##role##_##name, \
1140 }
1141
1142 static const struct bst_test_instance test_brg[] = {
1143 TEST_CASE(tester, simple,
1144 "Tester node: provisions network, exchanges messages with "
1145 "mesh nodes"),
1146 TEST_CASE(tester, simple_group,
1147 "Tester node: provisions network, configures group subscription and exchanges "
1148 "messages with mesh nodes"),
1149 TEST_CASE(tester, simple_va,
1150 "Tester node: provisions network, configures virtual address subscription "
1151 "and exchanges messages with mesh nodes"),
1152 TEST_CASE(tester, table_state_change,
1153 "Tester node: tests changing bridging table "
1154 "state"),
1155 TEST_CASE(tester, net_key_remove,
1156 "Tester node: tests removing net key from Subnet "
1157 "Bridge"),
1158 #if CONFIG_BT_SETTINGS
1159 TEST_CASE(tester, persistence, "Tester node: test persistence of subnet bridge states"),
1160 #endif
1161 TEST_CASE(tester, ivu, "Tester node: tests subnet bridge with IV Update procedure"),
1162 TEST_CASE(tester, key_refresh,
1163 "Tester node: tests bridge behavior during key refresh procedures"),
1164 TEST_CASE(bridge, simple, "Subnet Bridge node"),
1165 TEST_CASE(device, simple, "A mesh node"),
1166
1167 TEST_CASE(bridge, simple_iv_test_mode, "Subnet Bridge node with IV test mode enabled"),
1168 TEST_CASE(device, simple_iv_test_mode, "A mesh node with IV test mode enabled"),
1169
1170 BSTEST_END_MARKER};
1171
test_brg_install(struct bst_test_list * tests)1172 struct bst_test_list *test_brg_install(struct bst_test_list *tests)
1173 {
1174 tests = bst_add_tests(tests, test_brg);
1175 return tests;
1176 }
1177