Bluetooth: Mesh: Add full virtual addresses support
This commit adds the following features related to virtual addresses support: - Allows to store Label UUIDs which virtual addresses collide; - Allows to decrypt messages encrypted with a virtual address with collision; - Allows to publish a message to a specific Label UUID to avoid virtual addresses collision by adding a pointer to Label UUID to struct bt_mesh_msg_ctx and struct bt_mesh_model_pub; - Allows to differentiate Label UUIDs in the model's Subscription List by storing all subscribed UUIDs in struct bt_mesh_model.uuids field. Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
parent
1956b06ecc
commit
648378b292
22 changed files with 1047 additions and 722 deletions
|
@ -35,6 +35,7 @@
|
|||
#include "friend.h"
|
||||
#include "settings.h"
|
||||
#include "cfg.h"
|
||||
#include "va.h"
|
||||
|
||||
#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
|
@ -130,7 +131,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
|
|||
}
|
||||
}
|
||||
|
||||
static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr,
|
||||
static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, const uint8_t *uuid,
|
||||
uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period,
|
||||
uint8_t retransmit, bool store)
|
||||
{
|
||||
|
@ -158,6 +159,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr,
|
|||
model->pub->period = 0U;
|
||||
model->pub->retransmit = 0U;
|
||||
model->pub->count = 0U;
|
||||
model->pub->uuid = NULL;
|
||||
|
||||
if (model->pub->update) {
|
||||
/* If this fails, the timer will check pub->addr and
|
||||
|
@ -179,11 +181,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr,
|
|||
|
||||
#if CONFIG_BT_MESH_LABEL_COUNT > 0
|
||||
if (BT_MESH_ADDR_IS_VIRTUAL(model->pub->addr)) {
|
||||
uint8_t *uuid = bt_mesh_va_label_get(model->pub->addr);
|
||||
|
||||
if (uuid) {
|
||||
bt_mesh_va_del(uuid, NULL);
|
||||
}
|
||||
(void)bt_mesh_va_del(model->pub->uuid);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -193,6 +191,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr,
|
|||
model->pub->ttl = ttl;
|
||||
model->pub->period = period;
|
||||
model->pub->retransmit = retransmit;
|
||||
model->pub->uuid = uuid;
|
||||
|
||||
if (model->pub->update) {
|
||||
int32_t period_ms;
|
||||
|
@ -273,7 +272,7 @@ static uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool st
|
|||
}
|
||||
|
||||
if (model->pub && model->pub->key == key_idx) {
|
||||
_mod_pub_set(model, BT_MESH_ADDR_UNASSIGNED,
|
||||
_mod_pub_set(model, BT_MESH_ADDR_UNASSIGNED, NULL,
|
||||
0, 0, 0, 0, 0, store);
|
||||
}
|
||||
}
|
||||
|
@ -803,7 +802,7 @@ static int mod_pub_set(struct bt_mesh_model *model,
|
|||
goto send_status;
|
||||
}
|
||||
|
||||
status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl,
|
||||
status = _mod_pub_set(mod, pub_addr, NULL, pub_app_idx, cred_flag, pub_ttl,
|
||||
pub_period, retransmit, true);
|
||||
|
||||
send_status:
|
||||
|
@ -813,32 +812,31 @@ send_status:
|
|||
|
||||
static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
|
||||
{
|
||||
uint8_t *label_uuid;
|
||||
size_t clear_count;
|
||||
int i;
|
||||
|
||||
/* Unref stored labels related to this model */
|
||||
for (i = 0, clear_count = 0; i < mod->groups_cnt; i++) {
|
||||
if (!BT_MESH_ADDR_IS_VIRTUAL(mod->groups[i])) {
|
||||
if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
|
||||
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
|
||||
clear_count++;
|
||||
}
|
||||
/* mod->groups contains both, group and virtual addrs. Virtual addrs deletion will
|
||||
* be handled separately.
|
||||
*/
|
||||
if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
|
||||
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
|
||||
clear_count++;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MESH_LABEL_COUNT > 0
|
||||
/* Unref stored labels related to this model */
|
||||
for (i = 0; i < CONFIG_BT_MESH_LABEL_COUNT; i++) {
|
||||
if (mod->uuids[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
label_uuid = bt_mesh_va_label_get(mod->groups[i]);
|
||||
|
||||
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
|
||||
clear_count++;
|
||||
|
||||
if (label_uuid) {
|
||||
bt_mesh_va_del(label_uuid, NULL);
|
||||
} else {
|
||||
LOG_ERR("Label UUID not found");
|
||||
}
|
||||
(void)bt_mesh_va_del(mod->uuids[i]);
|
||||
mod->uuids[i] = NULL;
|
||||
/* No need to increment `clear_count` as `groups` contains virtual addresses. */
|
||||
}
|
||||
#endif
|
||||
|
||||
return clear_count;
|
||||
}
|
||||
|
@ -847,11 +845,13 @@ static int mod_pub_va_set(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
const struct bt_mesh_va *va;
|
||||
uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
|
||||
uint16_t elem_addr, pub_addr, pub_app_idx;
|
||||
uint16_t elem_addr, pub_app_idx;
|
||||
uint16_t pub_addr = 0U;
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
uint8_t *label_uuid;
|
||||
const uint8_t *uuid;
|
||||
uint8_t *mod_id;
|
||||
bool vnd;
|
||||
|
||||
|
@ -866,7 +866,7 @@ static int mod_pub_va_set(struct bt_mesh_model *model,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
label_uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
pub_app_idx = net_buf_simple_pull_le16(buf);
|
||||
cred_flag = ((pub_app_idx >> 12) & BIT_MASK(1));
|
||||
pub_app_idx &= BIT_MASK(12);
|
||||
|
@ -890,27 +890,27 @@ static int mod_pub_va_set(struct bt_mesh_model *model,
|
|||
if (!elem) {
|
||||
mod = NULL;
|
||||
vnd = (buf->len == 4U);
|
||||
pub_addr = 0U;
|
||||
status = STATUS_INVALID_ADDRESS;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
mod = get_model(elem, buf, &vnd);
|
||||
if (!mod) {
|
||||
pub_addr = 0U;
|
||||
status = STATUS_INVALID_MODEL;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
status = bt_mesh_va_add(label_uuid, &pub_addr);
|
||||
status = bt_mesh_va_add(uuid, &va);
|
||||
if (status != STATUS_SUCCESS) {
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl,
|
||||
pub_addr = va->addr;
|
||||
|
||||
status = _mod_pub_set(mod, pub_addr, va->uuid, pub_app_idx, cred_flag, pub_ttl,
|
||||
pub_period, retransmit, true);
|
||||
if (status != STATUS_SUCCESS) {
|
||||
bt_mesh_va_del(label_uuid, NULL);
|
||||
(void)bt_mesh_va_del(va->uuid);
|
||||
}
|
||||
|
||||
send_status:
|
||||
|
@ -1383,12 +1383,14 @@ static int mod_sub_va_add(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
uint16_t elem_addr, sub_addr;
|
||||
const struct bt_mesh_va *va;
|
||||
uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
uint8_t *label_uuid;
|
||||
const uint8_t *uuid;
|
||||
uint8_t *mod_id;
|
||||
uint16_t *entry;
|
||||
uint16_t *group_entry;
|
||||
const uint8_t **label_entry;
|
||||
uint8_t status;
|
||||
bool vnd;
|
||||
|
||||
|
@ -1403,7 +1405,7 @@ static int mod_sub_va_add(struct bt_mesh_model *model,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
label_uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
|
||||
LOG_DBG("elem_addr 0x%04x", elem_addr);
|
||||
|
||||
|
@ -1412,42 +1414,59 @@ static int mod_sub_va_add(struct bt_mesh_model *model,
|
|||
if (!elem) {
|
||||
mod = NULL;
|
||||
vnd = (buf->len == 4U);
|
||||
sub_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
status = STATUS_INVALID_ADDRESS;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
mod = get_model(elem, buf, &vnd);
|
||||
if (!mod) {
|
||||
sub_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
status = STATUS_INVALID_MODEL;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
status = bt_mesh_va_add(label_uuid, &sub_addr);
|
||||
status = bt_mesh_va_add(uuid, &va);
|
||||
if (status != STATUS_SUCCESS) {
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
if (bt_mesh_model_find_group(&mod, sub_addr)) {
|
||||
if (bt_mesh_model_find_uuid(&mod, va->uuid)) {
|
||||
/* Tried to add existing subscription */
|
||||
status = STATUS_SUCCESS;
|
||||
bt_mesh_va_del(label_uuid, NULL);
|
||||
(void)bt_mesh_va_del(va->uuid);
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
|
||||
entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED);
|
||||
if (!entry) {
|
||||
label_entry = bt_mesh_model_find_uuid(&mod, NULL);
|
||||
if (!label_entry) {
|
||||
status = STATUS_INSUFF_RESOURCES;
|
||||
bt_mesh_va_del(label_uuid, NULL);
|
||||
(void)bt_mesh_va_del(va->uuid);
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
*entry = sub_addr;
|
||||
group_entry = NULL;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
for (int i = 0; i < mod->groups_cnt; i++) {
|
||||
if (mod->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
|
||||
group_entry = &mod->groups[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* bt_mesh_model_find_uuid() should find a model where both, uuids and groups lists have
|
||||
* empty entry.
|
||||
*/
|
||||
if (!group_entry) {
|
||||
status = STATUS_INSUFF_RESOURCES;
|
||||
(void)bt_mesh_va_del(va->uuid);
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
*group_entry = va->addr;
|
||||
*label_entry = va->uuid;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && va->ref == 1 &&
|
||||
!bt_mesh_va_collision_check(va->addr)) {
|
||||
bt_mesh_lpn_group_add(va->addr);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
|
@ -1455,6 +1474,7 @@ static int mod_sub_va_add(struct bt_mesh_model *model,
|
|||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
sub_addr = va->addr;
|
||||
|
||||
send_status:
|
||||
return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
|
||||
|
@ -1465,12 +1485,13 @@ static int mod_sub_va_del(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
uint16_t elem_addr, sub_addr;
|
||||
const struct bt_mesh_va *va;
|
||||
uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
uint8_t *label_uuid;
|
||||
const uint8_t *uuid;
|
||||
uint8_t *mod_id;
|
||||
uint16_t *match;
|
||||
const uint8_t **label_match;
|
||||
uint8_t status;
|
||||
bool vnd;
|
||||
|
||||
|
@ -1485,7 +1506,7 @@ static int mod_sub_va_del(struct bt_mesh_model *model,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
label_uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
|
||||
LOG_DBG("elem_addr 0x%04x", elem_addr);
|
||||
|
||||
|
@ -1495,40 +1516,50 @@ static int mod_sub_va_del(struct bt_mesh_model *model,
|
|||
if (!elem) {
|
||||
mod = NULL;
|
||||
vnd = (buf->len == 4U);
|
||||
sub_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
status = STATUS_INVALID_ADDRESS;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
mod = get_model(elem, buf, &vnd);
|
||||
if (!mod) {
|
||||
sub_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
status = STATUS_INVALID_MODEL;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
status = bt_mesh_va_del(label_uuid, &sub_addr);
|
||||
if (sub_addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
va = bt_mesh_va_find(uuid);
|
||||
if (!va) {
|
||||
status = STATUS_CANNOT_REMOVE;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_del(&sub_addr, 1);
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && va->ref == 1 &&
|
||||
!bt_mesh_va_collision_check(va->addr)) {
|
||||
bt_mesh_lpn_group_del(&va->addr, 1);
|
||||
}
|
||||
|
||||
match = bt_mesh_model_find_group(&mod, sub_addr);
|
||||
if (match) {
|
||||
*match = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_model_sub_store(mod);
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
} else {
|
||||
label_match = bt_mesh_model_find_uuid(&mod, va->uuid);
|
||||
if (!label_match) {
|
||||
status = STATUS_CANNOT_REMOVE;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mod->groups_cnt; i++) {
|
||||
if (mod->groups[i] == va->addr) {
|
||||
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*label_match = NULL;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_model_sub_store(mod);
|
||||
}
|
||||
|
||||
sub_addr = va->addr;
|
||||
(void)bt_mesh_va_del(va->uuid);
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
send_status:
|
||||
return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
|
||||
mod_id, vnd);
|
||||
|
@ -1538,10 +1569,11 @@ static int mod_sub_va_overwrite(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
const struct bt_mesh_va *va;
|
||||
uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
uint8_t *label_uuid;
|
||||
const uint8_t *uuid;
|
||||
uint8_t *mod_id;
|
||||
uint8_t status;
|
||||
bool vnd;
|
||||
|
@ -1557,7 +1589,7 @@ static int mod_sub_va_overwrite(struct bt_mesh_model *model,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
label_uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
|
||||
LOG_DBG("elem_addr 0x%04x", elem_addr);
|
||||
|
||||
|
@ -1577,26 +1609,33 @@ static int mod_sub_va_overwrite(struct bt_mesh_model *model,
|
|||
goto send_status;
|
||||
}
|
||||
|
||||
|
||||
if (mod->groups_cnt > 0) {
|
||||
|
||||
status = bt_mesh_va_add(label_uuid, &sub_addr);
|
||||
if (status == STATUS_SUCCESS) {
|
||||
bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL);
|
||||
mod->groups[0] = sub_addr;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_model_sub_store(mod);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (CONFIG_BT_MESH_LABEL_COUNT == 0 || mod->groups_cnt == 0) {
|
||||
(void)va;
|
||||
status = STATUS_INSUFF_RESOURCES;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MESH_LABEL_COUNT > 0
|
||||
status = bt_mesh_va_add(uuid, &va);
|
||||
if (status != STATUS_SUCCESS) {
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL);
|
||||
mod->groups[0] = va->addr;
|
||||
mod->uuids[0] = va->uuid;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_model_sub_store(mod);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && va->ref == 1 &&
|
||||
!bt_mesh_va_collision_check(va->addr)) {
|
||||
bt_mesh_lpn_group_add(va->addr);
|
||||
}
|
||||
|
||||
sub_addr = va->addr;
|
||||
#endif
|
||||
send_status:
|
||||
return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
|
||||
mod_id, vnd);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue