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:
parent
6c67ab3a63
commit
f70929a8f1
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue