From 0a25a61c7df60cf1a59e5052e9ea719dafdd8563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Wed, 18 Oct 2023 17:43:13 +0200 Subject: [PATCH] Bluetooth: Mesh: Op agg mdl coex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactors the implementation of the Opcode Aggregator models to allow them to coexist on the same device. Signed-off-by: Anders Storrø --- subsys/bluetooth/mesh/access.c | 6 +- subsys/bluetooth/mesh/op_agg.c | 91 ++++++++-------------------- subsys/bluetooth/mesh/op_agg.h | 39 +++--------- subsys/bluetooth/mesh/op_agg_cli.c | 96 ++++++++++++++++++------------ subsys/bluetooth/mesh/op_agg_srv.c | 66 ++++++++++++++------ 5 files changed, 141 insertions(+), 157 deletions(-) diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 6ca7dbe580b..583652d4fbb 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -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)) { diff --git a/subsys/bluetooth/mesh/op_agg.c b/subsys/bluetooth/mesh/op_agg.c index 1580c7f0847..8c4497e4f6f 100644 --- a/subsys/bluetooth/mesh/op_agg.c +++ b/subsys/bluetooth/mesh/op_agg.c @@ -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; } @@ -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->len >= 2 && (buf->data[0] >> 6) == 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; +} diff --git a/subsys/bluetooth/mesh/op_agg.h b/subsys/bluetooth/mesh/op_agg.h index a267fc737f7..8bb3d6c97ba 100644 --- a/subsys/bluetooth/mesh/op_agg.h +++ b/subsys/bluetooth/mesh/op_agg.h @@ -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); diff --git a/subsys/bluetooth/mesh/op_agg_cli.c b/subsys/bluetooth/mesh/op_agg_cli.c index d3371306a8b..612843a98cc 100644 --- a/subsys/bluetooth/mesh/op_agg_cli.c +++ b/subsys/bluetooth/mesh/op_agg_cli.c @@ -18,14 +18,24 @@ #include 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; @@ -33,7 +43,6 @@ 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; @@ -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) { @@ -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; } } @@ -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); @@ -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) @@ -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 cli.ctx.initialized && (ctx->net_idx == cli.ctx.net_idx) && + (ctx->addr == cli.ctx.addr) && (ctx->app_idx == cli.ctx.app_idx) && + !bt_mesh_op_agg_is_op_agg_msg(buf); +} + const struct bt_mesh_model_cb _bt_mesh_op_agg_cli_cb = { .init = op_agg_cli_init, }; diff --git a/subsys/bluetooth/mesh/op_agg_srv.c b/subsys/bluetooth/mesh/op_agg_srv.c index bed3b54c946..a6e5f666411 100644 --- a/subsys/bluetooth/mesh/op_agg_srv.c +++ b/subsys/bluetooth/mesh/op_agg_srv.c @@ -17,17 +17,26 @@ #include LOG_MODULE_REGISTER(bt_mesh_op_agg_srv); +NET_BUF_SIMPLE_DEFINE_STATIC(sdu, BT_MESH_TX_SDU_MAX); + /** Mesh Opcodes Aggragator Server Model Context */ static struct bt_mesh_op_agg_srv { /** Composition data model entry pointer. */ struct bt_mesh_model *model; -} srv; + /** Response error code. */ + int rsp_err; + /** Indicates that the received aggregated message + * was acknowledged by local server model. + */ + bool ack; + /** Aggregator context. */ + struct op_agg_ctx ctx; +} srv = {.ctx.sdu = &sdu}; static int handle_sequence(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_state state; struct net_buf_simple msg; uint16_t elem; @@ -37,14 +46,14 @@ static int handle_sequence(struct bt_mesh_model *model, elem = net_buf_simple_pull_le16(buf); ctx->recv_dst = elem; - bt_mesh_model_msg_init(agg->sdu, OP_OPCODES_AGGREGATOR_STATUS); - status = net_buf_simple_add_u8(agg->sdu, 0); - net_buf_simple_add_le16(agg->sdu, elem); + bt_mesh_model_msg_init(srv.ctx.sdu, OP_OPCODES_AGGREGATOR_STATUS); + status = net_buf_simple_add_u8(srv.ctx.sdu, 0); + net_buf_simple_add_le16(srv.ctx.sdu, elem); - agg->net_idx = ctx->net_idx; - agg->app_idx = ctx->app_idx; - agg->addr = ctx->addr; - agg->initialized = true; + srv.ctx.net_idx = ctx->net_idx; + srv.ctx.app_idx = ctx->app_idx; + srv.ctx.addr = ctx->addr; + srv.ctx.initialized = true; if (!BT_MESH_ADDR_IS_UNICAST(elem)) { LOG_WRN("Address is not unicast, ignoring."); @@ -70,12 +79,12 @@ static int handle_sequence(struct bt_mesh_model *model, while (buf->len > 0) { (void) bt_mesh_op_agg_decode_msg(&msg, buf); - agg->ack = false; - agg->rsp_err = 0; + srv.ack = false; + srv.rsp_err = 0; err = bt_mesh_model_recv(ctx, &msg); - if (agg->rsp_err) { - *status = agg->rsp_err; + if (srv.rsp_err) { + *status = srv.rsp_err; break; } @@ -84,14 +93,14 @@ static int handle_sequence(struct bt_mesh_model *model, break; } - if (!agg->ack) { - net_buf_simple_add_u8(agg->sdu, 0); + if (!srv.ack) { + net_buf_simple_add_u8(srv.ctx.sdu, 0); } } send: - agg->initialized = false; - err = bt_mesh_model_send(model, ctx, agg->sdu, NULL, NULL); + srv.ctx.initialized = false; + err = bt_mesh_model_send(model, ctx, srv.ctx.sdu, NULL, NULL); if (err) { LOG_ERR("Unable to send Opcodes Aggregator Status"); return err; @@ -122,6 +131,29 @@ static int op_agg_srv_init(struct bt_mesh_model *model) return 0; } +int bt_mesh_op_agg_srv_send(struct bt_mesh_model *model, struct net_buf_simple *msg) +{ + int err; + + /* Model responded so mark this message as acknowledged */ + srv.ack = true; + + err = bt_mesh_op_agg_encode_msg(msg, srv.ctx.sdu); + if (err) { + srv.rsp_err = ACCESS_STATUS_RESPONSE_OVERFLOW; + } + + return err; +} + +int bt_mesh_op_agg_srv_accept(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) +{ + + return srv.ctx.initialized && (ctx->net_idx == srv.ctx.net_idx) && + (ctx->addr == srv.ctx.addr) && (ctx->app_idx == srv.ctx.app_idx) && + !bt_mesh_op_agg_is_op_agg_msg(buf); +} + const struct bt_mesh_model_cb _bt_mesh_op_agg_srv_cb = { .init = op_agg_srv_init, };