Skip to content

Commit

Permalink
Bluetooth: Mesh: Op agg mdl coex
Browse files Browse the repository at this point in the history
Refactors the implementation of the Opcode Aggregator
models to allow them to coexist on the same device.

Signed-off-by: Anders Storrø <[email protected]>
  • Loading branch information
Andrewpini committed Oct 19, 2023
1 parent 90b9809 commit fa5d18a
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 157 deletions.
6 changes: 4 additions & 2 deletions subsys/bluetooth/mesh/access.c
Original file line number Diff line number Diff line change
Expand Up @@ -1506,8 +1506,10 @@ int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG) && bt_mesh_op_agg_accept(ctx)) {
return bt_mesh_op_agg_send(model, ctx, msg, cb);
if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG_SRV) && bt_mesh_op_agg_srv_accept(ctx, msg)) {
return bt_mesh_op_agg_srv_send(model, msg);
} else if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG_CLI) && bt_mesh_op_agg_cli_accept(ctx, msg)) {
return bt_mesh_op_agg_cli_send(model, msg);
}

if (!bt_mesh_model_has_key(model, ctx->app_idx)) {
Expand Down
91 changes: 24 additions & 67 deletions subsys/bluetooth/mesh/op_agg.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,83 +16,22 @@ LOG_MODULE_REGISTER(bt_mesh_op_agg);
#define IS_LENGTH_LONG(buf) ((buf)->data[0] & 1)
#define LENGTH_SHORT_MAX BIT_MASK(7)

NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX);
NET_BUF_SIMPLE_DEFINE_STATIC(srcs, BT_MESH_TX_SDU_MAX);

static struct op_agg_ctx agg_ctx = {
.sdu = &sdu,
#if IS_ENABLED(CONFIG_BT_MESH_OP_AGG_CLI)
.srcs = &srcs,
#endif
};

struct op_agg_ctx *bt_mesh_op_agg_ctx_get(void)
{
return &agg_ctx;
}

static bool ctx_match(struct bt_mesh_msg_ctx *ctx)
{
return (ctx->net_idx == agg_ctx.net_idx) && (ctx->addr == agg_ctx.addr) &&
(ctx->app_idx == agg_ctx.app_idx);
}

int bt_mesh_op_agg_accept(struct bt_mesh_msg_ctx *msg_ctx)
{
return agg_ctx.initialized && ctx_match(msg_ctx);
}

void bt_mesh_op_agg_ctx_reinit(void)
{
agg_ctx.initialized = true;
}

int bt_mesh_op_agg_send(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb)
{
int err;

/* Model responded so mark this message as acknowledged */
agg_ctx.ack = true;

if (IS_ENABLED(CONFIG_BT_MESH_OP_AGG_CLI)) {
/* Store source address so that Opcodes Aggregator Client can
* match response with source model
*/
uint16_t src = bt_mesh_model_elem(model)->addr;

if (net_buf_simple_tailroom(&srcs) < 2) {
return -ENOMEM;
}

net_buf_simple_add_le16(&srcs, src);
}

err = bt_mesh_op_agg_encode_msg(msg);
if (err) {
agg_ctx.rsp_err = ACCESS_STATUS_RESPONSE_OVERFLOW;
}

return err;
}

int bt_mesh_op_agg_encode_msg(struct net_buf_simple *msg)
int bt_mesh_op_agg_encode_msg(struct net_buf_simple *msg, struct net_buf_simple *buf)
{
if (msg->len > LENGTH_SHORT_MAX) {
if (net_buf_simple_tailroom(agg_ctx.sdu) < (msg->len + 2)) {
if (net_buf_simple_tailroom(buf) < (msg->len + 2)) {
return -ENOMEM;
}

net_buf_simple_add_le16(agg_ctx.sdu, (msg->len << 1) | 1);
net_buf_simple_add_le16(buf, (msg->len << 1) | 1);
} else {
if (net_buf_simple_tailroom(agg_ctx.sdu) < (msg->len + 1)) {
if (net_buf_simple_tailroom(buf) < (msg->len + 1)) {
return -ENOMEM;
}

net_buf_simple_add_u8(agg_ctx.sdu, msg->len << 1);
net_buf_simple_add_u8(buf, msg->len << 1);
}
net_buf_simple_add_mem(agg_ctx.sdu, msg->data, msg->len);
net_buf_simple_add_mem(buf, msg->data, msg->len);

return 0;
}
Expand Down Expand Up @@ -124,3 +63,21 @@ int bt_mesh_op_agg_decode_msg(struct net_buf_simple *msg,

return 0;
}

bool bt_mesh_op_agg_is_op_agg_msg(struct net_buf_simple *buf)
{
if ((buf->data[0] >> 6) == 2 && buf->len >= 2) {
uint16_t opcode;
struct net_buf_simple_state state;

net_buf_simple_save(buf, &state);
opcode = net_buf_simple_pull_be16(buf);
net_buf_simple_restore(buf, &state);

if ((opcode == OP_OPCODES_AGGREGATOR_STATUS) ||
(opcode == OP_OPCODES_AGGREGATOR_SEQUENCE)) {
return true;
}
}
return false;
}
39 changes: 7 additions & 32 deletions subsys/bluetooth/mesh/op_agg.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,20 @@
struct op_agg_ctx {
/** Context is initialized. */
bool initialized;

/** NetKey Index of the subnet to send the message on. */
uint16_t net_idx;

/** AppKey Index to encrypt the message with. */
uint16_t app_idx;

/** Remote element address. */
uint16_t addr;

/** List of source element addresses.
* Used by Client to match aggregated responses
* with local source client models.
*/
struct net_buf_simple *srcs;

/** Response error code. */
int rsp_err;

/** Aggregated message buffer. */
struct net_buf_simple *sdu;

/** Used only by the Opcodes Aggregator Server.
*
* Indicates that the received aggregated message
* was acknowledged by local server model.
*/
bool ack;
};

struct op_agg_ctx *bt_mesh_op_agg_ctx_get(void);
void bt_mesh_op_agg_ctx_reinit(void);

int bt_mesh_op_agg_encode_msg(struct net_buf_simple *msg);
int bt_mesh_op_agg_decode_msg(struct net_buf_simple *msg,
struct net_buf_simple *buf);

int bt_mesh_op_agg_accept(struct bt_mesh_msg_ctx *ctx);

int bt_mesh_op_agg_send(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb);
int bt_mesh_op_agg_encode_msg(struct net_buf_simple *msg, struct net_buf_simple *buf);
int bt_mesh_op_agg_decode_msg(struct net_buf_simple *msg, struct net_buf_simple *buf);
int bt_mesh_op_agg_cli_send(struct bt_mesh_model *model, struct net_buf_simple *msg);
int bt_mesh_op_agg_cli_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf);
int bt_mesh_op_agg_srv_send(struct bt_mesh_model *model, struct net_buf_simple *msg);
int bt_mesh_op_agg_srv_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf);
bool bt_mesh_op_agg_is_op_agg_msg(struct net_buf_simple *buf);
96 changes: 57 additions & 39 deletions subsys/bluetooth/mesh/op_agg_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,31 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_mesh_op_agg_cli);

NET_BUF_SIMPLE_DEFINE_STATIC(srcs, BT_MESH_TX_SDU_MAX);
NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX);

/** Mesh Opcodes Aggregator Client Model Context */
static struct bt_mesh_op_agg_cli {
/** Composition data model entry pointer. */
struct bt_mesh_model *model;

/* Internal parameters for tracking message responses. */
/** Acknowledge context. */
struct bt_mesh_msg_ack_ctx ack_ctx;
} cli;
/** List of source element addresses.
* Used by Client to match aggregated responses
* with local source client models.
*/
struct net_buf_simple *srcs;
/** Aggregator context. */
struct op_agg_ctx ctx;

} cli = {.srcs = &srcs, .ctx.sdu = &sdu};

static int32_t msg_timeout;

static int handle_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get();
struct net_buf_simple msg;
uint8_t status;
uint16_t elem_addr, addr;
Expand All @@ -57,17 +66,17 @@ static int handle_status(struct bt_mesh_model *model,
err = bt_mesh_op_agg_decode_msg(&msg, buf);
if (err) {
LOG_ERR("Cannot decode aggregated message %d", err);
bt_mesh_op_agg_ctx_reinit();
cli.ctx.initialized = true;
return -EINVAL;
}

if (agg->srcs->len < 2) {
if (cli.srcs->len < 2) {
LOG_ERR("Mismatch in sources address buffer");
bt_mesh_op_agg_ctx_reinit();
cli.ctx.initialized = true;
return -ENOENT;
}

addr = net_buf_simple_pull_le16(agg->srcs);
addr = net_buf_simple_pull_le16(cli.srcs);

/* Empty item means unacked msg. */
if (!msg.len) {
Expand All @@ -78,7 +87,7 @@ static int handle_status(struct bt_mesh_model *model,
err = bt_mesh_model_recv(ctx, &msg);
if (err) {
LOG_ERR("Opcodes Aggregator receive error %d", err);
bt_mesh_op_agg_ctx_reinit();
cli.ctx.initialized = true;
return err;
}
}
Expand Down Expand Up @@ -115,56 +124,51 @@ static int op_agg_cli_init(struct bt_mesh_model *model)
int bt_mesh_op_agg_cli_seq_start(uint16_t net_idx, uint16_t app_idx, uint16_t dst,
uint16_t elem_addr)
{
struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get();

if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
LOG_ERR("Element address shall be a unicast address");
return -EINVAL;
}

if (agg->initialized) {
if (cli.ctx.initialized) {
LOG_ERR("Opcodes Aggregator is already configured");
return -EALREADY;
}

agg->net_idx = net_idx;
agg->app_idx = app_idx;
agg->addr = dst;
agg->ack = false;
agg->rsp_err = 0;
agg->initialized = true;
cli.ctx.net_idx = net_idx;
cli.ctx.app_idx = app_idx;
cli.ctx.addr = dst;
cli.ctx.initialized = true;

net_buf_simple_init(agg->srcs, 0);
bt_mesh_model_msg_init(agg->sdu, OP_OPCODES_AGGREGATOR_SEQUENCE);
net_buf_simple_add_le16(agg->sdu, elem_addr);
net_buf_simple_init(cli.srcs, 0);
bt_mesh_model_msg_init(cli.ctx.sdu, OP_OPCODES_AGGREGATOR_SEQUENCE);
net_buf_simple_add_le16(cli.ctx.sdu, elem_addr);

return 0;
}

int bt_mesh_op_agg_cli_seq_send(void)
{
struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get();
struct bt_mesh_msg_ctx ctx = {
.net_idx = agg->net_idx,
.app_idx = agg->app_idx,
.addr = agg->addr,
.net_idx = cli.ctx.net_idx,
.app_idx = cli.ctx.app_idx,
.addr = cli.ctx.addr,
};
int err;

if (!agg->initialized) {
if (!cli.ctx.initialized) {
LOG_ERR("Opcodes Aggregator not initialized");
return -EINVAL;
}

err = bt_mesh_msg_ack_ctx_prepare(&cli.ack_ctx, OP_OPCODES_AGGREGATOR_STATUS, agg->addr,
NULL);
err = bt_mesh_msg_ack_ctx_prepare(&cli.ack_ctx, OP_OPCODES_AGGREGATOR_STATUS,
cli.ctx.addr, NULL);
if (err) {
return err;
}

agg->initialized = false;
cli.ctx.initialized = false;

err = bt_mesh_model_send(cli.model, &ctx, agg->sdu, NULL, NULL);
err = bt_mesh_model_send(cli.model, &ctx, cli.ctx.sdu, NULL, NULL);
if (err) {
LOG_ERR("model_send() failed (err %d)", err);
bt_mesh_msg_ack_ctx_clear(&cli.ack_ctx);
Expand All @@ -176,23 +180,17 @@ int bt_mesh_op_agg_cli_seq_send(void)

void bt_mesh_op_agg_cli_seq_abort(void)
{
struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get();

agg->initialized = false;
cli.ctx.initialized = false;
}

bool bt_mesh_op_agg_cli_seq_is_started(void)
{
struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get();

return agg->initialized;
return cli.ctx.initialized;
}

size_t bt_mesh_op_agg_cli_seq_tailroom(void)
{
struct op_agg_ctx *agg = bt_mesh_op_agg_ctx_get();

return net_buf_simple_tailroom(agg->sdu);
return net_buf_simple_tailroom(cli.ctx.sdu);
}

int32_t bt_mesh_op_agg_cli_timeout_get(void)
Expand All @@ -205,6 +203,26 @@ void bt_mesh_op_agg_cli_timeout_set(int32_t timeout)
msg_timeout = timeout;
}

int bt_mesh_op_agg_cli_send(struct bt_mesh_model *model, struct net_buf_simple *msg)
{
uint16_t src = bt_mesh_model_elem(model)->addr;

if (net_buf_simple_tailroom(&srcs) < 2) {
return -ENOMEM;
}

net_buf_simple_add_le16(&srcs, src);
return bt_mesh_op_agg_encode_msg(msg, cli.ctx.sdu);
}

int bt_mesh_op_agg_cli_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
{

return !bt_mesh_op_agg_is_op_agg_msg(buf) && cli.ctx.initialized &&
(ctx->net_idx == cli.ctx.net_idx) && (ctx->addr == cli.ctx.addr) &&
(ctx->app_idx == cli.ctx.app_idx);
}

const struct bt_mesh_model_cb _bt_mesh_op_agg_cli_cb = {
.init = op_agg_cli_init,
};
Loading

0 comments on commit fa5d18a

Please sign in to comment.