Bluetooth: Mesh: Adds subnet bridge states
The `brg_cfg` module implements the states needed for subnet bridge feature. It provides two states - enable state, and bridging table state. APIs are provided to access and modify the states. The module handles responsibility of persistence of the states. Signed-off-by: Omkar Kulkarni <omkar.kulkarni@nordicsemi.no>
This commit is contained in:
parent
709c006b58
commit
092f808ea4
12 changed files with 951 additions and 2 deletions
|
@ -407,6 +407,10 @@ module = BT_MESH_NET
|
|||
module-str = "Network layer"
|
||||
source "subsys/logging/Kconfig.template.log_config_inherit"
|
||||
|
||||
module = BT_MESH_BRG
|
||||
module-str = "Subnet Bridging layer"
|
||||
source "subsys/logging/Kconfig.template.log_config_inherit"
|
||||
|
||||
module = BT_MESH_RPL
|
||||
module-str = "Replay protection list"
|
||||
source "subsys/logging/Kconfig.template.log_config_inherit"
|
||||
|
|
|
@ -115,7 +115,7 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV sol_pdu_rpl_srv.c)
|
|||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_BRG_CFG_CLI brg_cfg_cli.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_BRG_CFG_SRV brg_cfg_srv.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_BRG_CFG_SRV brg_cfg_srv.c brg_cfg.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_SOLICITATION solicitation.c)
|
||||
|
||||
|
|
|
@ -1274,6 +1274,18 @@ config BT_MESH_BRG_CFG_SRV
|
|||
The Bridge Configuration Server model is used to support the configuration
|
||||
of the subnet bridge functionality of a node.
|
||||
|
||||
menu "Subnet Bridge configuration"
|
||||
visible if BT_MESH_BRG_CFG_SRV
|
||||
|
||||
config BT_MESH_BRG_TABLE_ITEMS_MAX
|
||||
int "Maximum number of entries in the bridging table"
|
||||
default 16
|
||||
range 16 255
|
||||
help
|
||||
The maximum number of entries in the bridging table.
|
||||
|
||||
endmenu
|
||||
|
||||
config BT_MESH_BRG_CFG_CLI
|
||||
bool "Support for Bridge Configuration Client model"
|
||||
help
|
||||
|
|
307
subsys/bluetooth/mesh/brg_cfg.c
Normal file
307
subsys/bluetooth/mesh/brg_cfg.c
Normal file
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Implementation for states of Subnet Bridge feature in Bluetooth Mesh Protocol v1.1
|
||||
* specification
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <zephyr/bluetooth/mesh.h>
|
||||
|
||||
#include "mesh.h"
|
||||
#include "net.h"
|
||||
#include "settings.h"
|
||||
#include "brg_cfg.h"
|
||||
|
||||
#define LOG_LEVEL CONFIG_BT_MESH_BRG_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(bt_mesh_brg_cfg);
|
||||
|
||||
/* Bridging table state and counter */
|
||||
static struct bt_mesh_brg_cfg_row brg_tbl[CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX];
|
||||
static uint32_t bt_mesh_brg_cfg_row_cnt;
|
||||
/* Bridging enabled state */
|
||||
static bool brg_enabled;
|
||||
|
||||
static void brg_tbl_compact(void)
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
for (int k = 0; k < bt_mesh_brg_cfg_row_cnt; k++) {
|
||||
if (brg_tbl[k].direction != 0) {
|
||||
brg_tbl[j] = brg_tbl[k];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
memset(&brg_tbl[j], 0, sizeof(brg_tbl[j]));
|
||||
bt_mesh_brg_cfg_row_cnt--;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_SETTINGS)
|
||||
/* Set function for initializing bridging enable state from value stored in settings. */
|
||||
static int brg_en_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (len_rd == 0) {
|
||||
brg_enabled = 0;
|
||||
LOG_DBG("Cleared bridge enable state");
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = bt_mesh_settings_set(read_cb, cb_arg, &brg_enabled, sizeof(brg_enabled));
|
||||
if (err) {
|
||||
LOG_ERR("Failed to set bridge enable state");
|
||||
return err;
|
||||
}
|
||||
|
||||
LOG_DBG("Restored bridge enable state");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Define a setting for storing enable state */
|
||||
BT_MESH_SETTINGS_DEFINE(brg_en, "brg_en", brg_en_set);
|
||||
|
||||
/* Set function for initializing bridging table rows from values stored in settings. */
|
||||
static int brg_tbl_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
if (len_rd == 0) {
|
||||
memset(brg_tbl, 0, sizeof(brg_tbl));
|
||||
bt_mesh_brg_cfg_row_cnt = 0;
|
||||
LOG_DBG("Cleared bridging table entries");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int err = bt_mesh_settings_set(read_cb, cb_arg, brg_tbl, sizeof(brg_tbl));
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Failed to set bridging table entries");
|
||||
return err;
|
||||
}
|
||||
|
||||
LOG_DBG("Restored bridging table");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Define a setting for storing briging table rows */
|
||||
BT_MESH_SETTINGS_DEFINE(brg_tbl, "brg_tbl", brg_tbl_set);
|
||||
#endif
|
||||
|
||||
bool bt_mesh_brg_cfg_enable_get(void)
|
||||
{
|
||||
return brg_enabled;
|
||||
}
|
||||
|
||||
int bt_mesh_brg_cfg_enable_set(bool enable)
|
||||
{
|
||||
if (brg_enabled == enable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
brg_enabled = enable;
|
||||
#if IS_ENABLED(CONFIG_BT_SETTINGS)
|
||||
bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_BRG_PENDING);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_brg_cfg_pending_store(void)
|
||||
{
|
||||
#if CONFIG_BT_SETTINGS
|
||||
char *path_en = "bt/mesh/brg_en";
|
||||
char *path_tbl = "bt/mesh/brg_tbl";
|
||||
int err;
|
||||
|
||||
if (brg_enabled) {
|
||||
err = settings_save_one(path_en, &brg_enabled, sizeof(brg_enabled));
|
||||
} else {
|
||||
err = settings_delete(path_en);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Failed to store %s value", path_en);
|
||||
}
|
||||
|
||||
|
||||
if (bt_mesh_brg_cfg_row_cnt) {
|
||||
err = settings_save_one(path_tbl, &brg_tbl,
|
||||
bt_mesh_brg_cfg_row_cnt * sizeof(brg_tbl[0]));
|
||||
} else {
|
||||
err = settings_delete(path_tbl);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Failed to store %s value", path_tbl);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Remove the entry from the bridging table that corresponds with the NetKey Index of the removed
|
||||
* subnet.
|
||||
*/
|
||||
static void brg_tbl_netkey_removed_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
if (evt != BT_MESH_KEY_DELETED) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX; i++) {
|
||||
if (brg_tbl[i].direction && (
|
||||
brg_tbl[i].net_idx1 == sub->net_idx ||
|
||||
brg_tbl[i].net_idx2 == sub->net_idx)) {
|
||||
memset(&brg_tbl[i], 0, sizeof(brg_tbl[i]));
|
||||
brg_tbl_compact();
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_SETTINGS)
|
||||
bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_BRG_PENDING);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Add event hook for key deletion event */
|
||||
BT_MESH_SUBNET_CB_DEFINE(sbr) = {
|
||||
.evt_handler = brg_tbl_netkey_removed_evt,
|
||||
};
|
||||
|
||||
int bt_mesh_brg_cfg_tbl_reset(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
brg_enabled = false;
|
||||
bt_mesh_brg_cfg_row_cnt = 0;
|
||||
memset(brg_tbl, 0, sizeof(brg_tbl));
|
||||
|
||||
#if CONFIG_BT_SETTINGS
|
||||
err = settings_delete("bt/mesh/brg_en");
|
||||
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = settings_delete("bt/mesh/brg_tbl");
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_brg_cfg_tbl_get(const struct bt_mesh_brg_cfg_row **rows)
|
||||
{
|
||||
*rows = brg_tbl;
|
||||
return bt_mesh_brg_cfg_row_cnt;
|
||||
}
|
||||
|
||||
int bt_mesh_brg_cfg_tbl_add(enum bt_mesh_brg_cfg_dir direction, uint16_t net_idx1,
|
||||
uint16_t net_idx2, uint16_t addr1, uint16_t addr2)
|
||||
{
|
||||
/* Sanity checks */
|
||||
if (!BT_MESH_ADDR_IS_UNICAST(addr1) || net_idx1 == net_idx2 || addr1 == addr2 ||
|
||||
net_idx1 > 0x03FF || net_idx2 > 0x03FF) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (direction != BT_MESH_BRG_CFG_DIR_ONEWAY && direction != BT_MESH_BRG_CFG_DIR_TWOWAY) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((direction == BT_MESH_BRG_CFG_DIR_ONEWAY &&
|
||||
(addr2 == BT_MESH_ADDR_UNASSIGNED || addr2 == BT_MESH_ADDR_ALL_NODES)) ||
|
||||
(direction == BT_MESH_BRG_CFG_DIR_TWOWAY &&
|
||||
!BT_MESH_ADDR_IS_UNICAST(addr2))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check if entry already exists, if yes, then, update the direction field and it is a
|
||||
* success.
|
||||
* "If a Bridging Table state entry corresponding to the received message exists, the
|
||||
* element shall set the Directions field in the entry to the value of the Directions field
|
||||
* in the received message."
|
||||
*/
|
||||
for (int i = 0; i < bt_mesh_brg_cfg_row_cnt; i++) {
|
||||
if (brg_tbl[i].net_idx1 == net_idx1 &&
|
||||
brg_tbl[i].net_idx2 == net_idx2 && brg_tbl[i].addr1 == addr1 &&
|
||||
brg_tbl[i].addr2 == addr2) {
|
||||
brg_tbl[i].direction = direction;
|
||||
goto store;
|
||||
}
|
||||
}
|
||||
|
||||
/* Empty element, is the current table row counter */
|
||||
if (bt_mesh_brg_cfg_row_cnt == CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Update the row */
|
||||
brg_tbl[bt_mesh_brg_cfg_row_cnt].direction = direction;
|
||||
brg_tbl[bt_mesh_brg_cfg_row_cnt].net_idx1 = net_idx1;
|
||||
brg_tbl[bt_mesh_brg_cfg_row_cnt].net_idx2 = net_idx2;
|
||||
brg_tbl[bt_mesh_brg_cfg_row_cnt].addr1 = addr1;
|
||||
brg_tbl[bt_mesh_brg_cfg_row_cnt].addr2 = addr2;
|
||||
bt_mesh_brg_cfg_row_cnt++;
|
||||
|
||||
store:
|
||||
#if IS_ENABLED(CONFIG_BT_SETTINGS)
|
||||
bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_BRG_PENDING);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_brg_cfg_tbl_foreach_subnet(uint16_t src, uint16_t dst, uint16_t net_idx,
|
||||
bt_mesh_brg_cfg_cb_t cb, void *user_data)
|
||||
{
|
||||
for (int i = 0; i < bt_mesh_brg_cfg_row_cnt; i++) {
|
||||
if ((brg_tbl[i].direction == BT_MESH_BRG_CFG_DIR_ONEWAY ||
|
||||
brg_tbl[i].direction == BT_MESH_BRG_CFG_DIR_TWOWAY) &&
|
||||
brg_tbl[i].net_idx1 == net_idx && brg_tbl[i].addr1 == src &&
|
||||
brg_tbl[i].addr2 == dst) {
|
||||
cb(brg_tbl[i].net_idx2, user_data);
|
||||
} else if ((brg_tbl[i].direction == BT_MESH_BRG_CFG_DIR_TWOWAY &&
|
||||
brg_tbl[i].net_idx2 == net_idx && brg_tbl[i].addr2 == src &&
|
||||
brg_tbl[i].addr1 == dst)) {
|
||||
cb(brg_tbl[i].net_idx1, user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_brg_cfg_tbl_remove(uint16_t net_idx1, uint16_t net_idx2, uint16_t addr1,
|
||||
uint16_t addr2)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_BT_SETTINGS)
|
||||
bool store = false;
|
||||
#endif
|
||||
|
||||
/* Iterate over items and set matching row to 0, if nothing exist, or nothing matches, then
|
||||
* it is success (similar to add)
|
||||
*/
|
||||
if (bt_mesh_brg_cfg_row_cnt == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < bt_mesh_brg_cfg_row_cnt; i++) {
|
||||
/* Match according to remove behavior in Section 4.4.9.2.2 of MshPRT_v1.1 */
|
||||
if (brg_tbl[i].direction) {
|
||||
if (!(brg_tbl[i].net_idx1 == net_idx1 && brg_tbl[i].net_idx2 == net_idx2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((brg_tbl[i].addr1 == addr1 && brg_tbl[i].addr2 == addr2) ||
|
||||
(addr2 == BT_MESH_ADDR_UNASSIGNED && brg_tbl[i].addr1 == addr1) ||
|
||||
(addr1 == BT_MESH_ADDR_UNASSIGNED && brg_tbl[i].addr2 == addr2)) {
|
||||
memset(&brg_tbl[i], 0, sizeof(brg_tbl[i]));
|
||||
brg_tbl_compact();
|
||||
#if IS_ENABLED(CONFIG_BT_SETTINGS)
|
||||
store = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_BT_SETTINGS)
|
||||
if (store) {
|
||||
bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_BRG_PENDING);
|
||||
}
|
||||
#endif
|
||||
}
|
74
subsys/bluetooth/mesh/brg_cfg.h
Normal file
74
subsys/bluetooth/mesh/brg_cfg.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_BRG_CFG_H_
|
||||
#define ZEPHYR_SUBSYS_BLUETOOTH_MESH_BRG_CFG_H_
|
||||
|
||||
/** These are internal APIs. They do not sanitize input params. */
|
||||
enum bt_mesh_brg_cfg_dir {
|
||||
/* Value is prohibited. */
|
||||
BT_MESH_BRG_CFG_DIR_PROHIBITED = 0,
|
||||
/* Briging from Addr1 to Addr2. */
|
||||
BT_MESH_BRG_CFG_DIR_ONEWAY = 1,
|
||||
/* Briging to/from Addr1 from/to Addr2. */
|
||||
BT_MESH_BRG_CFG_DIR_TWOWAY = 2,
|
||||
/* Values above these are prohibited. */
|
||||
BT_MESH_BRG_CFG_DIR_MAX = 3,
|
||||
};
|
||||
|
||||
#define BT_MESH_BRG_CFG_NETIDX_NOMATCH 0xFFFF
|
||||
|
||||
/* One row of the bridging table */
|
||||
struct bt_mesh_brg_cfg_row {
|
||||
/* Direction of the entry in the bridging table
|
||||
* 0 - no entry,
|
||||
* 1 - bridge messages with src as addr1 and dst as addr2
|
||||
* 2 - bridge messages with src as addr1 and dst as addr2 and vice-versa
|
||||
*/
|
||||
uint32_t direction:8;
|
||||
uint32_t net_idx1:12;
|
||||
uint32_t net_idx2:12;
|
||||
uint16_t addr1;
|
||||
uint16_t addr2;
|
||||
};
|
||||
|
||||
bool bt_mesh_brg_cfg_enable_get(void);
|
||||
|
||||
int bt_mesh_brg_cfg_enable_set(bool enable);
|
||||
|
||||
void bt_mesh_brg_cfg_pending_store(void);
|
||||
|
||||
int bt_mesh_brg_cfg_tbl_reset(void);
|
||||
|
||||
int bt_mesh_brg_cfg_tbl_get(const struct bt_mesh_brg_cfg_row **rows);
|
||||
|
||||
int bt_mesh_brg_cfg_tbl_add(enum bt_mesh_brg_cfg_dir direction, uint16_t net_idx1,
|
||||
uint16_t net_idx2, uint16_t addr1, uint16_t addr2);
|
||||
|
||||
void bt_mesh_brg_cfg_tbl_remove(uint16_t net_idx1, uint16_t net_idx2, uint16_t addr1,
|
||||
uint16_t addr2);
|
||||
|
||||
typedef void (*bt_mesh_brg_cfg_cb_t)(uint16_t new_netidx, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Iterate over the bridging table to find a matching entry for the given SRC, DST, and
|
||||
* NetKey Index.
|
||||
*
|
||||
* This function iterates over the bridging table and checks if there is a match for the provided
|
||||
* parameters. If a match is found, the callback function specified by the 'cb' parameter is
|
||||
* invoked with the NetKey Index of each matching entry (there can be several). Relaying operation
|
||||
* can then happen inside this callback.
|
||||
*
|
||||
* @param src The source address to match.
|
||||
* @param dst The destination address to match.
|
||||
* @param net_idx The NetKey Index to match.
|
||||
* @param cb The callback function to be invoked for each matching entry.
|
||||
* @param user_data User data to be passed to the callback function.
|
||||
*/
|
||||
void bt_mesh_brg_cfg_tbl_foreach_subnet(uint16_t src, uint16_t dst, uint16_t net_idx,
|
||||
bt_mesh_brg_cfg_cb_t cb, void *user_data);
|
||||
|
||||
#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_BRG_CFG_H_ */
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <zephyr/bluetooth/mesh.h>
|
||||
#include "brg_cfg.h"
|
||||
|
||||
#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
|
@ -30,6 +31,12 @@ static int brg_cfg_srv_init(const struct bt_mesh_model *model)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void brg_cfg_srv_reset(const struct bt_mesh_model *model)
|
||||
{
|
||||
bt_mesh_brg_cfg_tbl_reset();
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb _bt_mesh_brg_cfg_srv_cb = {
|
||||
.init = brg_cfg_srv_init,
|
||||
.reset = brg_cfg_srv_reset,
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "pb_gatt_srv.h"
|
||||
#include "settings.h"
|
||||
#include "cfg.h"
|
||||
#include "brg_cfg.h"
|
||||
#include "solicitation.h"
|
||||
#include "va.h"
|
||||
|
||||
|
@ -134,7 +135,8 @@ SETTINGS_STATIC_HANDLER_DEFINE(bt_mesh, "bt/mesh", NULL, NULL, mesh_commit,
|
|||
BIT(BT_MESH_SETTINGS_VA_PENDING) | \
|
||||
BIT(BT_MESH_SETTINGS_SSEQ_PENDING) | \
|
||||
BIT(BT_MESH_SETTINGS_COMP_PENDING) | \
|
||||
BIT(BT_MESH_SETTINGS_DEV_KEY_CAND_PENDING))
|
||||
BIT(BT_MESH_SETTINGS_DEV_KEY_CAND_PENDING) | \
|
||||
BIT(BT_MESH_SETTINGS_BRG_PENDING))
|
||||
|
||||
void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)
|
||||
{
|
||||
|
@ -262,6 +264,12 @@ static void store_pending(struct k_work *work)
|
|||
BT_MESH_SETTINGS_SSEQ_PENDING)) {
|
||||
bt_mesh_sseq_pending_store();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_BRG_CFG_SRV) &&
|
||||
atomic_test_and_clear_bit(pending_flags,
|
||||
BT_MESH_SETTINGS_BRG_PENDING)) {
|
||||
bt_mesh_brg_cfg_pending_store();
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_settings_init(void)
|
||||
|
|
|
@ -21,6 +21,7 @@ enum bt_mesh_settings_flag {
|
|||
BT_MESH_SETTINGS_SSEQ_PENDING,
|
||||
BT_MESH_SETTINGS_COMP_PENDING,
|
||||
BT_MESH_SETTINGS_DEV_KEY_CAND_PENDING,
|
||||
BT_MESH_SETTINGS_BRG_PENDING,
|
||||
|
||||
BT_MESH_SETTINGS_FLAG_COUNT,
|
||||
};
|
||||
|
|
22
tests/bluetooth/mesh/brg/CMakeLists.txt
Normal file
22
tests/bluetooth/mesh/brg/CMakeLists.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(bluetooth_mesh_brg)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app
|
||||
PRIVATE
|
||||
${app_sources}
|
||||
${ZEPHYR_BASE}/subsys/bluetooth/mesh/brg_cfg.c)
|
||||
|
||||
target_include_directories(app
|
||||
PRIVATE
|
||||
${ZEPHYR_BASE}/subsys/bluetooth/mesh)
|
||||
|
||||
target_compile_options(app
|
||||
PRIVATE
|
||||
-DCONFIG_BT_SETTINGS
|
||||
-DCONFIG_BT_MESH_BRG_CFG_SRV
|
||||
-DCONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX=16
|
||||
-DCONFIG_BT_MESH_USES_TINYCRYPT)
|
3
tests/bluetooth/mesh/brg/prj.conf
Normal file
3
tests/bluetooth/mesh/brg/prj.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_ZTEST=y
|
||||
CONFIG_ZTEST_MOCKING=y
|
||||
CONFIG_BT_MESH_BRG_CFG_SRV=y
|
501
tests/bluetooth/mesh/brg/src/main.c
Normal file
501
tests/bluetooth/mesh/brg/src/main.c
Normal file
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/ztest.h>
|
||||
#include <zephyr/net/buf.h>
|
||||
#include <zephyr/bluetooth/mesh.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "settings.h"
|
||||
#include "brg_cfg.h"
|
||||
|
||||
#define TEST_VECT_SZ (CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX + 1)
|
||||
|
||||
static struct test_brg_cfg_row {
|
||||
uint8_t direction;
|
||||
uint16_t net_idx1;
|
||||
uint16_t net_idx2;
|
||||
uint16_t addr1;
|
||||
uint16_t addr2;
|
||||
} test_vector[TEST_VECT_SZ];
|
||||
|
||||
#define ADDR1_BASE (1)
|
||||
#define ADDR2_BASE (100)
|
||||
|
||||
/**** Helper functions ****/
|
||||
static void setup(void *f)
|
||||
{
|
||||
/* create test vector */
|
||||
for (int i = 0; i < TEST_VECT_SZ; i++) {
|
||||
test_vector[i].direction = i < (TEST_VECT_SZ / 2) ? 1 : 2;
|
||||
test_vector[i].net_idx1 = (i/8);
|
||||
test_vector[i].addr1 = ADDR1_BASE + i;
|
||||
test_vector[i].net_idx2 = (i/8) + 16;
|
||||
test_vector[i].addr2 = ADDR2_BASE + i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**** Mocked functions ****/
|
||||
|
||||
void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag)
|
||||
{
|
||||
ztest_check_expected_value(flag);
|
||||
}
|
||||
|
||||
int settings_save_one(const char *name, const void *value, size_t val_len)
|
||||
{
|
||||
ztest_check_expected_data(name, strlen(name));
|
||||
ztest_check_expected_value(val_len);
|
||||
ztest_check_expected_data(value, val_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int settings_delete(const char *name)
|
||||
{
|
||||
ztest_check_expected_data(name, strlen(name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**** Mocked functions - end ****/
|
||||
|
||||
static void check_fill_all_bt_entries(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
for (int i = 0; i < TEST_VECT_SZ; i++) {
|
||||
|
||||
if (i < CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
|
||||
ztest_expect_value(bt_mesh_settings_store_schedule, flag,
|
||||
BT_MESH_SETTINGS_BRG_PENDING);
|
||||
}
|
||||
|
||||
err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction, test_vector[i].net_idx1,
|
||||
test_vector[i].net_idx2, test_vector[i].addr1, test_vector[i].addr2);
|
||||
|
||||
if (i != CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
|
||||
zassert_equal(err, 0);
|
||||
} else {
|
||||
zassert_equal(err, -ENOMEM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void check_delete_all_bt_entries(void)
|
||||
{
|
||||
for (int i = 0; i < TEST_VECT_SZ; i++) {
|
||||
|
||||
if (i < CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
|
||||
ztest_expect_value(bt_mesh_settings_store_schedule, flag,
|
||||
BT_MESH_SETTINGS_BRG_PENDING);
|
||||
}
|
||||
|
||||
bt_mesh_brg_cfg_tbl_remove(test_vector[i].net_idx1, test_vector[i].net_idx2,
|
||||
test_vector[i].addr1, test_vector[i].addr2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void check_bt_mesh_brg_cfg_tbl_reset(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
ztest_expect_data(settings_delete, name, "bt/mesh/brg_en");
|
||||
ztest_expect_data(settings_delete, name, "bt/mesh/brg_tbl");
|
||||
err = bt_mesh_brg_cfg_tbl_reset();
|
||||
zassert_equal(err, 0);
|
||||
}
|
||||
|
||||
/**** Tests ****/
|
||||
|
||||
ZTEST_SUITE(bt_mesh_brg_cfg, NULL, NULL, setup, NULL, NULL);
|
||||
|
||||
/* Test if basic functionality (add and remove entries) works correctly. */
|
||||
ZTEST(bt_mesh_brg_cfg, test_basic_functionality_storage)
|
||||
{
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
|
||||
/* Test add entries to bridging table. */
|
||||
check_fill_all_bt_entries();
|
||||
|
||||
/* Test remove entries from bridging table, and then fill it again. */
|
||||
check_delete_all_bt_entries();
|
||||
check_fill_all_bt_entries();
|
||||
|
||||
/* Test resetting of the table, and then fill it again. */
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries();
|
||||
|
||||
/* Test remove entries matching netkey1, and netkey2 */
|
||||
uint16_t net_idx1 = test_vector[TEST_VECT_SZ - 1].net_idx1;
|
||||
uint16_t net_idx2 = test_vector[TEST_VECT_SZ - 1].net_idx2;
|
||||
uint16_t addr1 = BT_MESH_ADDR_UNASSIGNED;
|
||||
uint16_t addr2 = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2);
|
||||
|
||||
const struct bt_mesh_brg_cfg_row *brg_tbl;
|
||||
int n = bt_mesh_brg_cfg_tbl_get(&brg_tbl);
|
||||
|
||||
zassert_true(n > 0);
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
zassert_true(brg_tbl[i].net_idx1 != net_idx1);
|
||||
zassert_true(brg_tbl[i].net_idx2 != net_idx2);
|
||||
}
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries();
|
||||
|
||||
/* Test remove entries matching netkey1, and netkey2, and addr1 */
|
||||
addr1 = test_vector[TEST_VECT_SZ - 1].addr1;
|
||||
n = bt_mesh_brg_cfg_tbl_get(&brg_tbl);
|
||||
|
||||
zassert_true(n > 0);
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
zassert_true(brg_tbl[i].net_idx1 != net_idx1);
|
||||
zassert_true(brg_tbl[i].net_idx2 != net_idx2);
|
||||
zassert_true(brg_tbl[i].addr1 != addr1);
|
||||
}
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries();
|
||||
|
||||
/* Test remove entries matching netkey1, and netkey2, and addr2 */
|
||||
addr1 = BT_MESH_ADDR_UNASSIGNED;
|
||||
addr2 = test_vector[TEST_VECT_SZ - 1].addr2;
|
||||
n = bt_mesh_brg_cfg_tbl_get(&brg_tbl);
|
||||
|
||||
zassert_true(n > 0);
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
zassert_true(brg_tbl[i].net_idx1 != net_idx1);
|
||||
zassert_true(brg_tbl[i].net_idx2 != net_idx2);
|
||||
zassert_true(brg_tbl[i].addr2 != addr2);
|
||||
}
|
||||
}
|
||||
|
||||
static void pending_store_enable_create_expectations(bool *enable_val,
|
||||
int n, const struct bt_mesh_brg_cfg_row *tbl_val)
|
||||
{
|
||||
if (*enable_val) {
|
||||
ztest_expect_data(settings_save_one, name, "bt/mesh/brg_en");
|
||||
ztest_expect_value(settings_save_one, val_len, 1);
|
||||
ztest_expect_data(settings_save_one, value, enable_val);
|
||||
} else {
|
||||
ztest_expect_data(settings_delete, name, "bt/mesh/brg_en");
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
ztest_expect_data(settings_save_one, name, "bt/mesh/brg_tbl");
|
||||
ztest_expect_value(settings_save_one, val_len,
|
||||
n * sizeof(struct bt_mesh_brg_cfg_row));
|
||||
ztest_expect_data(settings_save_one, value, tbl_val);
|
||||
} else {
|
||||
ztest_expect_data(settings_delete, name, "bt/mesh/brg_tbl");
|
||||
}
|
||||
}
|
||||
|
||||
/* Test if enable flag is stored correctly. */
|
||||
ZTEST(bt_mesh_brg_cfg, test_brg_cfg_en)
|
||||
{
|
||||
int err;
|
||||
int n;
|
||||
bool val;
|
||||
const struct bt_mesh_brg_cfg_row *tbl;
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
val = bt_mesh_brg_cfg_enable_get();
|
||||
n = bt_mesh_brg_cfg_tbl_get(&tbl);
|
||||
zassert_equal(val, false, NULL);
|
||||
pending_store_enable_create_expectations(&val, n, tbl);
|
||||
bt_mesh_brg_cfg_pending_store();
|
||||
|
||||
|
||||
ztest_expect_value(bt_mesh_settings_store_schedule, flag,
|
||||
BT_MESH_SETTINGS_BRG_PENDING);
|
||||
err = bt_mesh_brg_cfg_enable_set(true);
|
||||
zassert_equal(err, 0, NULL);
|
||||
val = bt_mesh_brg_cfg_enable_get();
|
||||
n = bt_mesh_brg_cfg_tbl_get(&tbl);
|
||||
pending_store_enable_create_expectations(&val, n, tbl);
|
||||
bt_mesh_brg_cfg_pending_store();
|
||||
|
||||
zassert_equal(bt_mesh_brg_cfg_enable_get(), true, NULL);
|
||||
}
|
||||
|
||||
/* Test if pending store works correctly by adding one entry to the table. */
|
||||
ZTEST(bt_mesh_brg_cfg, test_brg_tbl_pending_store)
|
||||
{
|
||||
int n, err;
|
||||
bool b_en;
|
||||
struct bt_mesh_brg_cfg_row test_vec = {
|
||||
.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 1,
|
||||
.net_idx2 = 2,
|
||||
.addr1 = 3,
|
||||
.addr2 = 4,
|
||||
};
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
ztest_expect_value(bt_mesh_settings_store_schedule, flag,
|
||||
BT_MESH_SETTINGS_BRG_PENDING);
|
||||
err = bt_mesh_brg_cfg_tbl_add(test_vec.direction, test_vec.net_idx1,
|
||||
test_vec.net_idx2, test_vec.addr1, test_vec.addr2);
|
||||
zassert_equal(err, 0);
|
||||
|
||||
const struct bt_mesh_brg_cfg_row *tbl;
|
||||
|
||||
n = bt_mesh_brg_cfg_tbl_get(&tbl);
|
||||
b_en = bt_mesh_brg_cfg_enable_get();
|
||||
|
||||
zassert_equal(n, 1);
|
||||
zassert_true(tbl);
|
||||
|
||||
pending_store_enable_create_expectations(&b_en, 1, &test_vec);
|
||||
bt_mesh_brg_cfg_pending_store();
|
||||
}
|
||||
|
||||
/* Test if invalid entries are not added to the table. */
|
||||
ZTEST(bt_mesh_brg_cfg, test_tbl_add_invalid_ip)
|
||||
{
|
||||
int err;
|
||||
/* Create test vector array of test_brg_cfg_row iteams with invalid values.
|
||||
* Each vector has only one invalid field value, rest all are valid values.
|
||||
*/
|
||||
const struct test_brg_cfg_row inv_test_vector[] = {
|
||||
/* Direction has invalid values */
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_PROHIBITED,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 2},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_MAX,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 2},
|
||||
/* Out of range netidx values */
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 4096, .net_idx2 = 1, .addr1 = 1, .addr2 = 2},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 4096, .addr1 = 1, .addr2 = 2},
|
||||
/* Same netidx values */
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 0, .addr1 = 1, .addr2 = 2},
|
||||
/* Same addr values */
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 1},
|
||||
/* Invalid address1 value */
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 0, .addr2 = 1},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 0x8000, .addr2 = 1},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 0xC000, .addr2 = 1},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 0xFFFE, .addr2 = 1},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 0xFFFF, .addr2 = 1},
|
||||
/* Invalid address2 values */
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 0},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 0xFFFF},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_TWOWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 0x8000},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_TWOWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 0xC000},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_TWOWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 0xFFFE},
|
||||
{.direction = BT_MESH_BRG_CFG_DIR_TWOWAY,
|
||||
.net_idx1 = 0, .net_idx2 = 1, .addr1 = 1, .addr2 = 0xFFFF},
|
||||
};
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(inv_test_vector); i++) {
|
||||
err = bt_mesh_brg_cfg_tbl_add(inv_test_vector[i].direction,
|
||||
inv_test_vector[i].net_idx1, inv_test_vector[i].net_idx2,
|
||||
inv_test_vector[i].addr1, inv_test_vector[i].addr2);
|
||||
zassert_equal(err, -EINVAL, "Test vector index: %zu", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Following are helper functions for the test that checks the iteration logic */
|
||||
#define NUM_MSGS (10000)
|
||||
|
||||
static void print_brg_tbl(void)
|
||||
{
|
||||
const struct bt_mesh_brg_cfg_row *tbl;
|
||||
int n = bt_mesh_brg_cfg_tbl_get(&tbl);
|
||||
|
||||
zassert_true(n <= CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX);
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
printk("entry: %3d # dir: %d, net_idx1: %3d, addr1: %3d, net_idx2: %3d, addr2: %3d\n",
|
||||
i, tbl[i].direction, tbl[i].net_idx1, tbl[i].addr1, tbl[i].net_idx2,
|
||||
tbl[i].addr2);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_fill_all_bt_entries_reversed(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
for (int i = TEST_VECT_SZ - 2; i >= 0 ; i--) {
|
||||
ztest_expect_value(bt_mesh_settings_store_schedule, flag,
|
||||
BT_MESH_SETTINGS_BRG_PENDING);
|
||||
err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction, test_vector[i].net_idx1,
|
||||
test_vector[i].net_idx2, test_vector[i].addr1, test_vector[i].addr2);
|
||||
zassert_equal(err, 0);
|
||||
}
|
||||
|
||||
int last = TEST_VECT_SZ - 1;
|
||||
|
||||
err = bt_mesh_brg_cfg_tbl_add(test_vector[last].direction, test_vector[last].net_idx1,
|
||||
test_vector[last].net_idx2, test_vector[last].addr1, test_vector[last].addr2);
|
||||
zassert_equal(err, -ENOMEM);
|
||||
}
|
||||
|
||||
static struct test_brg_cfg_row test_vector_copy[TEST_VECT_SZ - 1];
|
||||
|
||||
static void check_fill_all_bt_entries_randomly(void)
|
||||
{
|
||||
int err;
|
||||
int copy_cnt = ARRAY_SIZE(test_vector_copy);
|
||||
|
||||
memcpy(test_vector_copy, test_vector, sizeof(test_vector_copy));
|
||||
|
||||
for (int i = 0; i < copy_cnt; i++) {
|
||||
int idx = rand() % copy_cnt;
|
||||
struct test_brg_cfg_row tmp = test_vector_copy[i];
|
||||
|
||||
test_vector_copy[i] = test_vector_copy[idx];
|
||||
test_vector_copy[idx] = tmp;
|
||||
}
|
||||
|
||||
for (int i = 0; i < copy_cnt; i++) {
|
||||
ztest_expect_value(bt_mesh_settings_store_schedule, flag,
|
||||
BT_MESH_SETTINGS_BRG_PENDING);
|
||||
err = bt_mesh_brg_cfg_tbl_add(test_vector_copy[i].direction,
|
||||
test_vector_copy[i].net_idx1, test_vector_copy[i].net_idx2,
|
||||
test_vector_copy[i].addr1, test_vector_copy[i].addr2);
|
||||
zassert_equal(err, 0);
|
||||
}
|
||||
|
||||
int last = TEST_VECT_SZ - 1;
|
||||
|
||||
err = bt_mesh_brg_cfg_tbl_add(test_vector[last].direction, test_vector[last].net_idx1,
|
||||
test_vector[last].net_idx2, test_vector[last].addr1, test_vector[last].addr2);
|
||||
zassert_equal(err, -ENOMEM);
|
||||
}
|
||||
|
||||
static void subnet_relay_cb_check(uint16_t new_net_idx, void *user_data)
|
||||
{
|
||||
int idx = *(int *)user_data;
|
||||
|
||||
zassert_equal(new_net_idx, test_vector[idx].net_idx2);
|
||||
}
|
||||
|
||||
static void subnet_relay_cb_check_rev(uint16_t new_net_idx, void *user_data)
|
||||
{
|
||||
int idx = *(int *)user_data;
|
||||
|
||||
if (test_vector[idx].direction == 2) {
|
||||
zassert_equal(new_net_idx, test_vector[idx].net_idx1);
|
||||
} else {
|
||||
/* Should never assert. Test vector created in setup(). */
|
||||
zassert_true(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_bridging_performance(bool test_one_way)
|
||||
{
|
||||
int idx;
|
||||
uint32_t tick1;
|
||||
uint32_t ticks = 0;
|
||||
|
||||
for (int i = 0; i < NUM_MSGS; i++) {
|
||||
/* randomly pick an entry from the test vector */
|
||||
idx = rand() % TEST_VECT_SZ;
|
||||
|
||||
/* check src to dst bridging*/
|
||||
const struct bt_mesh_brg_cfg_row *tbl_row = NULL;
|
||||
|
||||
tick1 = k_uptime_ticks();
|
||||
bt_mesh_brg_cfg_tbl_foreach_subnet(test_vector[idx].addr1, test_vector[idx].addr2,
|
||||
test_vector[idx].net_idx1, subnet_relay_cb_check, &idx);
|
||||
ticks += k_uptime_ticks() - tick1;
|
||||
|
||||
if (test_one_way) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check dst to src bridging - for the same test vector src-dst pairs
|
||||
* but now, reverse them and consider packets are arriving on net_idx2
|
||||
*/
|
||||
tbl_row = NULL;
|
||||
tick1 = k_uptime_ticks();
|
||||
bt_mesh_brg_cfg_tbl_foreach_subnet(test_vector[idx].addr2, test_vector[idx].addr1,
|
||||
test_vector[idx].net_idx2, subnet_relay_cb_check_rev, &idx);
|
||||
ticks += k_uptime_ticks() - tick1;
|
||||
}
|
||||
printk("ticks: %8u us: %u\n", ticks, k_ticks_to_us_floor32(ticks));
|
||||
}
|
||||
|
||||
/* Test checks iteration logic and performance when run on real devices. */
|
||||
ZTEST(bt_mesh_brg_cfg, test_zcheck_entry_randomly_sorting)
|
||||
{
|
||||
printk("num msgs: %d\n\n", NUM_MSGS);
|
||||
|
||||
/* Test performance when packets are flowing in one directions */
|
||||
/* Fill bridging table in sorted order */
|
||||
printk("\n\nPackets going only in one direction (from outside towards the subnet)\n");
|
||||
printk("\nBridging table is pre-filled in sorted order\n");
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries();
|
||||
print_brg_tbl();
|
||||
test_bridging_performance(true);
|
||||
|
||||
/* Fill bridging table in reversed order */
|
||||
printk("\nBridging table is pre-filled in reversed order\n");
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries_reversed();
|
||||
print_brg_tbl();
|
||||
test_bridging_performance(true);
|
||||
|
||||
/* Fill bridging table in random order */
|
||||
printk("\nBridging table is pre-filled in random order\n");
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries_randomly();
|
||||
print_brg_tbl();
|
||||
test_bridging_performance(true);
|
||||
|
||||
/* Test performance when packets are flowing in both directions - use same dataset. */
|
||||
printk("\n\nPackets going in both directions (same data set, flip src and dst pairs)\n");
|
||||
printk("\nBridging table is pre-filled in sorted order\n");
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries();
|
||||
print_brg_tbl();
|
||||
test_bridging_performance(false);
|
||||
|
||||
/* Fill bridging table in reversed order */
|
||||
printk("\nBridging table is pre-filled in reversed order\n");
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries_reversed();
|
||||
print_brg_tbl();
|
||||
test_bridging_performance(false);
|
||||
|
||||
/* Fill bridging table in random order */
|
||||
printk("\nBridging table is pre-filled in random order\n");
|
||||
|
||||
check_bt_mesh_brg_cfg_tbl_reset();
|
||||
check_fill_all_bt_entries_randomly();
|
||||
print_brg_tbl();
|
||||
test_bridging_performance(false);
|
||||
}
|
10
tests/bluetooth/mesh/brg/testcase.yaml
Normal file
10
tests/bluetooth/mesh/brg/testcase.yaml
Normal file
|
@ -0,0 +1,10 @@
|
|||
tests:
|
||||
bluetooth.mesh.brg:
|
||||
platform_allow:
|
||||
- native_posix
|
||||
- native_sim
|
||||
tags:
|
||||
- bluetooth
|
||||
- mesh
|
||||
integration_platforms:
|
||||
- native_sim
|
Loading…
Add table
Add a link
Reference in a new issue