From 0b35b38ef59b81040adc5014b9f82dd3863144ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Reierstad?= Date: Tue, 19 Nov 2024 08:53:27 +0100 Subject: [PATCH] Bsim: Bluetooth: Mesh: Add multicast bridge tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two new tests for the Subnet Bridge feature, testing group and virtual addresses as destinations. The tests are based on the existing `brg_simple.sh` test, with the addition of a new node and a new subnet to make sure that messages are bridged to multiple subnets, but only subnets that have a corresponding entry in the bridging table. Signed-off-by: HÃ¥vard Reierstad --- tests/bsim/bluetooth/mesh/prj.conf | 4 +- tests/bsim/bluetooth/mesh/src/test_brg.c | 187 ++++++++++++++++-- .../tests_scripts/bridge/brg_simple_group.sh | 45 +++++ .../tests_scripts/bridge/brg_simple_va.sh | 43 ++++ 4 files changed, 257 insertions(+), 22 deletions(-) create mode 100755 tests/bsim/bluetooth/mesh/tests_scripts/bridge/brg_simple_group.sh create mode 100755 tests/bsim/bluetooth/mesh/tests_scripts/bridge/brg_simple_va.sh diff --git a/tests/bsim/bluetooth/mesh/prj.conf b/tests/bsim/bluetooth/mesh/prj.conf index 156b1249675..bd5c2d2ec47 100644 --- a/tests/bsim/bluetooth/mesh/prj.conf +++ b/tests/bsim/bluetooth/mesh/prj.conf @@ -40,10 +40,10 @@ CONFIG_BT_MESH_PB_ADV=y CONFIG_BT_MESH_PROVISIONER=y CONFIG_BT_MESH_PROVISIONEE=y CONFIG_BT_MESH_CDB=y -CONFIG_BT_MESH_CDB_NODE_COUNT=4 +CONFIG_BT_MESH_CDB_NODE_COUNT=5 CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY=y CONFIG_BT_MESH_MODEL_EXTENSIONS=y -CONFIG_BT_MESH_CDB_SUBNET_COUNT=3 +CONFIG_BT_MESH_CDB_SUBNET_COUNT=4 CONFIG_BT_MESH_SUBNET_COUNT=5 CONFIG_BT_MESH_SAR_CFG_CLI=y CONFIG_BT_MESH_SAR_CFG_SRV=y diff --git a/tests/bsim/bluetooth/mesh/src/test_brg.c b/tests/bsim/bluetooth/mesh/src/test_brg.c index 0637ea1c48c..507b291fe62 100644 --- a/tests/bsim/bluetooth/mesh/src/test_brg.c +++ b/tests/bsim/bluetooth/mesh/src/test_brg.c @@ -10,6 +10,7 @@ #include #include "mesh/net.h" #include "mesh/keys.h" +#include "mesh/va.h" #include "bsim_args_runner.h" #include "common/bt_str.h" @@ -24,8 +25,10 @@ LOG_MODULE_REGISTER(test_brg, LOG_LEVEL_INF); /* Bridge address must be less than DEVICE_ADDR_START */ #define BRIDGE_ADDR 0x0002 #define DEVICE_ADDR_START 0x0003 +#define GROUP_ADDR 0xc000 #define REMOTE_NODES 2 +#define REMOTE_NODES_MULTICAST 3 static const uint8_t prov_dev_key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; @@ -34,6 +37,7 @@ static const uint8_t subnet_keys[][16] = { {0xaa, 0xbb, 0xcc}, {0xdd, 0xee, 0xff}, {0x11, 0x22, 0x33}, + {0x12, 0x34, 0x56}, }; static uint8_t prov_uuid[16] = {0x6c, 0x69, 0x6e, 0x67, 0x61, 0xaa}; @@ -54,6 +58,14 @@ enum { static uint8_t recvd_msgs[10]; static uint8_t recvd_msgs_cnt; +const struct bt_mesh_va *va_entry; + +enum { + TEST_TYPE_UNICAST = 0, + TEST_TYPE_GROUP = 1, + TEST_TYPE_VA = 2, +}; + BUILD_ASSERT((2 /* opcode */ + 1 /* type */ + 1 /* msgs cnt */ + sizeof(recvd_msgs) + BT_MESH_MIC_SHORT) <= BT_MESH_RX_SDU_MAX, "Status message does not fit into the maximum incoming SDU size."); @@ -148,10 +160,11 @@ static struct bt_mesh_prov bridge_prov = { .complete = prov_complete, }; -static void tester_setup(void) +static void tester_setup(int test_type) { uint8_t status; int err; + int subnets = (test_type == TEST_TYPE_UNICAST) ? REMOTE_NODES : REMOTE_NODES_MULTICAST; ASSERT_OK(bt_mesh_cdb_create(test_net_key)); ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, test_ividx, PROV_ADDR, prov_dev_key)); @@ -168,7 +181,7 @@ static void tester_setup(void) return; } - for (int i = 0; i < REMOTE_NODES; i++) { + for (int i = 0; i < subnets; i++) { LOG_INF("Creating subnet idx %d", i); ASSERT_OK( @@ -266,7 +279,7 @@ static void tester_bridge_configure(int subnets) LOG_INF("Bridge configured"); } -static void tester_device_configure(uint16_t net_key_idx, uint16_t addr) +static void tester_device_configure(uint16_t net_key_idx, uint16_t addr, int test_type) { int err; uint8_t status; @@ -290,6 +303,25 @@ static void tester_device_configure(uint16_t net_key_idx, uint16_t addr) return; } + if (test_type == TEST_TYPE_GROUP) { + err = bt_mesh_cfg_cli_mod_sub_add(net_key_idx, addr, addr, GROUP_ADDR, TEST_MOD_ID, + &status); + if (err || status) { + FAIL("Mod sub add failed (err %d, status %u)", err, status); + return; + } + } else if (test_type == TEST_TYPE_VA) { + uint16_t vaddr; + + err = bt_mesh_cfg_cli_mod_sub_va_add(net_key_idx, addr, addr, test_va_uuid, + TEST_MOD_ID, &vaddr, &status); + if (err || status) { + FAIL("Mod sub VA add failed (err %d, status %u)", err, status); + return; + } + ASSERT_EQUAL(vaddr, va_entry->addr); + } + LOG_INF("Device 0x%04x configured", addr); } @@ -367,6 +399,12 @@ static void device_data_cb(uint8_t *data, size_t length) { uint8_t type = data[0]; + /* For group/va tests: There is no bridge entry for the subnet that the final device + * belongs to. If it receives a message from the tester, fail. + */ + ASSERT_TRUE_MSG(get_device_nbr() != REMOTE_NODES_MULTICAST + 1, + "Unbridged device received message"); + LOG_HEXDUMP_DBG(data, length, "Device received message"); switch (type) { @@ -386,8 +424,8 @@ static void device_data_cb(uint8_t *data, size_t length) memcpy(&test_data[2], recvd_msgs, recvd_msgs_cnt * sizeof(recvd_msgs[0])); ASSERT_OK(bt_mesh_test_send_data(PROV_ADDR, NULL, test_data, - 2 + recvd_msgs_cnt * sizeof(recvd_msgs[0]), NULL, - NULL)); + 2 + recvd_msgs_cnt * sizeof(recvd_msgs[0]), NULL, + NULL)); memset(recvd_msgs, 0, sizeof(recvd_msgs)); recvd_msgs_cnt = 0; @@ -406,14 +444,15 @@ static void device_data_cb(uint8_t *data, size_t length) * hit when the devices send STATUS message encrypted with the subnet key known by the tester, * but with different app key pair (app key is the same, but net key <-> app key pair is different). */ -static void tester_workaround(void) +static void tester_workaround(int test_type) { uint8_t status; int err; + int subnets = (test_type == TEST_TYPE_UNICAST) ? REMOTE_NODES : REMOTE_NODES_MULTICAST; LOG_INF("Applying subnet's workaround for tester..."); - for (int i = 0; i < REMOTE_NODES; i++) { + for (int i = 0; i < subnets; i++) { err = bt_mesh_cfg_cli_net_key_del(0, PROV_ADDR, i + 1, &status); if (err || status) { FAIL("NetKey del failed (err %d, status %u)", err, status); @@ -459,7 +498,7 @@ static void test_tester_simple(void) bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&tester_prov, &comp); - tester_setup(); + tester_setup(TEST_TYPE_UNICAST); for (int i = 0; i < 1 /* bridge */ + REMOTE_NODES; i++) { LOG_INF("Waiting for a device to provision..."); @@ -475,10 +514,10 @@ static void test_tester_simple(void) } for (int i = 0; i < REMOTE_NODES; i++) { - tester_device_configure(i + 1, DEVICE_ADDR_START + i); + tester_device_configure(i + 1, DEVICE_ADDR_START + i, TEST_TYPE_UNICAST); } - tester_workaround(); + tester_workaround(TEST_TYPE_UNICAST); bt_mesh_test_data_cb_setup(tester_data_cb); @@ -521,6 +560,108 @@ static void test_tester_simple(void) PASS(); } +static void tester_simple_multicast(int test_type) +{ + uint8_t status; + int err; + const int msgs_cnt = 3; + uint16_t addr = (test_type == TEST_TYPE_GROUP) ? GROUP_ADDR : va_entry->addr; + const uint8_t *uuid = (test_type == TEST_TYPE_VA) ? va_entry->uuid : NULL; + + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_device_setup(&tester_prov, &comp); + + tester_setup(test_type); + + for (int i = 0; i < 1 /* bridge */ + REMOTE_NODES_MULTICAST; i++) { + LOG_INF("Waiting for a device to provision..."); + ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40))); + } + + tester_bridge_configure(REMOTE_NODES_MULTICAST); + + for (int i = 0; i < REMOTE_NODES_MULTICAST; i++) { + tester_device_configure(i + 1, DEVICE_ADDR_START + i, test_type); + } + + /* Adding devices to bridge table */ + for (int i = 0; i < REMOTE_NODES_MULTICAST; i++) { + /* Bridge messages from tester to multicast addr, for each subnet expect the last */ + if (i != REMOTE_NODES_MULTICAST - 1) { + bridge_entry_add(PROV_ADDR, addr, 0, i + 1, BT_MESH_BRG_CFG_DIR_ONEWAY); + } + + /* Bridge messages from remote nodes to tester */ + bridge_entry_add(DEVICE_ADDR_START + i, PROV_ADDR, i + 1, 0, + BT_MESH_BRG_CFG_DIR_ONEWAY); + } + + tester_workaround(test_type); + + bt_mesh_test_data_cb_setup(tester_data_cb); + + LOG_INF("Step 1: Checking bridging table..."); + + LOG_INF("Sending data..."); + + for (int i = 0; i < msgs_cnt; i++) { + ASSERT_OK(send_data(addr, i, uuid)); + } + + LOG_INF("Checking data..."); + + ASSERT_OK(send_get(addr, uuid)); + for (int i = 0; i < REMOTE_NODES_MULTICAST - 1; i++) { + ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5))); + + ASSERT_EQUAL(recvd_msgs_cnt, msgs_cnt); + for (int j = 0; j < recvd_msgs_cnt; j++) { + ASSERT_EQUAL(recvd_msgs[j], j); + } + } + + LOG_INF("Step 2: Disabling bridging..."); + + err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_DISABLED, &status); + if (err || status != BT_MESH_BRG_CFG_DISABLED) { + FAIL("Subnet bridge set failed (err %d) (status %u)", err, status); + return; + } + + LOG_INF("Sending data..."); + for (int i = 0; i < msgs_cnt; i++) { + ASSERT_OK(send_data(addr, i, uuid)); + } + + LOG_INF("Step 3: Enabling bridging..."); + err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_ENABLED, &status); + if (err || status != BT_MESH_BRG_CFG_ENABLED) { + FAIL("Subnet bridge set failed (err %d) (status %u)", err, status); + return; + } + + LOG_INF("Checking data..."); + ASSERT_OK(send_get(addr, uuid)); + for (int i = 0; i < REMOTE_NODES_MULTICAST - 1; i++) { + ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5))); + ASSERT_EQUAL(recvd_msgs_cnt, 0); + } +} + +static void test_tester_simple_group(void) +{ + tester_simple_multicast(TEST_TYPE_GROUP); + PASS(); +} + +static void test_tester_simple_va(void) +{ + ASSERT_OK(bt_mesh_va_add(test_va_uuid, &va_entry)); + ASSERT_TRUE(va_entry != NULL); + tester_simple_multicast(TEST_TYPE_VA); + PASS(); +} + static void test_tester_table_state_change(void) { int err; @@ -528,7 +669,7 @@ static void test_tester_table_state_change(void) bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&tester_prov, &comp); - tester_setup(); + tester_setup(TEST_TYPE_UNICAST); for (int i = 0; i < 1 /* bridge */ + REMOTE_NODES; i++) { LOG_INF("Waiting for a device to provision..."); @@ -538,10 +679,10 @@ static void test_tester_table_state_change(void) tester_bridge_configure(REMOTE_NODES); for (int i = 0; i < REMOTE_NODES; i++) { - tester_device_configure(i + 1, DEVICE_ADDR_START + i); + tester_device_configure(i + 1, DEVICE_ADDR_START + i, TEST_TYPE_UNICAST); } - tester_workaround(); + tester_workaround(TEST_TYPE_UNICAST); bt_mesh_test_data_cb_setup(tester_data_cb); @@ -625,7 +766,7 @@ static void test_tester_net_key_remove(void) bt_mesh_test_cfg_set(NULL, WAIT_TIME); bt_mesh_device_setup(&tester_prov, &comp); - tester_setup(); + tester_setup(TEST_TYPE_UNICAST); for (int i = 0; i < 1 /* bridge */ + REMOTE_NODES; i++) { LOG_INF("Waiting for a device to provision..."); @@ -635,10 +776,10 @@ static void test_tester_net_key_remove(void) tester_bridge_configure(REMOTE_NODES); for (int i = 0; i < REMOTE_NODES; i++) { - tester_device_configure(i + 1, DEVICE_ADDR_START + i); + tester_device_configure(i + 1, DEVICE_ADDR_START + i, TEST_TYPE_UNICAST); } - tester_workaround(); + tester_workaround(TEST_TYPE_UNICAST); bt_mesh_test_data_cb_setup(tester_data_cb); @@ -726,7 +867,7 @@ static void test_tester_persistence(void) }, 1); } else { - tester_setup(); + tester_setup(TEST_TYPE_UNICAST); LOG_INF("Waiting for a bridge to provision..."); ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40))); @@ -820,7 +961,7 @@ static void test_tester_ivu(void) bt_mesh_device_setup(&tester_prov, &comp); bt_mesh_iv_update_test(true); - tester_setup(); + tester_setup(TEST_TYPE_UNICAST); for (int i = 0; i < 1 /* bridge */ + REMOTE_NODES; i++) { LOG_INF("Waiting for a device to provision..."); @@ -836,10 +977,10 @@ static void test_tester_ivu(void) } for (int i = 0; i < REMOTE_NODES; i++) { - tester_device_configure(i + 1, DEVICE_ADDR_START + i); + tester_device_configure(i + 1, DEVICE_ADDR_START + i, TEST_TYPE_UNICAST); } - tester_workaround(); + tester_workaround(TEST_TYPE_UNICAST); bt_mesh_test_data_cb_setup(tester_data_cb); @@ -964,6 +1105,12 @@ static const struct bst_test_instance test_brg[] = { TEST_CASE(tester, simple, "Tester node: provisions network, exchanges messages with " "mesh nodes"), + TEST_CASE(tester, simple_group, + "Tester node: provisions network, configures group subscription and exchanges " + "messages with mesh nodes"), + TEST_CASE(tester, simple_va, + "Tester node: provisions network, configures virtual address subscription " + "and exchanges messages with mesh nodes"), TEST_CASE(tester, table_state_change, "Tester node: tests changing bridging table " "state"), diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/bridge/brg_simple_group.sh b/tests/bsim/bluetooth/mesh/tests_scripts/bridge/brg_simple_group.sh new file mode 100755 index 00000000000..02dc8d799a5 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/bridge/brg_simple_group.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# This test checks basic functionality of the Subnet Bridge with group addressing. It checks the +# following: +# - Messages are bridged to group address subscribers, only for subnets in the bridging table. +# - Messages are not bridged when the Subnet Bridge state is disabled. +# +# 3 roles are used in this test: Tester, Subnet Bridge node, and Mesh node. +# +# Subnets topology*: +# Tester +# | +# (subnet 0) +# | +# Subnet Bridge (bridges subnets: 0 --> 0xC000, subnets 1 and 2) +# | +# Group Address (0xC000) +# / | \ +# (subnet 1) (subnet 2) (subnet 3)** +# | | \ +# Node Node Node +# +# (*) - All nodes are in the tester's range +# (**) - Messages are not bridged to subnet 3 via the group address. If the node belonging to subnet +# 3 receives a message from the tester, the test will fail. +# +# Test procedure: +# The same procedure as in the `mesh_brg_simple` test is used. The main differences are: +# - An additional node is added to a new subnet (3). +# - Each of the nodes are subscribed to the same group address. Messages are bridged from the tester +# to the group address, only for subnets 1 and 2. +# - To allow nodes to respond to the tester, messages from each node is bridged to the tester. + +RunTest mesh_brg_simple_group \ + brg_tester_simple_group brg_bridge_simple brg_device_simple brg_device_simple \ + brg_device_simple + +overlay=overlay_psa_conf +RunTest mesh_brg_simple_group_psa \ + brg_tester_simple_group brg_bridge_simple brg_device_simple brg_device_simple \ + brg_device_simple diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/bridge/brg_simple_va.sh b/tests/bsim/bluetooth/mesh/tests_scripts/bridge/brg_simple_va.sh new file mode 100755 index 00000000000..4c061c9e388 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/bridge/brg_simple_va.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# This test checks basic functionality of the Subnet Bridge with virtual addressing. It checks the +# following: +# - Messages are bridged to virtual address subscribers, only for subnets in the bridging table. +# - Messages are not bridged when the Subnet Bridge state is disabled. +# +# 3 roles are used in this test: Tester, Subnet Bridge node, and Mesh node. +# +# Subnets topology*: +# Tester +# | +# (subnet 0) +# | +# Subnet Bridge (bridges subnets 1 and 2) +# | +# Virtual Address +# / | \ +# (subnet 1) (subnet 2) (subnet 3)** +# | | \ +# Node Node Node +# +# (*) - All nodes are in the tester's range +# (**) - Messages are not bridged to subnet 3 via the virtual address. If the node belonging to +# subnet 3 receives a message from the tester, the test will fail. +# +# Test procedure: +# The same procedure as in the `mesh_brg_simple` test is used. The main differences are: +# - An additional node is added to a new subnet (3). +# - Each of the nodes are subscribed to the same virtual address. Messages are bridged from the +# tester to the virtual address, only for subnets 1 and 2. +# - To allow nodes to respond to the tester, messages from each node is bridged to the tester. + +RunTest mesh_brg_simple_va \ + brg_tester_simple_va brg_bridge_simple brg_device_simple brg_device_simple brg_device_simple + +overlay=overlay_psa_conf +RunTest mesh_brg_simple_va_psa \ + brg_tester_simple_va brg_bridge_simple brg_device_simple brg_device_simple brg_device_simple