Bluetooth: Mesh: Allow sending SNB and PRB in parallel

Private Beacons and Secure Network Beacons are not mutually exclusive by
spec. This means both beacons can be sent simultaneously. For both
beacons spec defines their own observation intervals and related
parameters, which means we need to monitor both beacons types
separately.

Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
Pavel Vasilyev 2023-03-28 13:55:58 +02:00 committed by Carles Cufí
commit c36fdf251f
6 changed files with 174 additions and 90 deletions

View file

@ -56,38 +56,72 @@ static struct {
uint64_t timestamp; uint64_t timestamp;
} priv_random; } priv_random;
struct beacon_params {
bool private;
union {
const uint8_t *net_id;
struct {
const uint8_t *data;
const uint8_t *random;
};
};
const uint8_t *auth;
uint32_t iv_index;
uint8_t flags;
bool new_key;
};
#if defined(CONFIG_BT_MESH_PRIV_BEACONS) #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
static int private_beacon_create(struct bt_mesh_subnet *sub, static int private_beacon_create(struct bt_mesh_subnet *sub,
struct net_buf_simple *buf); struct net_buf_simple *buf);
static int private_beacon_update(struct bt_mesh_subnet *sub); static int private_beacon_update(struct bt_mesh_subnet *sub);
#endif #endif
static bool beacon_cache_match(struct bt_mesh_subnet *sub, void *auth) static struct bt_mesh_beacon *subnet_beacon_get_by_type(struct bt_mesh_subnet *sub, bool priv)
{ {
return !memcmp(sub->beacon_cache, auth, sizeof(sub->beacon_cache)); #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
return priv ? &sub->priv_beacon : &sub->secure_beacon;
#else
return &sub->secure_beacon;
#endif
} }
static void cache_add(const uint8_t auth[8], struct bt_mesh_subnet *sub) static bool beacon_cache_match(struct bt_mesh_subnet *sub, void *data)
{ {
memcpy(sub->beacon_cache, auth, sizeof(sub->beacon_cache)); struct beacon_params *params;
struct bt_mesh_beacon *beacon;
params = data;
beacon = subnet_beacon_get_by_type(sub, params->private);
return !memcmp(beacon->cache, params->auth, sizeof(beacon->cache));
}
static void cache_add(const uint8_t auth[8], struct bt_mesh_beacon *beacon)
{
memcpy(beacon->cache, auth, sizeof(beacon->cache));
} }
void bt_mesh_beacon_cache_clear(struct bt_mesh_subnet *sub) void bt_mesh_beacon_cache_clear(struct bt_mesh_subnet *sub)
{ {
(void)memset(sub->beacon_cache, 0, sizeof(sub->beacon_cache)); (void)memset(sub->secure_beacon.cache, 0, sizeof(sub->secure_beacon.cache));
#if defined(CONFIG_BT_MESH_PRIV_BEACONS)
(void)memset(sub->priv_beacon.cache, 0, sizeof(sub->priv_beacon.cache));
#endif
} }
static void beacon_complete(int err, void *user_data) static void beacon_complete(int err, void *user_data)
{ {
struct bt_mesh_subnet *sub = user_data; struct bt_mesh_beacon *beacon = user_data;
LOG_DBG("err %d", err); LOG_DBG("err %d", err);
sub->beacon_sent = k_uptime_get_32(); beacon->sent = k_uptime_get_32();
} }
static void secure_beacon_create(struct bt_mesh_subnet *sub, static int secure_beacon_create(struct bt_mesh_subnet *sub,
struct net_buf_simple *buf) struct net_buf_simple *buf)
{ {
uint8_t flags = bt_mesh_net_flags(sub); uint8_t flags = bt_mesh_net_flags(sub);
struct bt_mesh_subnet_keys *keys; struct bt_mesh_subnet_keys *keys;
@ -104,11 +138,13 @@ static void secure_beacon_create(struct bt_mesh_subnet *sub,
/* IV Index */ /* IV Index */
net_buf_simple_add_be32(buf, bt_mesh.iv_index); net_buf_simple_add_be32(buf, bt_mesh.iv_index);
net_buf_simple_add_mem(buf, sub->auth, 8); net_buf_simple_add_mem(buf, sub->secure_beacon.auth, 8);
LOG_DBG("net_idx 0x%04x flags 0x%02x NetID %s", sub->net_idx, flags, LOG_DBG("net_idx 0x%04x flags 0x%02x NetID %s", sub->net_idx, flags,
bt_hex(keys->net_id, 8)); bt_hex(keys->net_id, 8));
LOG_DBG("IV Index 0x%08x Auth %s", bt_mesh.iv_index, bt_hex(sub->auth, 8)); LOG_DBG("IV Index 0x%08x Auth %s", bt_mesh.iv_index, bt_hex(sub->secure_beacon.auth, 8));
return 0;
} }
#if defined(CONFIG_BT_MESH_PRIV_BEACONS) #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
@ -148,13 +184,13 @@ static int private_beacon_update(struct bt_mesh_subnet *sub)
int err; int err;
err = bt_mesh_beacon_encrypt(keys->priv_beacon, flags, bt_mesh.iv_index, err = bt_mesh_beacon_encrypt(keys->priv_beacon, flags, bt_mesh.iv_index,
priv_random.val, sub->priv_beacon.data, priv_random.val, sub->priv_beacon_ctx.data,
sub->auth); sub->priv_beacon.auth);
if (err) { if (err) {
return err; return err;
} }
sub->priv_beacon.idx = priv_random.idx; sub->priv_beacon_ctx.idx = priv_random.idx;
return 0; return 0;
} }
@ -169,7 +205,7 @@ static int private_beacon_create(struct bt_mesh_subnet *sub,
return err; return err;
} }
if (sub->priv_beacon.idx != priv_random.idx) { if (sub->priv_beacon_ctx.idx != priv_random.idx) {
err = private_beacon_update(sub); err = private_beacon_update(sub);
if (err) { if (err) {
return err; return err;
@ -178,8 +214,8 @@ static int private_beacon_create(struct bt_mesh_subnet *sub,
net_buf_simple_add_u8(buf, BEACON_TYPE_PRIVATE); net_buf_simple_add_u8(buf, BEACON_TYPE_PRIVATE);
net_buf_simple_add_mem(buf, priv_random.val, 13); net_buf_simple_add_mem(buf, priv_random.val, 13);
net_buf_simple_add_mem(buf, sub->priv_beacon.data, 5); net_buf_simple_add_mem(buf, sub->priv_beacon_ctx.data, 5);
net_buf_simple_add_mem(buf, sub->auth, 8); net_buf_simple_add_mem(buf, sub->priv_beacon.auth, 8);
LOG_DBG("0x%03x", sub->net_idx); LOG_DBG("0x%03x", sub->net_idx);
return 0; return 0;
@ -200,10 +236,18 @@ int bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
} }
/* If the interval has passed or is within 5 seconds from now send a beacon */ /* If the interval has passed or is within 5 seconds from now send a beacon */
#define BEACON_THRESHOLD(sub) \ #define BEACON_THRESHOLD(beacon) \
((10 * ((sub)->beacons_last + 1)) * MSEC_PER_SEC - (5 * MSEC_PER_SEC)) ((10 * ((beacon)->last + 1)) * MSEC_PER_SEC - (5 * MSEC_PER_SEC))
static bool net_beacon_send(struct bt_mesh_subnet *sub, void *cb_data) static bool secure_beacon_is_running(void)
{
return bt_mesh_beacon_enabled() ||
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR);
}
static bool net_beacon_send(struct bt_mesh_subnet *sub, struct bt_mesh_beacon *beacon,
void *cb_data, int (*beacon_create)(struct bt_mesh_subnet *sub,
struct net_buf_simple *buf))
{ {
static const struct bt_mesh_send_cb send_cb = { static const struct bt_mesh_send_cb send_cb = {
.end = beacon_complete, .end = beacon_complete,
@ -216,10 +260,10 @@ static bool net_beacon_send(struct bt_mesh_subnet *sub, void *cb_data)
LOG_DBG(""); LOG_DBG("");
time_diff = now - sub->beacon_sent; time_diff = now - beacon->sent;
time_since_last_recv = now - sub->beacon_recv; time_since_last_recv = now - beacon->recv;
if (time_diff < (600 * MSEC_PER_SEC) && if (time_diff < (600 * MSEC_PER_SEC) &&
(time_diff < BEACON_THRESHOLD(sub) || (time_diff < BEACON_THRESHOLD(beacon) ||
time_since_last_recv < (10 * MSEC_PER_SEC))) { time_since_last_recv < (10 * MSEC_PER_SEC))) {
return false; return false;
} }
@ -231,15 +275,52 @@ static bool net_beacon_send(struct bt_mesh_subnet *sub, void *cb_data)
return true; /* Bail out */ return true; /* Bail out */
} }
err = bt_mesh_beacon_create(sub, &buf->b); err = beacon_create(sub, &buf->b);
if (err) { if (!err) {
return true; /* Bail out */ bt_mesh_adv_send(buf, &send_cb, beacon);
} }
bt_mesh_adv_send(buf, &send_cb, sub);
net_buf_unref(buf); net_buf_unref(buf);
return false; return err != 0;
}
static bool net_beacon_for_subnet_send(struct bt_mesh_subnet *sub, void *cb_data)
{
bool res = true;
struct {
struct bt_mesh_beacon *beacon;
bool enabled;
int (*create_fn)(struct bt_mesh_subnet *sub, struct net_buf_simple *buf);
} beacons[] = {
[0] = {
.beacon = &sub->secure_beacon,
.enabled = secure_beacon_is_running(),
.create_fn = secure_beacon_create,
},
#if defined(CONFIG_BT_MESH_PRIV_BEACONS)
[1] = {
.beacon = &sub->priv_beacon,
.enabled = bt_mesh_priv_beacon_get() == BT_MESH_FEATURE_ENABLED,
.create_fn = private_beacon_create,
},
#endif
};
for (int i = 0; i < ARRAY_SIZE(beacons); i++) {
if (!beacons[i].enabled) {
continue;
}
res = net_beacon_send(sub, beacons[i].beacon, cb_data, beacons[i].create_fn);
if (res) {
/* Bail out */
break;
}
}
return res;
} }
static int unprovisioned_beacon_send(void) static int unprovisioned_beacon_send(void)
@ -335,8 +416,13 @@ static void unprovisioned_beacon_recv(struct net_buf_simple *buf)
static void sub_update_beacon_observation(struct bt_mesh_subnet *sub) static void sub_update_beacon_observation(struct bt_mesh_subnet *sub)
{ {
sub->beacons_last = sub->beacons_cur; sub->secure_beacon.last = sub->secure_beacon.cur;
sub->beacons_cur = 0U; sub->secure_beacon.cur = 0U;
#if defined(CONFIG_BT_MESH_PRIV_BEACONS)
sub->priv_beacon.last = sub->priv_beacon.cur;
sub->priv_beacon.cur = 0U;
#endif
} }
static void update_beacon_observation(void) static void update_beacon_observation(void)
@ -357,8 +443,7 @@ static void update_beacon_observation(void)
static bool net_beacon_is_running(void) static bool net_beacon_is_running(void)
{ {
return bt_mesh_beacon_enabled() || return secure_beacon_is_running() ||
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) ||
(bt_mesh_priv_beacon_get() == BT_MESH_FEATURE_ENABLED); (bt_mesh_priv_beacon_get() == BT_MESH_FEATURE_ENABLED);
} }
@ -372,7 +457,7 @@ static void beacon_send(struct k_work *work)
} }
update_beacon_observation(); update_beacon_observation();
(void)bt_mesh_subnet_find(net_beacon_send, NULL); (void)bt_mesh_subnet_find(net_beacon_for_subnet_send, NULL);
k_work_schedule(&beacon_timer, PROVISIONED_INTERVAL); k_work_schedule(&beacon_timer, PROVISIONED_INTERVAL);
return; return;
@ -389,21 +474,6 @@ static void beacon_send(struct k_work *work)
} }
struct beacon_params {
union {
const uint8_t *net_id;
struct {
const uint8_t *data;
const uint8_t *random;
} private;
};
const uint8_t *auth;
uint32_t iv_index;
uint8_t flags;
bool new_key;
};
static bool auth_match(struct bt_mesh_subnet_keys *keys, static bool auth_match(struct bt_mesh_subnet_keys *keys,
const struct beacon_params *params) const struct beacon_params *params)
{ {
@ -450,10 +520,8 @@ static bool priv_beacon_decrypt(struct bt_mesh_subnet *sub, void *cb_data)
continue; continue;
} }
err = bt_mesh_beacon_decrypt(sub->keys[i].priv_beacon, err = bt_mesh_beacon_decrypt(sub->keys[i].priv_beacon, params->random,
params->private.random, params->data, params->auth, out);
params->private.data, params->auth,
out);
if (!err) { if (!err) {
params->new_key = (i > 0); params->new_key = (i > 0);
params->flags = out[0]; params->flags = out[0];
@ -465,11 +533,12 @@ static bool priv_beacon_decrypt(struct bt_mesh_subnet *sub, void *cb_data)
return false; return false;
} }
static void net_beacon_register(struct bt_mesh_subnet *sub) static void net_beacon_register(struct bt_mesh_beacon *beacon, bool priv)
{ {
if (bt_mesh_beacon_enabled() && sub->beacons_cur < 0xff) { if (((priv && bt_mesh_priv_beacon_get() == BT_MESH_PRIV_GATT_PROXY_ENABLED) ||
sub->beacons_cur++; bt_mesh_beacon_enabled()) && beacon->cur < 0xff) {
sub->beacon_recv = k_uptime_get_32(); beacon->cur++;
beacon->recv = k_uptime_get_32();
} }
} }
@ -505,11 +574,14 @@ static void net_beacon_resolve(struct beacon_params *params,
void *cb_data)) void *cb_data))
{ {
struct bt_mesh_subnet *sub; struct bt_mesh_subnet *sub;
struct bt_mesh_beacon *beacon;
sub = bt_mesh_subnet_find(beacon_cache_match, (void *)params->auth); sub = bt_mesh_subnet_find(beacon_cache_match, (void *)params);
if (sub) { if (sub) {
beacon = subnet_beacon_get_by_type(sub, params->private);
/* We've seen this beacon before - just update the stats */ /* We've seen this beacon before - just update the stats */
net_beacon_register(sub); net_beacon_register(beacon, params->private);
return; return;
} }
@ -524,10 +596,12 @@ static void net_beacon_resolve(struct beacon_params *params,
return; return;
} }
cache_add(params->auth, sub); beacon = subnet_beacon_get_by_type(sub, params->private);
cache_add(params->auth, beacon);
net_beacon_recv(sub, params); net_beacon_recv(sub, params);
net_beacon_register(sub); net_beacon_register(beacon, params->private);
} }
static void secure_beacon_recv(struct net_buf_simple *buf) static void secure_beacon_recv(struct net_buf_simple *buf)
@ -539,6 +613,7 @@ static void secure_beacon_recv(struct net_buf_simple *buf)
return; return;
} }
params.private = false;
params.flags = net_buf_simple_pull_u8(buf); params.flags = net_buf_simple_pull_u8(buf);
params.net_id = net_buf_simple_pull_mem(buf, 8); params.net_id = net_buf_simple_pull_mem(buf, 8);
params.iv_index = net_buf_simple_pull_be32(buf); params.iv_index = net_buf_simple_pull_be32(buf);
@ -556,8 +631,9 @@ static void private_beacon_recv(struct net_buf_simple *buf)
return; return;
} }
params.private.random = net_buf_simple_pull_mem(buf, 13); params.private = true;
params.private.data = net_buf_simple_pull_mem(buf, 5); params.random = net_buf_simple_pull_mem(buf, 13);
params.data = net_buf_simple_pull_mem(buf, 5);
params.auth = buf->data; params.auth = buf->data;
net_beacon_resolve(&params, priv_beacon_decrypt); net_beacon_resolve(&params, priv_beacon_decrypt);
@ -606,11 +682,11 @@ void bt_mesh_beacon_update(struct bt_mesh_subnet *sub)
#if defined(CONFIG_BT_MESH_PRIV_BEACONS) #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
/* Invalidate private beacon to force regeneration: */ /* Invalidate private beacon to force regeneration: */
sub->priv_beacon.idx = priv_random.idx - 1; sub->priv_beacon_ctx.idx = priv_random.idx - 1;
#endif #endif
bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, bt_mesh.iv_index, bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, bt_mesh.iv_index,
sub->auth); sub->secure_beacon.auth);
} }
static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
@ -651,8 +727,13 @@ void bt_mesh_beacon_ivu_initiator(bool enable)
static void subnet_beacon_enable(struct bt_mesh_subnet *sub) static void subnet_beacon_enable(struct bt_mesh_subnet *sub)
{ {
sub->beacons_last = 0U; sub->secure_beacon.last = 0U;
sub->beacons_cur = 0U; sub->secure_beacon.cur = 0U;
#if defined(CONFIG_BT_MESH_PRIV_BEACONS)
sub->priv_beacon.last = 0U;
sub->priv_beacon.cur = 0U;
#endif
bt_mesh_beacon_update(sub); bt_mesh_beacon_update(sub);
} }

View file

@ -50,7 +50,7 @@ void bt_mesh_beacon_set(bool beacon)
if (beacon) { if (beacon) {
bt_mesh_beacon_enable(); bt_mesh_beacon_enable();
} else { } else {
bt_mesh_beacon_disable(); /* Beacon timer will stop automatically when all beacons are disabled. */
} }
if (IS_ENABLED(CONFIG_BT_SETTINGS) && if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
@ -104,8 +104,8 @@ int bt_mesh_priv_beacon_set(enum bt_mesh_feat_state priv_beacon)
if (priv_beacon == BT_MESH_FEATURE_ENABLED) { if (priv_beacon == BT_MESH_FEATURE_ENABLED) {
bt_mesh_beacon_enable(); bt_mesh_beacon_enable();
} else if (bt_mesh_beacon_enabled()) { } else {
bt_mesh_beacon_disable(); /* Beacon timer will stop automatically when all beacons are disabled. */
} }
if (IS_ENABLED(CONFIG_BT_SETTINGS) && if (IS_ENABLED(CONFIG_BT_SETTINGS) &&

View file

@ -401,9 +401,7 @@ int bt_mesh_suspend(void)
bt_mesh_hb_suspend(); bt_mesh_hb_suspend();
if (bt_mesh_beacon_enabled()) { bt_mesh_beacon_disable();
bt_mesh_beacon_disable();
}
bt_mesh_model_foreach(model_suspend, NULL); bt_mesh_model_foreach(model_suspend, NULL);
@ -444,7 +442,8 @@ int bt_mesh_resume(void)
bt_mesh_hb_resume(); bt_mesh_hb_resume();
if (bt_mesh_beacon_enabled()) { if (bt_mesh_beacon_enabled() ||
bt_mesh_priv_beacon_get() == BT_MESH_PRIV_BEACON_ENABLED) {
bt_mesh_beacon_enable(); bt_mesh_beacon_enable();
} }
@ -511,10 +510,10 @@ int bt_mesh_start(void)
return err; return err;
} }
if (bt_mesh_beacon_enabled()) {
if (bt_mesh_beacon_enabled() ||
bt_mesh_priv_beacon_get() == BT_MESH_PRIV_BEACON_ENABLED) {
bt_mesh_beacon_enable(); bt_mesh_beacon_enable();
} else {
bt_mesh_beacon_disable();
} }
if (!IS_ENABLED(CONFIG_BT_MESH_PROV) || !bt_mesh_prov_active() || if (!IS_ENABLED(CONFIG_BT_MESH_PROV) || !bt_mesh_prov_active() ||

View file

@ -382,7 +382,7 @@ static void identity_enabled(struct bt_mesh_subnet *sub)
static void node_id_start(struct bt_mesh_subnet *sub) static void node_id_start(struct bt_mesh_subnet *sub)
{ {
#if defined(CONFIG_BT_MESH_PRIV_BEACONS) #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
sub->priv_beacon.node_id = false; sub->priv_beacon_ctx.node_id = false;
#endif #endif
identity_enabled(sub); identity_enabled(sub);
@ -391,7 +391,7 @@ static void node_id_start(struct bt_mesh_subnet *sub)
static void private_node_id_start(struct bt_mesh_subnet *sub) static void private_node_id_start(struct bt_mesh_subnet *sub)
{ {
#if defined(CONFIG_BT_MESH_PRIV_BEACONS) #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
sub->priv_beacon.node_id = true; sub->priv_beacon_ctx.node_id = true;
#endif #endif
identity_enabled(sub); identity_enabled(sub);
@ -752,7 +752,7 @@ static int gatt_proxy_advertise(struct bt_mesh_subnet *sub)
LOG_DBG("Node ID active for %u ms, %d ms remaining", LOG_DBG("Node ID active for %u ms, %d ms remaining",
active, remaining); active, remaining);
#if defined(CONFIG_BT_MESH_PRIV_BEACONS) #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
priv_node_id = sub->priv_beacon.node_id; priv_node_id = sub->priv_beacon_ctx.node_id;
#endif #endif
if (priv_node_id) { if (priv_node_id) {
err = priv_node_id_adv(sub, remaining); err = priv_node_id_adv(sub, remaining);

View file

@ -612,7 +612,7 @@ uint8_t bt_mesh_subnet_priv_node_id_get(uint16_t net_idx,
} }
#if CONFIG_BT_MESH_GATT_PROXY && CONFIG_BT_MESH_PRIV_BEACONS #if CONFIG_BT_MESH_GATT_PROXY && CONFIG_BT_MESH_PRIV_BEACONS
if (sub->node_id == BT_MESH_FEATURE_ENABLED && sub->priv_beacon.node_id) { if (sub->node_id == BT_MESH_FEATURE_ENABLED && sub->priv_beacon_ctx.node_id) {
*priv_node_id = sub->node_id; *priv_node_id = sub->node_id;
} else { } else {
*priv_node_id = BT_MESH_FEATURE_DISABLED; *priv_node_id = BT_MESH_FEATURE_DISABLED;

View file

@ -33,19 +33,21 @@ struct bt_mesh_net_cred {
uint8_t privacy[16]; /* PrivacyKey */ uint8_t privacy[16]; /* PrivacyKey */
}; };
/** Subnet instance. */ struct bt_mesh_beacon {
struct bt_mesh_subnet { uint32_t sent; /* Timestamp of last sent beacon */
uint32_t beacon_sent; /* Timestamp of last sent beacon */ uint32_t recv; /* Timestamp of last received beacon */
uint32_t beacon_recv; /* Timestamp of last received beacon */ uint8_t last; /* Number of beacons during last
uint8_t beacons_last; /* Number of beacons during last
* observation window * observation window
*/ */
uint8_t beacons_cur; /* Number of beacons observed during uint8_t cur; /* Number of beacons observed during
* currently ongoing window. * currently ongoing window.
*/ */
uint8_t cache[8]; /* Cached last beacon auth value */
uint8_t auth[8]; /* Beacon Authentication Value */
};
uint8_t beacon_cache[8]; /* Cached last beacon auth value */ /** Subnet instance. */
struct bt_mesh_subnet {
uint16_t net_idx; /* NetKeyIndex */ uint16_t net_idx; /* NetKeyIndex */
uint8_t kr_phase; /* Key Refresh Phase */ uint8_t kr_phase; /* Key Refresh Phase */
@ -53,14 +55,16 @@ struct bt_mesh_subnet {
uint8_t node_id; /* Node Identity State */ uint8_t node_id; /* Node Identity State */
uint32_t node_id_start; /* Node Identity started timestamp */ uint32_t node_id_start; /* Node Identity started timestamp */
struct bt_mesh_beacon secure_beacon;
#if defined(CONFIG_BT_MESH_PRIV_BEACONS) #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
struct bt_mesh_beacon priv_beacon;
struct { struct {
uint16_t idx; /* Private beacon random index */ uint16_t idx; /* Private beacon random index */
bool node_id; /* Private Node Identity enabled */ bool node_id; /* Private Node Identity enabled */
uint8_t data[5]; /* Private Beacon data */ uint8_t data[5]; /* Private Beacon data */
} priv_beacon; } priv_beacon_ctx;
#endif #endif
uint8_t auth[8]; /* Beacon Authentication Value */
struct bt_mesh_subnet_keys { struct bt_mesh_subnet_keys {
bool valid; bool valid;