tests: Bluetooth: Mesh: Add proxy adv coex test.

Adds test that verifies correct Proxy advertisement behavior for
a device where the Proxy adv requirements changes over time,
both for single and multiple subnets.

Signed-off-by: Anders Storrø <anders.storro@nordicsemi.no>
This commit is contained in:
Anders Storrø 2023-12-06 13:59:39 +01:00 committed by Carles Cufí
parent 6c67ab3a63
commit f70929a8f1
4 changed files with 397 additions and 35 deletions

View file

@ -712,6 +712,13 @@ static bool proxy_adv_request_get(struct bt_mesh_subnet *sub, struct proxy_adv_r
return false;
}
/** The priority for proxy adv is first solicitation, then Node Identity,
* and lastly Network ID. Network ID is prioritized last since, in many
* cases, another device can fulfill the same demand. Solicitation is
* prioritized first since legacy devices are dependent on this to
* connect to the network.
*/
#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
if (bt_mesh_od_priv_proxy_get() > 0 && sub->solicited) {
int32_t timeout = MSEC_PER_SEC * (int32_t)bt_mesh_od_priv_proxy_get();
@ -753,7 +760,7 @@ static bool proxy_adv_request_get(struct bt_mesh_subnet *sub, struct proxy_adv_r
static struct bt_mesh_subnet *adv_sub_get_next(struct bt_mesh_subnet *sub_start,
struct proxy_adv_request *request)
{
struct bt_mesh_subnet *sub_temp = sub_start;
struct bt_mesh_subnet *sub_temp = bt_mesh_subnet_next(sub_start);
do {
if (proxy_adv_request_get(sub_temp, request)) {
@ -823,7 +830,7 @@ static int gatt_proxy_advertise(void)
}
}
sub = adv_sub_get_next(bt_mesh_subnet_next(sub_adv.sub), &request);
sub = adv_sub_get_next(sub_adv.sub, &request);
if (!sub) {
LOG_ERR("Could not find subnet to advertise");
return -ENOENT;

View file

@ -6,3 +6,4 @@ CONFIG_BT_MESH_LOW_POWER=n
CONFIG_BT_MESH_FRIEND=n
CONFIG_BT_CENTRAL=y
CONFIG_BT_MESH_PROXY_CLIENT=y
CONFIG_BT_MESH_PROXY_SOLICITATION=y

View file

@ -31,7 +31,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF);
#define BEACON_TYPE_PRIVATE 0x02
#endif
static uint8_t test_net_key_secondary[16] = { 0xca, 0x11, 0xab, 0x1e };
static uint8_t test_net_key_2[16] = { 0xca, 0x11, 0xab, 0x1e };
static struct {
uint8_t primary[16];
uint8_t secondary[16];
@ -334,6 +334,7 @@ static struct {
uint8_t random[13];
uint64_t pp_hash;
uint64_t pp_random;
uint64_t net_id;
bt_addr_le_t adv_addr;
#endif
bool (*process_cb)(const uint8_t *net_id, void *ctx);
@ -625,7 +626,7 @@ static void test_tx_kr_old_key(void)
* the new Net Key. The node shall set Key Refresh phase to 2. The beacon interval shall
* be increased.
*/
beacon_create(&buf, test_net_key_secondary, 0x03, 0x0001);
beacon_create(&buf, test_net_key_2, 0x03, 0x0001);
send_beacon(&buf);
ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL));
ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL));
@ -645,7 +646,7 @@ static void test_tx_kr_old_key(void)
/* Try the same with the new Net Key. Now the node shall change Key Refresh phase to 0. The
* beacon interval shall be increased.
*/
beacon_create(&buf, test_net_key_secondary, 0x02, 0x0001);
beacon_create(&buf, test_net_key_2, 0x02, 0x0001);
send_beacon(&buf);
ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL));
ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL));
@ -665,7 +666,7 @@ static void test_tx_kr_old_key(void)
/* Do the same, but secure beacon with the new Net Key. Now the node shall change IV Update
* flag to 0. The beacon interval shall be increased.
*/
beacon_create(&buf, test_net_key_secondary, 0x00, 0x0001);
beacon_create(&buf, test_net_key_2, 0x00, 0x0001);
send_beacon(&buf);
ASSERT_FALSE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL));
ASSERT_TRUE(wait_for_beacon(beacon_scan_cb, BEACON_INTERVAL + 1, NULL, NULL));
@ -686,7 +687,7 @@ static void test_rx_kr_old_key(void)
bt_mesh_test_setup();
bt_mesh_iv_update_test(true);
err = bt_mesh_cfg_cli_net_key_update(0, cfg->addr, 0, test_net_key_secondary, &status);
err = bt_mesh_cfg_cli_net_key_update(0, cfg->addr, 0, test_net_key_2, &status);
if (err || status) {
FAIL("Net Key update failed (err %d, status %u)", err, status);
}
@ -1541,60 +1542,73 @@ static void test_tx_priv_beacon_cache(void)
#if IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)
static uint8_t test_net_key_3[16] = {0x12, 0x54, 0xab, 0x1e};
#define UNTIL_UPTIME(time) (k_uptime_get() > (time) ? K_NO_WAIT : K_MSEC((time) - k_uptime_get()))
#define BEACON_TYPE_NET_ID 0
#define BEACON_TYPE_NODE_ID 1
#define BEACON_TYPE_PRIVATE_NET_ID 2
#define BEACON_TYPE_PRIVATE_NODE_ID 3
#define BEACON_TYPE_PRIVATE_LEN 28
#define TEST_NET_IDX1 0
#define TEST_NET_IDX2 1
#define TEST_NET_IDX3 2
#define MAX_TIMEOUT ((CONFIG_BT_MESH_NODE_ID_TIMEOUT * 1000) / 6)
#define PP_NET_ID_WAIT_TIME 610 /*seconds*/
#define PP_NODE_ID_WAIT_TIME 80 /*seconds*/
#define PP_MULT_NET_ID_WAIT_TIME 50 /*seconds*/
#define PROXY_ADV_MULTI_SUBNET_COEX_WAIT_TIME 151 /*seconds*/
struct pp_netkey_ctx {
struct netkey_ctx {
uint8_t *net_key;
uint8_t net_id[8];
uint8_t net_idx;
struct bt_mesh_key id_key;
};
static struct pp_netkey_ctx pp_net0 = {.net_key = (uint8_t *)test_net_key};
static struct pp_netkey_ctx pp_net1 = {.net_key = (uint8_t *)test_net_key_secondary};
static struct netkey_ctx pp_net0 = {.net_key = (uint8_t *)test_net_key, .net_idx = 0};
static struct netkey_ctx pp_net1 = {.net_key = (uint8_t *)test_net_key_2, .net_idx = 1};
static struct netkey_ctx pp_net2 = {.net_key = (uint8_t *)test_net_key_3, .net_idx = 2};
struct priv_test_ctx {
uint8_t beacon_type;
uint16_t *node_id_addr;
};
static void pp_netkey_ctx_init(struct pp_netkey_ctx *net)
static void pp_netkey_ctx_init(struct netkey_ctx *net)
{
ASSERT_OK_MSG(bt_mesh_identity_key(net->net_key, &net->id_key),
"Failed to generate ID key");
ASSERT_OK_MSG(bt_mesh_k3(net->net_key, net->net_id), "Failed to generate Net ID");
}
static bool pp_type_check(uint16_t expected_beacon, uint8_t adv_type, struct net_buf_simple *buf)
static uint8_t proxy_adv_type_get(uint8_t adv_type, struct net_buf_simple *buf)
{
if (adv_type != BT_GAP_ADV_TYPE_ADV_IND || buf->len != BEACON_TYPE_PRIVATE_LEN) {
return false;
uint8_t type;
uint8_t len = buf->len;
if (adv_type != BT_GAP_ADV_TYPE_ADV_IND || len < 12) {
return 0xFF;
}
/* Remove Header */
(void)net_buf_simple_pull_mem(buf, 11);
uint8_t beacon_type = net_buf_simple_pull_u8(buf);
if (beacon_type != expected_beacon) {
return false;
type = net_buf_simple_pull_u8(buf);
/* BEACON_TYPE_NET_ID is 20 bytes long, while the three other accepted types are 28 bytes*/
if (len != ((type == BEACON_TYPE_NET_ID) ? 20 : 28)) {
return 0xFF;
}
return true;
return type;
}
static uint64_t pp_hash_calc(struct pp_netkey_ctx *net, uint64_t random, uint16_t *addr)
static uint64_t proxy_adv_hash_calc(struct netkey_ctx *net, uint64_t random, uint16_t *addr,
bool is_priv)
{
uint64_t hash;
uint8_t tmp[16] = {0, 0, 0, 0, 0, 3};
uint8_t tmp[16] = {0};
tmp[5] = is_priv ? 3 : 0;
if (addr) {
memcpy(&tmp[6], &random, 8);
@ -1616,7 +1630,7 @@ static bool pp_beacon_check(const uint8_t *net_id, void *ctx)
struct priv_test_ctx *test_ctx = (struct priv_test_ctx *)ctx;
ASSERT_EQUAL(beacon.pp_hash,
pp_hash_calc(&pp_net0, beacon.pp_random, test_ctx->node_id_addr));
proxy_adv_hash_calc(&pp_net0, beacon.pp_random, test_ctx->node_id_addr, true));
if (memcmp(beacon.adv_addr.a.val, last_beacon_adv_addr.a.val, BT_ADDR_SIZE) == 0) {
return false;
@ -1632,15 +1646,58 @@ static void priv_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type
{
struct priv_test_ctx *ctx = (struct priv_test_ctx *)beacon.user_ctx;
if (!pp_type_check(ctx->beacon_type, adv_type, buf)) {
if (proxy_adv_type_get(adv_type, buf) != ctx->beacon_type) {
/* Wrong message type */
return;
}
bt_addr_le_copy(&beacon.adv_addr, addr);
beacon.pp_hash = net_buf_simple_pull_le64(buf);
beacon.pp_random = net_buf_simple_pull_le64(buf);
if (ctx->beacon_type == BEACON_TYPE_NET_ID) {
beacon.net_id = net_buf_simple_pull_le64(buf);
} else {
beacon.pp_hash = net_buf_simple_pull_le64(buf);
beacon.pp_random = net_buf_simple_pull_le64(buf);
}
if (!beacon.process_cb || beacon.process_cb(NULL, beacon.user_ctx)) {
k_sem_give(&observer_sem);
}
}
struct proxy_adv_beacon {
uint8_t evt_type;
uint8_t net_idx;
int64_t rx_timestamp;
union {
uint64_t net_id;
struct {
uint64_t hash;
uint64_t random;
} enc;
} ctx;
};
static void proxy_adv_scan_all_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
struct net_buf_simple *buf)
{
struct proxy_adv_beacon *beac = (struct proxy_adv_beacon *)beacon.user_ctx;
beac->evt_type = proxy_adv_type_get(adv_type, buf);
if (beac->evt_type == 0xFF) {
/* Not a related beacon type */
return;
}
bt_addr_le_copy(&beacon.adv_addr, addr);
beac->rx_timestamp = k_uptime_get();
if (beac->evt_type == BEACON_TYPE_NET_ID) {
beac->ctx.net_id = net_buf_simple_pull_le64(buf);
} else {
beac->ctx.enc.hash = net_buf_simple_pull_le64(buf);
beac->ctx.enc.random = net_buf_simple_pull_le64(buf);
}
if (!beacon.process_cb || beacon.process_cb(NULL, beacon.user_ctx)) {
k_sem_give(&observer_sem);
@ -1656,11 +1713,11 @@ static void rx_priv_common_init(uint16_t wait)
ASSERT_OK_MSG(bt_enable(NULL), "Bluetooth init failed");
}
static void tx_priv_common_init(uint16_t wait)
static void tx_proxy_adv_common_init(uint16_t wait, const struct bt_mesh_test_cfg *cfg)
{
bt_mesh_test_cfg_set(NULL, wait);
bt_mesh_device_setup(&prov, &prb_comp);
provision(&tx_cfg);
provision(cfg);
/* Disable GATT proxy */
ASSERT_OK_MSG(bt_mesh_gatt_proxy_set(BT_MESH_GATT_PROXY_DISABLED),
@ -1669,7 +1726,7 @@ static void tx_priv_common_init(uint16_t wait)
static void test_tx_priv_net_id(void)
{
tx_priv_common_init(PP_NET_ID_WAIT_TIME);
tx_proxy_adv_common_init(PP_NET_ID_WAIT_TIME, &tx_cfg);
/* Enable private GATT proxy */
ASSERT_OK_MSG(bt_mesh_priv_gatt_proxy_set(BT_MESH_GATT_PROXY_ENABLED),
@ -1708,7 +1765,7 @@ static void test_tx_priv_node_id(void)
{
enum bt_mesh_feat_state state;
tx_priv_common_init(PP_NODE_ID_WAIT_TIME);
tx_proxy_adv_common_init(PP_NODE_ID_WAIT_TIME, &tx_cfg);
/* Start first node advertisement */
ASSERT_OK_MSG(bt_mesh_subnet_priv_node_id_set(TEST_NET_IDX1, BT_MESH_NODE_IDENTITY_RUNNING),
@ -1761,10 +1818,10 @@ static void test_rx_priv_node_id(void)
static void test_tx_priv_multi_net_id(void)
{
tx_priv_common_init(PP_MULT_NET_ID_WAIT_TIME);
tx_proxy_adv_common_init(PP_MULT_NET_ID_WAIT_TIME, &tx_cfg);
/* Add second network */
ASSERT_OK_MSG(bt_mesh_subnet_add(TEST_NET_IDX2, test_net_key_secondary),
ASSERT_OK_MSG(bt_mesh_subnet_add(TEST_NET_IDX2, test_net_key_2),
"Failed to add second subnet");
/* Enable private GATT proxy */
@ -1774,6 +1831,246 @@ static void test_tx_priv_multi_net_id(void)
PASS();
}
static void proxy_adv_subnet_find(struct proxy_adv_beacon *beac, struct netkey_ctx **nets,
uint8_t net_cnt)
{
for (size_t i = 0; i < net_cnt; i++) {
switch (beac->evt_type) {
case BEACON_TYPE_NET_ID:
if (!memcmp(nets[i]->net_id, &beac->ctx.net_id, 8)) {
beac->net_idx = nets[i]->net_idx;
return;
}
break;
case BEACON_TYPE_NODE_ID:
if (beac->ctx.enc.hash ==
proxy_adv_hash_calc(nets[i], beac->ctx.enc.random,
(uint16_t *)&tx_cfg.addr, false)) {
beac->net_idx = nets[i]->net_idx;
return;
}
break;
case BEACON_TYPE_PRIVATE_NET_ID:
if (beac->ctx.enc.hash ==
proxy_adv_hash_calc(nets[i], beac->ctx.enc.random,
NULL, true)) {
beac->net_idx = nets[i]->net_idx;
return;
}
break;
case BEACON_TYPE_PRIVATE_NODE_ID:
if (beac->ctx.enc.hash ==
proxy_adv_hash_calc(nets[i], beac->ctx.enc.random,
(uint16_t *)&tx_cfg.addr, true)) {
beac->net_idx = nets[i]->net_idx;
return;
}
break;
default:
FAIL("Unexpected beacon type");
break;
}
}
FAIL("Could not find matching subnet for incoming proxy adv beacon");
}
static const char *const proxy_adv_str[] = {"Net_ID", "Node_ID", "Priv_Net_ID", "Priv_Node_ID"};
struct expected_proxy_adv_evt {
uint8_t evt_type;
uint8_t net_idx;
uint16_t evt_cnt;
struct {
int64_t after;
int64_t before;
} time;
};
static void proxy_adv_register_evt(struct proxy_adv_beacon *beac,
struct expected_proxy_adv_evt *exp_evts, uint8_t cnt)
{
for (int i = 0; i < cnt; i++) {
if ((exp_evts[i].evt_cnt) && (beac->evt_type == exp_evts[i].evt_type) &&
(beac->net_idx == exp_evts[i].net_idx) &&
(beac->rx_timestamp >= exp_evts[i].time.after) &&
(beac->rx_timestamp <= exp_evts[i].time.before)) {
exp_evts[i].evt_cnt--;
}
}
}
static void proxy_adv_confirm_evt(struct expected_proxy_adv_evt *exp_evts, uint8_t cnt)
{
bool missing_evts = false;
for (int i = 0; i < cnt; i++) {
if (exp_evts[i].evt_cnt) {
LOG_ERR("Missing %d expected %s events in period %llums-%llums",
exp_evts[i].evt_cnt, proxy_adv_str[exp_evts[i].evt_type],
exp_evts[i].time.after, exp_evts[i].time.before);
missing_evts = true;
}
}
if (missing_evts) {
FAIL("Test failed due to missing events");
}
}
static void proxy_adv_scan_all(struct netkey_ctx **nets, uint16_t net_cnt,
struct expected_proxy_adv_evt *exp_evt, uint16_t exp_evt_cnt,
int64_t timeout)
{
struct proxy_adv_beacon beac;
while (k_uptime_get() < timeout) {
ASSERT_TRUE(wait_for_beacon(proxy_adv_scan_all_cb, 2, NULL, &beac));
proxy_adv_subnet_find(&beac, nets, net_cnt);
proxy_adv_register_evt(&beac, exp_evt, exp_evt_cnt);
/** We want to monitor an even distribution of adv events.
* To ensure this, we wait a little less than the minimum
* proxy adv period (1 second) before scanning for the next
* evt.
*/
k_sleep(K_MSEC(990));
}
proxy_adv_confirm_evt(exp_evt, exp_evt_cnt);
}
#define PROXY_ADV_MULTI_CHECKPOINT_1 20000
#define PROXY_ADV_MULTI_CHECKPOINT_2 50000
#define PROXY_ADV_MULTI_CHECKPOINT_3 110000
#define PROXY_ADV_MULTI_CHECKPOINT_4 130000
#define PROXY_ADV_MULTI_CHECKPOINT_END 150000
static void test_tx_proxy_adv_multi_subnet_coex(void)
{
tx_proxy_adv_common_init(PROXY_ADV_MULTI_SUBNET_COEX_WAIT_TIME, &tx_cfg);
/* Enable GATT proxy */
ASSERT_OK_MSG(bt_mesh_gatt_proxy_set(BT_MESH_GATT_PROXY_ENABLED),
"Failed to Enable gatt proxy");
k_sleep(UNTIL_UPTIME(PROXY_ADV_MULTI_CHECKPOINT_1));
/* Add second and third network */
ASSERT_OK_MSG(bt_mesh_subnet_add(TEST_NET_IDX2, test_net_key_2),
"Failed to add second subnet");
ASSERT_OK_MSG(bt_mesh_subnet_add(TEST_NET_IDX3, test_net_key_3),
"Failed to add third subnet");
k_sleep(UNTIL_UPTIME(PROXY_ADV_MULTI_CHECKPOINT_2));
/* Start Node Identity on second network */
bt_mesh_proxy_identity_start(bt_mesh_subnet_get(TEST_NET_IDX2), false);
k_sleep(UNTIL_UPTIME(PROXY_ADV_MULTI_CHECKPOINT_3));
/* Prepare for solicitation */
ASSERT_OK_MSG(bt_mesh_gatt_proxy_set(BT_MESH_GATT_PROXY_DISABLED),
"Failed to Enable gatt proxy");
ASSERT_OK_MSG(bt_mesh_od_priv_proxy_set(20), "Failed to set OD priv proxy state");
k_sleep(UNTIL_UPTIME(PROXY_ADV_MULTI_CHECKPOINT_4));
/* Re-enable GATT proxy and remove second and third network */
ASSERT_OK_MSG(bt_mesh_gatt_proxy_set(BT_MESH_GATT_PROXY_ENABLED),
"Failed to Enable gatt proxy");
ASSERT_OK_MSG(bt_mesh_subnet_del(TEST_NET_IDX2), "Failed to delete subnet");
ASSERT_OK_MSG(bt_mesh_subnet_del(TEST_NET_IDX3), "Failed to delete subnet");
PASS();
}
static const struct bt_mesh_test_cfg solicit_trigger_cfg = {
.addr = 0x0003,
.dev_key = { 0x03 },
};
static void test_tx_proxy_adv_solicit_trigger(void)
{
tx_proxy_adv_common_init(PROXY_ADV_MULTI_SUBNET_COEX_WAIT_TIME, &solicit_trigger_cfg);
ASSERT_OK_MSG(bt_mesh_subnet_add(TEST_NET_IDX2, test_net_key_2),
"Failed to add second subnet");
k_sleep(UNTIL_UPTIME(PROXY_ADV_MULTI_CHECKPOINT_3));
/* Solicit first and second network */
ASSERT_OK_MSG(bt_mesh_proxy_solicit(TEST_NET_IDX1),
"Failed to start solicitation");
ASSERT_OK_MSG(bt_mesh_proxy_solicit(TEST_NET_IDX2),
"Failed to start solicitation");
PASS();
}
static void test_rx_proxy_adv_multi_subnet_coex(void)
{
rx_priv_common_init(PROXY_ADV_MULTI_SUBNET_COEX_WAIT_TIME);
pp_netkey_ctx_init(&pp_net1);
pp_netkey_ctx_init(&pp_net2);
struct netkey_ctx *nets[] = {&pp_net0, &pp_net1, &pp_net2};
struct expected_proxy_adv_evt exp_evt[] = {
/** A single subnet is active on the device with GATT Proxy
* enabled. Verify that the single subnet has exclusive
* access to the adv medium.
*/
{.evt_type = BEACON_TYPE_NET_ID, .net_idx = 0, .evt_cnt = 19,
.time = {.after = 0, .before = PROXY_ADV_MULTI_CHECKPOINT_1}},
/** Two additional subnets are added to the device.
* Check that the subnets are sharing the adv medium,
* advertising NET_ID beacons.
*/
{.evt_type = BEACON_TYPE_NET_ID, .net_idx = 0, .evt_cnt = 8,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_1,
.before = PROXY_ADV_MULTI_CHECKPOINT_2}},
{.evt_type = BEACON_TYPE_NET_ID, .net_idx = 1, .evt_cnt = 8,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_1,
.before = PROXY_ADV_MULTI_CHECKPOINT_2}},
{.evt_type = BEACON_TYPE_NET_ID, .net_idx = 2, .evt_cnt = 8,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_1,
.before = PROXY_ADV_MULTI_CHECKPOINT_2}},
/** The second subnet enables Node Identity. Check that NODE_ID
* is advertised by this subnet, and that the two others
* continues to advertise NET_ID.
*/
{.evt_type = BEACON_TYPE_NET_ID, .net_idx = 0, .evt_cnt = 17,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_2,
.before = PROXY_ADV_MULTI_CHECKPOINT_3}},
{.evt_type = BEACON_TYPE_NODE_ID, .net_idx = 1, .evt_cnt = 17,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_2,
.before = PROXY_ADV_MULTI_CHECKPOINT_3}},
{.evt_type = BEACON_TYPE_NET_ID, .net_idx = 2, .evt_cnt = 17,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_2,
.before = PROXY_ADV_MULTI_CHECKPOINT_3}},
/** The first and second subnet gets solicited. Check that
* PRIVATE_NET_ID is advertised by these subnet,
*/
{.evt_type = BEACON_TYPE_PRIVATE_NET_ID, .net_idx = 0, .evt_cnt = 9,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_3,
.before = PROXY_ADV_MULTI_CHECKPOINT_4}},
{.evt_type = BEACON_TYPE_PRIVATE_NET_ID, .net_idx = 1, .evt_cnt = 9,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_3,
.before = PROXY_ADV_MULTI_CHECKPOINT_4}},
/** Second and third subnet are disabled. Verify that the single
* subnet has exclusive access to the adv medium.
*/
{.evt_type = BEACON_TYPE_NET_ID, .net_idx = 0, .evt_cnt = 19,
.time = {.after = PROXY_ADV_MULTI_CHECKPOINT_4,
.before = PROXY_ADV_MULTI_CHECKPOINT_END}},
};
proxy_adv_scan_all(nets, ARRAY_SIZE(nets), exp_evt, ARRAY_SIZE(exp_evt),
PROXY_ADV_MULTI_CHECKPOINT_END);
PASS();
}
static void test_rx_priv_multi_net_id(void)
{
rx_priv_common_init(PP_MULT_NET_ID_WAIT_TIME);
@ -1787,7 +2084,7 @@ static void test_rx_priv_multi_net_id(void)
uint16_t itr = 4;
static uint8_t old_idx = 0xff;
static struct {
struct pp_netkey_ctx *net;
struct netkey_ctx *net;
uint16_t recv_cnt;
int64_t start;
} net_ctx[2] = {
@ -1802,7 +2099,7 @@ static void test_rx_priv_multi_net_id(void)
for (size_t i = 0; i < ARRAY_SIZE(net_ctx); i++) {
if (beacon.pp_hash ==
pp_hash_calc(net_ctx[i].net, beacon.pp_random, NULL)) {
proxy_adv_hash_calc(net_ctx[i].net, beacon.pp_random, NULL, true)) {
if (old_idx == 0xff) {
/* Received first Net ID advertisment */
old_idx = i;
@ -1931,6 +2228,8 @@ static const struct bst_test_instance test_beacon[] = {
TEST_CASE(tx, priv_node_id, "Private Proxy: advertise Node ID"),
TEST_CASE(tx, priv_multi_net_id, "Private Proxy: advertise multiple Net ID"),
TEST_CASE(tx, priv_gatt_proxy, "Private Proxy: Send Private Beacons over GATT"),
TEST_CASE(tx, proxy_adv_multi_subnet_coex, "Proxy Adv: Multi subnet coex proxy adv"),
TEST_CASE(tx, proxy_adv_solicit_trigger, "Proxy Adv: Trigger Solicitation"),
#endif
#endif
@ -1951,6 +2250,7 @@ static const struct bst_test_instance test_beacon[] = {
TEST_CASE(rx, priv_node_id, "Private Proxy: scan for Node ID"),
TEST_CASE(rx, priv_multi_net_id, "Private Proxy: scan for multiple Net ID"),
TEST_CASE(rx, priv_gatt_proxy, "Private Proxy: Receive Private Beacons over GATT"),
TEST_CASE(rx, proxy_adv_multi_subnet_coex, "Proxy Adv: Multi subnet coex proxy adv"),
#endif
#endif
BSTEST_END_MARKER

View file

@ -0,0 +1,54 @@
#!/usr/bin/env bash
# Copyright 2023 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0
source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh
# Test Proxy advertisement Coex
# This test verifies correct Proxy advertisement behavior for a device
# where the Proxy adv requirements changes over time, both for single
# and multiple subnets. The TX device is the DUT in this instance, while
# the RX device scans and verifies that the correct proxy adv messages of
# the different subnets is sent within the expected time delta.
# Note 1: The maximum allowed timeslot for a subnet to advertise proxy
# in this scenario is 10 seconds when there is more than one subnet that
# has active proxy adv work. This is reflected in the scanning criteria
# on the RX device.
# Note 2: The expected message received count for each event is based on
# what would be a reasonable/acceptable to receive within a given time
# window. The Mesh Protocol specification does not specify exactly the
# timing for Proxy ADV messages.
# Test procedure:
# 1. (0-20 seconds) A single subnet is active on the TX device with GATT
# Proxy enabled. RX device verifies that the single subnet has exclusive
# access to the adv medium.
# 2. (20-50 seconds) Two additional subnets are added to the TX device. RX
# device checks that the subnets are sharing the adv medium, advertising
# NET_ID beacons.
# 3. (50-110 seconds) The second subnet enables Node Identity. RX device
# checks that NODE_ID is advertised by this subnet, and that the two
# others continues to advertise NET_ID.
# 4. (110-130 seconds) The first and second subnet gets solicited. RX device
# checks that PRIVATE_NET_ID is advertised by these subnets.
# 5. (130-150 seconds) The second and third subnet are disabled on the TX
# device. RX device verifies that the single subnet has exclusive access
# to the adv medium again.
conf=prj_mesh1d1_conf
overlay=overlay_gatt_conf
RunTest proxy_adv_multi_subnet_coex \
beacon_tx_proxy_adv_multi_subnet_coex \
beacon_rx_proxy_adv_multi_subnet_coex \
beacon_tx_proxy_adv_solicit_trigger
conf=prj_mesh1d1_conf
overlay=overlay_gatt_conf_overlay_psa_conf
RunTest proxy_adv_multi_subnet_coex \
beacon_tx_proxy_adv_multi_subnet_coex \
beacon_rx_proxy_adv_multi_subnet_coex \
beacon_tx_proxy_adv_solicit_trigger