From patchwork Wed Aug 5 17:44:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252914 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.2 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS,UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 19BA0C433E0 for ; Wed, 5 Aug 2020 17:55:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E70EA2073E for ; Wed, 5 Aug 2020 17:55:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728928AbgHERyv (ORCPT ); Wed, 5 Aug 2020 13:54:51 -0400 Received: from mga05.intel.com ([192.55.52.43]:42213 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729031AbgHERtk (ORCPT ); Wed, 5 Aug 2020 13:49:40 -0400 IronPort-SDR: EmgZD/uYicIsrfiU/ONvOdB6tbyZMUKMzLguFT0s5xri9iI+TsvctbNsKlFl5g4IPDA5elN0wG YCop0fokZv2A== X-IronPort-AV: E=McAfee;i="6000,8403,9704"; a="237470622" X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="237470622" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2020 10:44:58 -0700 IronPort-SDR: upjRO79vetpmJY5R+6Wi2nBAqCdfN4GbLYP3quwp9FaBDlKMLnZxw95jCHNPtofJkatWGa5K+V ltJN/W4OBGQA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="437245719" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.189]) by orsmga004.jf.intel.com with ESMTP; 05 Aug 2020 10:44:58 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v4 02/10] mesh: Clean up handling of config model binding messages Date: Wed, 5 Aug 2020 10:44:48 -0700 Message-Id: <20200805174456.49342-3-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200805174456.49342-1-inga.stotland@intel.com> References: <20200805174456.49342-1-inga.stotland@intel.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This modification allows using a single point for sending out the composed status messages by the Config Server. Also, remove unused definitions for binding functions in node.h --- mesh/cfgmod-server.c | 130 ++++++++++++------------------------------- mesh/model.c | 16 +----- mesh/node.h | 4 -- 3 files changed, 38 insertions(+), 112 deletions(-) diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index cd0e8b94c..35d0325a9 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -112,8 +112,7 @@ static void config_pub_set(struct mesh_node *node, uint16_t net_idx, uint16_t ele_addr, idx, ota = UNASSIGNED_ADDRESS; const uint8_t *pub_addr; uint16_t test_addr; - uint8_t ttl, period; - uint8_t retransmit; + uint8_t ttl, period, retransmit; int status; bool cred_flag; @@ -362,115 +361,56 @@ static uint16_t config_sub_del_all(struct mesh_node *node, const uint8_t *pkt, return n; } -static void send_model_app_status(struct mesh_node *node, uint16_t net_idx, - uint16_t src, uint16_t dst, - uint8_t status, uint16_t addr, - uint32_t id, uint16_t idx) -{ - size_t n = mesh_model_opcode_set(OP_MODEL_APP_STATUS, msg); - - msg[n++] = status; - l_put_le16(addr, msg + n); - n += 2; - l_put_le16(idx, msg + n); - n += 2; - - if (IS_VENDOR(id)) { - l_put_le16(VENDOR_ID(id), msg + n); - n += 2; - } - - l_put_le16(MODEL_ID(id), msg + n); - n += 2; - - mesh_model_send(node, dst, src, APP_IDX_DEV_LOCAL, net_idx, DEFAULT_TTL, - false, msg, n); -} - -static void model_app_list(struct mesh_node *node, uint16_t net_idx, - uint16_t src, uint16_t dst, +static uint16_t model_app_list(struct mesh_node *node, const uint8_t *pkt, uint16_t size) { - uint16_t ele_addr; + uint16_t ele_addr, n, bnd_len; uint32_t id; - uint8_t *status; - uint16_t n; - int result; + int opcode; + opcode = (size == 4) ? OP_MODEL_APP_LIST : OP_VEND_MODEL_APP_LIST; ele_addr = l_get_le16(pkt); - switch (size) { - default: - return; - case 4: - n = mesh_model_opcode_set(OP_MODEL_APP_LIST, msg); - status = msg + n; - id = l_get_le16(pkt + 2); - l_put_le16(ele_addr, msg + 1 + n); - l_put_le16((uint16_t) id, msg + 3 + n); - id = SET_ID(SIG_VENDOR, id); - n += 5; - break; - case 6: - n = mesh_model_opcode_set(OP_VEND_MODEL_APP_LIST, msg); - status = msg + n; - id = SET_ID(l_get_le16(pkt + 2), l_get_le16(pkt + 4)); + n = mesh_model_opcode_set(opcode, msg); + memcpy(msg + n + 1, pkt, size); - l_put_le16(ele_addr, msg + 1 + n); - l_put_le16((uint16_t) VENDOR_ID(id), msg + 3 + n); - l_put_le16((uint16_t) MODEL_ID(id), msg + 5 + n); - n += 7; - break; - } + id = CFG_SET_ID(size == 6, pkt + 2); - result = mesh_model_get_bindings(node, ele_addr, id, msg + n, - MAX_MSG_LEN - n, &size); - n += size; + msg[n] = mesh_model_get_bindings(node, ele_addr, id, msg + n + 1 + size, + MAX_MSG_LEN - (n + 1 + size), &bnd_len); - if (result >= 0) { - *status = result; - mesh_model_send(node, dst, src, APP_IDX_DEV_LOCAL, net_idx, - DEFAULT_TTL, false, msg, n); - } + if (msg[n] == MESH_STATUS_SUCCESS) + n += bnd_len; + + n += (size + 1); + return n; } -static bool model_app_bind(struct mesh_node *node, uint16_t net_idx, - uint16_t src, uint16_t dst, - const uint8_t *pkt, uint16_t size, - bool unbind) +static uint16_t model_app_bind(struct mesh_node *node, const uint8_t *pkt, + uint16_t size, bool unbind) { - uint16_t ele_addr; + uint16_t ele_addr, idx, n; uint32_t id; - uint16_t idx; - int result; - switch (size) { - default: - return false; - case 6: - id = SET_ID(SIG_VENDOR, l_get_le16(pkt + 4)); - break; - case 8: - id = SET_ID(l_get_le16(pkt + 4), l_get_le16(pkt + 6)); - break; - } + idx = l_get_le16(pkt + 2); + if (idx > APP_IDX_MASK) + return 0; ele_addr = l_get_le16(pkt); - idx = l_get_le16(pkt + 2); + id = CFG_SET_ID(size == 8, pkt + 4); - if (idx > 0xfff) - return false; + n = mesh_model_opcode_set(OP_MODEL_APP_STATUS, msg); if (unbind) - result = mesh_model_binding_del(node, ele_addr, id, idx); + msg[n] = mesh_model_binding_del(node, ele_addr, id, idx); else - result = mesh_model_binding_add(node, ele_addr, id, idx); + msg[n] = mesh_model_binding_add(node, ele_addr, id, idx); - send_model_app_status(node, net_idx, src, dst, result, ele_addr, - id, idx); + memcpy(msg + n + 1, pkt, size); + n += (size + 1); - return true; + return n; } static void hb_pub_timeout_func(struct l_timeout *timeout, void *user_data) @@ -703,8 +643,7 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, if (size != 1 || pkt[0] > TTL_MASK || pkt[0] == 1) return true; - if (pkt[0] <= TTL_MASK) - node_default_ttl_set(node, pkt[0]); + node_default_ttl_set(node, pkt[0]); /* Fall Through */ case OP_CONFIG_DEFAULT_TTL_GET: @@ -1048,22 +987,25 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, case OP_MODEL_APP_BIND: case OP_MODEL_APP_UNBIND: - model_app_bind(node, net_idx, src, dst, pkt, size, - opcode != OP_MODEL_APP_BIND); + if (size != 6 && size != 8) + return true; + + n = model_app_bind(node, pkt, size, + opcode != OP_MODEL_APP_BIND); break; case OP_VEND_MODEL_APP_GET: if (size != 6) return true; - model_app_list(node, net_idx, src, dst, pkt, size); + n = model_app_list(node, pkt, size); break; case OP_MODEL_APP_GET: if (size != 4) return true; - model_app_list(node, net_idx, src, dst, pkt, size); + n = model_app_list(node, pkt, size); break; case OP_CONFIG_HEARTBEAT_PUB_SET: diff --git a/mesh/model.c b/mesh/model.c index 3c9b6577a..e2cadfe36 100644 --- a/mesh/model.c +++ b/mesh/model.c @@ -111,13 +111,7 @@ static bool simple_match(const void *a, const void *b) static bool has_binding(struct l_queue *bindings, uint16_t idx) { - const struct l_queue_entry *l; - - for (l = l_queue_get_entries(bindings); l; l = l->next) { - if (L_PTR_TO_UINT(l->data) == idx) - return true; - } - return false; + return l_queue_find(bindings, simple_match, L_UINT_TO_PTR(idx)) != NULL; } static bool find_virt_by_label(const void *a, const void *b) @@ -628,7 +622,6 @@ static int update_binding(struct mesh_node *node, uint16_t addr, uint32_t id, uint16_t app_idx, bool unbind) { struct mesh_model *mod; - bool is_present; int ele_idx = node_get_element_idx(node, addr); if (ele_idx < 0) @@ -645,12 +638,7 @@ static int update_binding(struct mesh_node *node, uint16_t addr, uint32_t id, if (!appkey_have_key(node_get_net(node), app_idx)) return MESH_STATUS_INVALID_APPKEY; - is_present = has_binding(mod->bindings, app_idx); - - if (!is_present && unbind) - return MESH_STATUS_SUCCESS; - - if (is_present && !unbind) + if (unbind ^ has_binding(mod->bindings, app_idx)) return MESH_STATUS_SUCCESS; if (unbind) { diff --git a/mesh/node.h b/mesh/node.h index 47c998530..7874b8692 100644 --- a/mesh/node.h +++ b/mesh/node.h @@ -49,10 +49,6 @@ const uint8_t *node_get_token(struct mesh_node *node); const uint8_t *node_get_device_key(struct mesh_node *node); void node_set_num_elements(struct mesh_node *node, uint8_t num_ele); uint8_t node_get_num_elements(struct mesh_node *node); -bool node_add_binding(struct mesh_node *node, uint8_t ele_idx, - uint32_t model_id, uint16_t app_idx); -bool node_del_binding(struct mesh_node *node, uint8_t ele_idx, - uint32_t model_id, uint16_t app_idx); uint8_t node_default_ttl_get(struct mesh_node *node); bool node_default_ttl_set(struct mesh_node *node, uint8_t ttl); bool node_set_sequence_number(struct mesh_node *node, uint32_t seq); From patchwork Wed Aug 5 17:44:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252915 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0684BC433DF for ; Wed, 5 Aug 2020 17:53:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E0DA02073E for ; Wed, 5 Aug 2020 17:53:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728999AbgHERxb (ORCPT ); Wed, 5 Aug 2020 13:53:31 -0400 Received: from mga05.intel.com ([192.55.52.43]:42213 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729036AbgHERuz (ORCPT ); Wed, 5 Aug 2020 13:50:55 -0400 IronPort-SDR: CL9dOmAUyumlRHlyqJ8guF3MDWmtmGZUT2KAHdf9LnWXFCF6DgUd87BU9ncrDokFWt1DlCWGoL 5qqdQ4esDYpw== X-IronPort-AV: E=McAfee;i="6000,8403,9704"; a="237470643" X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="237470643" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2020 10:44:59 -0700 IronPort-SDR: a81zaGdrVDutwySX5zxfF//JtmG8/9BO72B40fk34+HayY2HE6IbNwS80ojI0nVejq84nTWx1X tEHZt0ZU+Mmg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="437245739" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.189]) by orsmga004.jf.intel.com with ESMTP; 05 Aug 2020 10:44:59 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v4 05/10] mesh: Clean up handling of config net and app key messages Date: Wed, 5 Aug 2020 10:44:51 -0700 Message-Id: <20200805174456.49342-6-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200805174456.49342-1-inga.stotland@intel.com> References: <20200805174456.49342-1-inga.stotland@intel.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This modification allows using a single point for sending out the composed status messages by the Config Server. --- mesh/cfgmod-server.c | 147 ++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 72 deletions(-) diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index 57646543d..030f9e744 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -547,6 +547,73 @@ static void node_reset(void *user_data) node_remove(node); } +static uint16_t cfg_appkey_msg(struct mesh_node *node, const uint8_t *pkt, + int opcode) +{ + uint16_t n_idx, a_idx, n; + struct mesh_net *net = node_get_net(node); + + n_idx = l_get_le16(pkt) & 0xfff; + a_idx = l_get_le16(pkt + 1) >> 4; + + n = mesh_model_opcode_set(OP_APPKEY_STATUS, msg); + + if (opcode == OP_APPKEY_ADD) + msg[n] = appkey_key_add(net, n_idx, a_idx, pkt + 3); + else if (opcode == OP_APPKEY_UPDATE) + msg[n] = appkey_key_update(net, n_idx, a_idx, pkt + 3); + else + msg[n] = appkey_key_delete(net, n_idx, a_idx); + + l_debug("AppKey Command %s: Net_Idx %3.3x, App_Idx %3.3x", + (msg[n] == MESH_STATUS_SUCCESS) ? "success" : "fail", + n_idx, a_idx); + + memcpy(msg + n + 1, &pkt[0], 3); + + return n + 4; +} + +static uint16_t cfg_netkey_msg(struct mesh_node *node, const uint8_t *pkt, + int opcode) +{ + uint16_t n_idx, n; + struct mesh_net *net = node_get_net(node); + + n_idx = l_get_le16(pkt); + n = mesh_model_opcode_set(OP_NETKEY_STATUS, msg); + + if (opcode == OP_NETKEY_ADD) + msg[n] = mesh_net_add_key(net, n_idx, pkt + 2); + else if (opcode == OP_NETKEY_UPDATE) + msg[n] = mesh_net_update_key(net, n_idx, pkt + 2); + else + msg[n] = mesh_net_del_key(net, n_idx); + + l_debug("NetKey Command %s: Net_Idx %3.3x", + (msg[n] == MESH_STATUS_SUCCESS) ? "success" : "fail", + n_idx); + + memcpy(msg + n + 1, &pkt[0], 2); + + return n + 3; +} + +static uint16_t cfg_get_appkeys_msg(struct mesh_node *node, const uint8_t *pkt) +{ + uint16_t n_idx, sz, n; + + n_idx = l_get_le16(pkt); + + n = mesh_model_opcode_set(OP_APPKEY_LIST, msg); + l_put_le16(n_idx, msg + n + 1); + + msg[n] = appkey_list(node_get_net(node), n_idx, msg + n + 3, + MAX_MSG_LEN - (n + 3), &sz); + + return n + 3 + sz; +} + static uint16_t get_composition(struct mesh_node *node, uint8_t page, uint8_t *buf) { @@ -585,7 +652,7 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, uint32_t opcode, tmp32; int b_res = MESH_STATUS_SUCCESS; struct mesh_net_heartbeat *hb; - uint16_t n_idx, a_idx; + uint16_t n_idx; uint8_t state, status; uint8_t phase; bool virt = false; @@ -856,60 +923,19 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, if (size != 19) return true; - n_idx = l_get_le16(pkt) & 0xfff; - a_idx = l_get_le16(pkt + 1) >> 4; - - if (opcode == OP_APPKEY_ADD) - b_res = appkey_key_add(net, n_idx, a_idx, pkt + 3); - else - b_res = appkey_key_update(net, n_idx, a_idx, - pkt + 3); - - l_debug("Add/Update AppKey %s: Net_Idx %3.3x, App_Idx %3.3x", - (b_res == MESH_STATUS_SUCCESS) ? "success" : "fail", - n_idx, a_idx); - - - n = mesh_model_opcode_set(OP_APPKEY_STATUS, msg); - - msg[n++] = b_res; - msg[n++] = pkt[0]; - msg[n++] = pkt[1]; - msg[n++] = pkt[2]; - break; - + /* Fall Through */ case OP_APPKEY_DELETE: - if (size != 3) + if (opcode == OP_APPKEY_DELETE && size != 3) return true; - n_idx = l_get_le16(pkt) & 0xfff; - a_idx = l_get_le16(pkt + 1) >> 4; - b_res = appkey_key_delete(net, n_idx, a_idx); - l_debug("Delete AppKey %s Net_Idx %3.3x to App_Idx %3.3x", - (b_res == MESH_STATUS_SUCCESS) ? "success" : "fail", - n_idx, a_idx); - - n = mesh_model_opcode_set(OP_APPKEY_STATUS, msg); - msg[n++] = b_res; - msg[n++] = pkt[0]; - msg[n++] = pkt[1]; - msg[n++] = pkt[2]; + n = cfg_appkey_msg(node, pkt, opcode); break; case OP_APPKEY_GET: if (size != 2) return true; - n_idx = l_get_le16(pkt); - - n = mesh_model_opcode_set(OP_APPKEY_LIST, msg); - - status = appkey_list(net, n_idx, msg + n + 3, - MAX_MSG_LEN - n - 3, &size); - - msg[n] = status; - l_put_le16(n_idx, msg + n + 1); - n += (size + 3); + n = cfg_get_appkeys_msg(node, pkt); break; case OP_NETKEY_ADD: @@ -917,35 +943,12 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, if (size != 18) return true; - n_idx = l_get_le16(pkt); - - if (opcode == OP_NETKEY_ADD) - b_res = mesh_net_add_key(net, n_idx, pkt + 2); - else - b_res = mesh_net_update_key(net, n_idx, pkt + 2); - - l_debug("NetKey Add/Update %s", - (b_res == MESH_STATUS_SUCCESS) ? "success" : "fail"); - - n = mesh_model_opcode_set(OP_NETKEY_STATUS, msg); - msg[n++] = b_res; - l_put_le16(l_get_le16(pkt), msg + n); - n += 2; - break; - + /* Fall Through */ case OP_NETKEY_DELETE: - if (size != 2) + if (opcode == OP_NETKEY_DELETE && size != 2) return true; - b_res = mesh_net_del_key(net, l_get_le16(pkt)); - - l_debug("NetKey delete %s", - (b_res == MESH_STATUS_SUCCESS) ? "success" : "fail"); - - n = mesh_model_opcode_set(OP_NETKEY_STATUS, msg); - msg[n++] = b_res; - l_put_le16(l_get_le16(pkt), msg + n); - n += 2; + n = cfg_netkey_msg(node, pkt, opcode); break; case OP_NETKEY_GET: From patchwork Wed Aug 5 17:44:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252911 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C2C3BC433DF for ; Wed, 5 Aug 2020 19:21:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AD8232075D for ; Wed, 5 Aug 2020 19:21:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728868AbgHETUn (ORCPT ); Wed, 5 Aug 2020 15:20:43 -0400 Received: from mga05.intel.com ([192.55.52.43]:42221 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728989AbgHERrb (ORCPT ); Wed, 5 Aug 2020 13:47:31 -0400 IronPort-SDR: vb2gEmlZG6KKkEMFjhFQjALxpnX5K5lzEwoAumx0lBC4pAnMeXYVCPKXzuf9iu5K45u8PQKLwb LRvVPR6by+6g== X-IronPort-AV: E=McAfee;i="6000,8403,9704"; a="237470666" X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="237470666" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2020 10:45:01 -0700 IronPort-SDR: HXkJqGMiCRMqe4Diix6MVCo3h0L9bv7IxvbKs9UY7roFHr0VguEKsCFzEWmAk3RbBkGhbD26SK dVIN/9nlsFlQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="437245771" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.189]) by orsmga004.jf.intel.com with ESMTP; 05 Aug 2020 10:45:01 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v4 08/10] mesh: Clean up handling of config net transmit messages Date: Wed, 5 Aug 2020 10:44:54 -0700 Message-Id: <20200805174456.49342-9-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200805174456.49342-1-inga.stotland@intel.com> References: <20200805174456.49342-1-inga.stotland@intel.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This modification allows using a single point for sending out the composed status messages by the Config Server. --- mesh/cfgmod-server.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index 9b1375317..5b3ed3d97 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -657,6 +657,28 @@ static uint16_t cfg_poll_timeout_msg(struct mesh_node *node, const uint8_t *pkt) return n; } +static uint16_t cfg_net_tx_msg(struct mesh_node *node, const uint8_t *pkt, + int opcode) +{ + uint8_t cnt; + uint16_t interval, n; + struct mesh_net *net = node_get_net(node); + + cnt = (pkt[0] & 0x7) + 1; + interval = ((pkt[0] >> 3) + 1) * 10; + + if (opcode == OP_CONFIG_NETWORK_TRANSMIT_SET && + mesh_config_write_net_transmit(node_config_get(node), + cnt, interval)) + mesh_net_transmit_params_set(net, cnt, interval); + + n = mesh_model_opcode_set(OP_CONFIG_NETWORK_TRANSMIT_STATUS, msg); + + mesh_net_transmit_params_get(net, &cnt, &interval); + msg[n++] = (cnt - 1) + ((interval/10 - 1) << 3); + return n; +} + static uint16_t get_composition(struct mesh_node *node, uint8_t page, uint8_t *buf) { @@ -699,8 +721,6 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, uint8_t state, status; uint8_t phase; bool virt = false; - uint8_t count; - uint16_t interval; uint16_t n; if (app_idx != APP_IDX_DEV_LOCAL) @@ -821,25 +841,13 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, case OP_CONFIG_NETWORK_TRANSMIT_SET: if (size != 1) return true; - - count = (pkt[0] & 0x7) + 1; - interval = ((pkt[0] >> 3) + 1) * 10; - - if (mesh_config_write_net_transmit(node_config_get(node), count, - interval)) - mesh_net_transmit_params_set(net, count, interval); /* Fall Through */ case OP_CONFIG_NETWORK_TRANSMIT_GET: if (opcode == OP_CONFIG_NETWORK_TRANSMIT_GET && size != 0) return true; - n = mesh_model_opcode_set(OP_CONFIG_NETWORK_TRANSMIT_STATUS, - msg); - mesh_net_transmit_params_get(net, &count, &interval); - msg[n++] = (count - 1) + ((interval/10 - 1) << 3); - - l_debug("Get/Set Network Transmit Config"); + n = cfg_net_tx_msg(node, pkt, opcode); break; case OP_CONFIG_PROXY_SET: From patchwork Wed Aug 5 17:44:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252912 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A222FC433E3 for ; Wed, 5 Aug 2020 19:20:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 88F672075D for ; Wed, 5 Aug 2020 19:20:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728586AbgHETUa (ORCPT ); Wed, 5 Aug 2020 15:20:30 -0400 Received: from mga05.intel.com ([192.55.52.43]:42218 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729011AbgHERsd (ORCPT ); Wed, 5 Aug 2020 13:48:33 -0400 IronPort-SDR: Q5E0MYTINo4cbxVY4MCN83I4ln99/V5qPyP+lbfb5C4cIjZhsnkd1JBv0SUqPQ0DToxuIq31cB +HLEt8HcJPKw== X-IronPort-AV: E=McAfee;i="6000,8403,9704"; a="237470672" X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="237470672" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2020 10:45:02 -0700 IronPort-SDR: +MZaZ9ic0ukh830t1xE74snLMpFxy5pkt+TGb5EArAMw8zgeONk+hPcjaLTrMLRThC4QhdXhce liTCv5OH0y2Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="437245790" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.189]) by orsmga004.jf.intel.com with ESMTP; 05 Aug 2020 10:45:02 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v4 09/10] mesh: Clean up handling of config KR phase messages Date: Wed, 5 Aug 2020 10:44:55 -0700 Message-Id: <20200805174456.49342-10-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200805174456.49342-1-inga.stotland@intel.com> References: <20200805174456.49342-1-inga.stotland@intel.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This modification allows using a single point for sending out the composed status messages by the Config Server. Also, this checks for the correct relationship between KR transition and KR phase values. Correct error codes are sent on unsuccessful requests and malformed requests are ignored. --- mesh/cfgmod-server.c | 68 +++++++++++++++++++++++++++----------------- mesh/mesh-defs.h | 3 ++ mesh/net.c | 53 ++++++++++++---------------------- mesh/net.h | 4 +-- 4 files changed, 65 insertions(+), 63 deletions(-) diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index 5b3ed3d97..98c04dde7 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -420,6 +420,43 @@ static uint16_t cfg_relay_msg(struct mesh_node *node, const uint8_t *pkt, return n; } +static uint16_t cfg_key_refresh_phase(struct mesh_node *node, + const uint8_t *pkt, int opcode) +{ + struct mesh_net *net = node_get_net(node); + uint16_t n, idx = l_get_le16(pkt); + uint8_t phase; + int status; + + n = mesh_model_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_STATUS, msg); + status = mesh_net_key_refresh_phase_get(net, idx, &phase); + + if (status == MESH_STATUS_SUCCESS && + opcode == OP_CONFIG_KEY_REFRESH_PHASE_SET) { + + if (pkt[2] == KEY_REFRESH_TRANS_TWO) { + if (phase == KEY_REFRESH_PHASE_TWO) + goto done; + else if (phase != KEY_REFRESH_PHASE_ONE) + return 0; + } + + status = mesh_net_key_refresh_phase_set(net, idx, pkt[2]); + l_debug("Set KR Phase: net=%3.3x transition=%d", idx, pkt[2]); + + if (status == MESH_STATUS_SUCCESS) + mesh_net_key_refresh_phase_get(net, idx, &phase); + } + +done: + msg[n] = status; + l_put_le16(idx, msg + n); + msg[n + 2] = (status != MESH_STATUS_SUCCESS) ? + KEY_REFRESH_PHASE_NONE : phase; + + return n + 3; +} + static void hb_pub_timeout_func(struct l_timeout *timeout, void *user_data) { struct mesh_net *net = user_data; @@ -718,8 +755,7 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, int b_res = MESH_STATUS_SUCCESS; struct mesh_net_heartbeat *hb; uint16_t n_idx; - uint8_t state, status; - uint8_t phase; + uint8_t state; bool virt = false; uint16_t n; @@ -926,37 +962,17 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, break; case OP_CONFIG_KEY_REFRESH_PHASE_SET: - if (size != 3 || pkt[2] > 0x03) + if (size != 3 || (pkt[2] != KEY_REFRESH_TRANS_THREE && + pkt[2] != KEY_REFRESH_TRANS_TWO)) return true; - b_res = mesh_net_key_refresh_phase_set(net, l_get_le16(pkt), - pkt[2]); - size = 2; /* Fall Through */ case OP_CONFIG_KEY_REFRESH_PHASE_GET: - if (size != 2) + if (size != 2 && opcode == OP_CONFIG_KEY_REFRESH_PHASE_GET) return true; - n_idx = l_get_le16(pkt); - - n = mesh_model_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_STATUS, - msg); - - /* State: 0x00-0x03 phase of key refresh */ - status = mesh_net_key_refresh_phase_get(net, n_idx, - &phase); - if (status != MESH_STATUS_SUCCESS) { - b_res = status; - phase = KEY_REFRESH_PHASE_NONE; - } - - msg[n++] = b_res; - l_put_le16(n_idx, msg + n); - n += 2; - msg[n++] = phase; - - l_debug("Get/Set Key Refresh State (%d)", msg[n-1]); + n = cfg_key_refresh_phase(node, pkt, opcode); break; case OP_APPKEY_ADD: diff --git a/mesh/mesh-defs.h b/mesh/mesh-defs.h index bbde53303..6ceeb73f5 100644 --- a/mesh/mesh-defs.h +++ b/mesh/mesh-defs.h @@ -36,6 +36,9 @@ #define KEY_REFRESH_PHASE_TWO 0x02 #define KEY_REFRESH_PHASE_THREE 0x03 +#define KEY_REFRESH_TRANS_TWO 0x02 +#define KEY_REFRESH_TRANS_THREE 0x03 + #define DEFAULT_TTL 0xff #define TTL_MASK 0x7f diff --git a/mesh/net.c b/mesh/net.c index b54c647cb..9b4454fee 100644 --- a/mesh/net.c +++ b/mesh/net.c @@ -2433,6 +2433,10 @@ static int key_refresh_phase_two(struct mesh_net *net, uint16_t idx) return MESH_STATUS_INVALID_NETKEY; l_debug("Key refresh procedure phase 2: start using new net TX keys"); + + if (subnet->kr_phase == KEY_REFRESH_PHASE_TWO) + return MESH_STATUS_SUCCESS; + subnet->key_refresh = 1; subnet->net_key_tx = subnet->net_key_upd; /* @@ -2445,8 +2449,9 @@ static int key_refresh_phase_two(struct mesh_net *net, uint16_t idx) l_queue_foreach(net->friends, frnd_kr_phase2, net); - mesh_config_net_key_set_phase(node_config_get(net->node), idx, - KEY_REFRESH_PHASE_TWO); + if (!mesh_config_net_key_set_phase(node_config_get(net->node), idx, + KEY_REFRESH_PHASE_TWO)) + return MESH_STATUS_STORAGE_FAIL; return MESH_STATUS_SUCCESS; } @@ -2479,8 +2484,9 @@ static int key_refresh_finish(struct mesh_net *net, uint16_t idx) l_queue_foreach(net->friends, frnd_kr_phase3, net); - mesh_config_net_key_set_phase(node_config_get(net->node), idx, - KEY_REFRESH_PHASE_NONE); + if (!mesh_config_net_key_set_phase(node_config_get(net->node), idx, + KEY_REFRESH_PHASE_NONE)) + return MESH_STATUS_STORAGE_FAIL; return MESH_STATUS_SUCCESS; } @@ -3168,45 +3174,22 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id, send_msg_pkt(net, pkt, pkt_len + 1); } -uint8_t mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t idx, +int mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t idx, uint8_t transition) { - struct mesh_subnet *subnet; - - if (!net) - return MESH_STATUS_UNSPECIFIED_ERROR; - - subnet = l_queue_find(net->subnets, match_key_index, - L_UINT_TO_PTR(idx)); - if (!subnet) - return MESH_STATUS_INVALID_NETKEY; - - if (transition == subnet->kr_phase) - return MESH_STATUS_SUCCESS; + switch (transition) { + case KEY_REFRESH_TRANS_TWO: + return key_refresh_phase_two(net, idx); - if ((transition != 2 && transition != 3) || - transition < subnet->kr_phase) - return MESH_STATUS_CANNOT_SET; + case KEY_REFRESH_TRANS_THREE: + return key_refresh_finish(net, idx); - switch (transition) { - case 2: - if (key_refresh_phase_two(net, idx) - != MESH_STATUS_SUCCESS) - return MESH_STATUS_CANNOT_SET; - break; - case 3: - if (key_refresh_finish(net, idx) - != MESH_STATUS_SUCCESS) - return MESH_STATUS_CANNOT_SET; - break; default: - return MESH_STATUS_CANNOT_SET; + return MESH_STATUS_UNSPECIFIED_ERROR; } - - return MESH_STATUS_SUCCESS; } -uint8_t mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t idx, +int mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t idx, uint8_t *phase) { struct mesh_subnet *subnet; diff --git a/mesh/net.h b/mesh/net.h index 2673b895a..3d374280f 100644 --- a/mesh/net.h +++ b/mesh/net.h @@ -320,9 +320,9 @@ void mesh_friend_sub_add(struct mesh_net *net, uint16_t lpn, uint8_t ele_cnt, const uint8_t *list); void mesh_friend_sub_del(struct mesh_net *net, uint16_t lpn, uint8_t cnt, const uint8_t *del_list); -uint8_t mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t net_idx, +int mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t net_idx, uint8_t transition); -uint8_t mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t net_idx, +int mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t net_idx, uint8_t *phase); void mesh_net_send_seg(struct mesh_net *net, uint32_t key_id, uint32_t iv_index, uint8_t ttl, uint32_t seq, From patchwork Wed Aug 5 17:44:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252913 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF1F2C433E0 for ; Wed, 5 Aug 2020 19:20:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CF5A42075A for ; Wed, 5 Aug 2020 19:20:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728146AbgHETUQ (ORCPT ); Wed, 5 Aug 2020 15:20:16 -0400 Received: from mga05.intel.com ([192.55.52.43]:42221 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728993AbgHERsu (ORCPT ); Wed, 5 Aug 2020 13:48:50 -0400 IronPort-SDR: RLh1ZHCg3Zj5wL6y2bWc1PxR9FWvMGHiPK0vfhu3QPJiwLswJhX0xOscgqWJyF9Zh/OmEaGMwj lyPDu2E7AvAw== X-IronPort-AV: E=McAfee;i="6000,8403,9704"; a="237470677" X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="237470677" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2020 10:45:03 -0700 IronPort-SDR: U25lcw8gnejGnT7Sl7TNPH+p+LCBftht2W67RkExKa1jwR+ha3vhvtgC9R6Ilejjq+haJISkxw Rk147iy6U4Og== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,438,1589266800"; d="scan'208";a="437245800" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.189]) by orsmga004.jf.intel.com with ESMTP; 05 Aug 2020 10:45:02 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v4 10/10] mesh: Refactor heartbeat pub/sub Date: Wed, 5 Aug 2020 10:44:56 -0700 Message-Id: <20200805174456.49342-11-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200805174456.49342-1-inga.stotland@intel.com> References: <20200805174456.49342-1-inga.stotland@intel.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Move heartbeat publication/subscription timers and housekeeping to net.c since this is where the trigger events and control messages are handled. Configuration server (cfgmod-server.c) stays responsible for parsing the set pub/sub message parameters and assemblying the pub/sub status messages. Also, make sure that the correct message status is reported. --- mesh/cfgmod-server.c | 307 ++++++++++++++----------------------------- mesh/net.c | 273 ++++++++++++++++++++++++++++---------- mesh/net.h | 48 ++++--- 3 files changed, 328 insertions(+), 300 deletions(-) diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index 98c04dde7..25632abeb 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -457,50 +457,6 @@ done: return n + 3; } -static void hb_pub_timeout_func(struct l_timeout *timeout, void *user_data) -{ - struct mesh_net *net = user_data; - struct mesh_net_heartbeat *hb = mesh_net_heartbeat_get(net); - - mesh_net_heartbeat_send(net); - - if (hb->pub_count != 0xffff) - hb->pub_count--; - if (hb->pub_count > 0) - l_timeout_modify(hb->pub_timer, hb->pub_period); - else { - l_timeout_remove(hb->pub_timer); - hb->pub_timer = NULL; - } -} - -static void update_hb_pub_timer(struct mesh_net *net, - struct mesh_net_heartbeat *hb) -{ - if (IS_UNASSIGNED(hb->pub_dst) || hb->pub_count == 0) { - l_timeout_remove(hb->pub_timer); - hb->pub_timer = NULL; - return; - } - - if (!hb->pub_timer) - hb->pub_timer = l_timeout_create(hb->pub_period, - hb_pub_timeout_func, net, NULL); - else - l_timeout_modify(hb->pub_timer, hb->pub_period); -} - -static void hb_sub_timeout_func(struct l_timeout *timeout, void *user_data) -{ - struct mesh_net *net = user_data; - struct mesh_net_heartbeat *hb = mesh_net_heartbeat_get(net); - - l_debug("HB Subscription Ended"); - l_timeout_remove(hb->sub_timer); - hb->sub_timer = NULL; - hb->sub_enabled = false; -} - static uint8_t uint32_to_log(uint32_t value) { uint32_t val = 1; @@ -519,85 +475,112 @@ static uint8_t uint32_to_log(uint32_t value) return ret; } -static uint32_t log_to_uint32(uint8_t log, uint8_t offset) +static uint16_t hb_subscription_get(struct mesh_node *node, int status) { - if (!log) - return 0x0000; - else if (log > 0x11) - return 0xffff; + struct mesh_net *net = node_get_net(node); + struct mesh_net_heartbeat_sub *sub = mesh_net_get_heartbeat_sub(net); + struct timeval time_now; + uint16_t n; + + gettimeofday(&time_now, NULL); + time_now.tv_sec -= sub->start; + + if (time_now.tv_sec >= (long int) sub->period) + time_now.tv_sec = 0; else - return (1 << (log - offset)); -} + time_now.tv_sec = sub->period - time_now.tv_sec; + + l_debug("Sub Period (Log %2.2x) %d sec", uint32_to_log(time_now.tv_sec), + (int) time_now.tv_sec); + + n = mesh_model_opcode_set(OP_CONFIG_HEARTBEAT_SUB_STATUS, msg); + msg[n++] = status; + l_put_le16(sub->src, msg + n); + n += 2; + l_put_le16(sub->dst, msg + n); + n += 2; + msg[n++] = uint32_to_log(time_now.tv_sec); + msg[n++] = uint32_to_log(sub->count); + msg[n++] = sub->count ? sub->min_hops : 0; + msg[n++] = sub->max_hops; + return n; +} -static int hb_subscription_set(struct mesh_net *net, uint16_t src, - uint16_t dst, uint8_t period_log) +static uint16_t hb_subscription_set(struct mesh_node *node, const uint8_t *pkt) { - struct mesh_net_heartbeat *hb = mesh_net_heartbeat_get(net); - struct timeval time_now; + uint16_t src, dst; + uint8_t period_log; + struct mesh_net *net; + int status; + + src = l_get_le16(pkt); + dst = l_get_le16(pkt + 2); /* SRC must be Unicast, DST can be any legal address except Virtual */ if ((!IS_UNASSIGNED(src) && !IS_UNICAST(src)) || IS_VIRTUAL(dst)) - return -1; - - /* Check if the subscription should be disabled */ - if (IS_UNASSIGNED(src) || IS_UNASSIGNED(dst)) { - if (IS_GROUP(hb->sub_dst)) - mesh_net_dst_unreg(net, hb->sub_dst); - - l_timeout_remove(hb->sub_timer); - hb->sub_timer = NULL; - hb->sub_enabled = false; - hb->sub_dst = UNASSIGNED_ADDRESS; - hb->sub_src = UNASSIGNED_ADDRESS; - hb->sub_count = 0; - hb->sub_period = 0; - hb->sub_min_hops = 0; - hb->sub_max_hops = 0; - return MESH_STATUS_SUCCESS; - - } else if (!period_log && src == hb->sub_src && dst == hb->sub_dst) { - /* Preserve collected data, but disable */ - l_timeout_remove(hb->sub_timer); - hb->sub_timer = NULL; - hb->sub_enabled = false; - hb->sub_period = 0; - return MESH_STATUS_SUCCESS; - } + return 0; - if (hb->sub_dst != dst) { - if (IS_GROUP(hb->sub_dst)) - mesh_net_dst_unreg(net, hb->sub_dst); - if (IS_GROUP(dst)) - mesh_net_dst_reg(net, dst); - } + period_log = pkt[4]; - hb->sub_enabled = !!period_log; - hb->sub_src = src; - hb->sub_dst = dst; - hb->sub_count = 0; - hb->sub_period = log_to_uint32(period_log, 1); - hb->sub_min_hops = 0x00; - hb->sub_max_hops = 0x00; + if (period_log > 0x11) + return 0; - gettimeofday(&time_now, NULL); - hb->sub_start = time_now.tv_sec; + net = node_get_net(node); - if (!hb->sub_enabled) { - l_timeout_remove(hb->sub_timer); - hb->sub_timer = NULL; - return MESH_STATUS_SUCCESS; - } + status = mesh_net_set_heartbeat_sub(net, src, dst, period_log); - hb->sub_min_hops = 0xff; + return hb_subscription_get(node, status); +} - if (!hb->sub_timer) - hb->sub_timer = l_timeout_create(hb->sub_period, - hb_sub_timeout_func, net, NULL); - else - l_timeout_modify(hb->sub_timer, hb->sub_period); +static uint16_t hb_publication_get(struct mesh_node *node, int status) +{ + struct mesh_net *net = node_get_net(node); + struct mesh_net_heartbeat_pub *pub = mesh_net_get_heartbeat_pub(net); + uint16_t n; - return MESH_STATUS_SUCCESS; + n = mesh_model_opcode_set(OP_CONFIG_HEARTBEAT_PUB_STATUS, msg); + msg[n++] = status; + l_put_le16(pub->dst, msg + n); + n += 2; + msg[n++] = uint32_to_log(pub->count); + msg[n++] = uint32_to_log(pub->period); + msg[n++] = pub->ttl; + l_put_le16(pub->features, msg + n); + n += 2; + l_put_le16(pub->net_idx, msg + n); + n += 2; + + return n; +} + +static uint16_t hb_publication_set(struct mesh_node *node, const uint8_t *pkt) +{ + uint16_t dst, features, net_idx; + uint8_t period_log, count_log, ttl; + struct mesh_net *net; + int status; + + dst = l_get_le16(pkt); + count_log = pkt[2]; + period_log = pkt[3]; + ttl = pkt[4]; + + if (count_log > 0x11 && count_log != 0xff) + return 0; + + if (period_log > 0x11 || ttl > TTL_MASK || IS_VIRTUAL(dst)) + return 0; + + features = l_get_le16(pkt + 5) & 0xf; + net_idx = l_get_le16(pkt + 7); + + net = node_get_net(node); + + status = mesh_net_set_heartbeat_pub(net, dst, features, net_idx, ttl, + count_log, period_log); + + return hb_publication_get(node, status); } static void node_reset(void *user_data) @@ -750,10 +733,7 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, struct mesh_node *node = (struct mesh_node *) user_data; struct mesh_net *net; const uint8_t *pkt = data; - struct timeval time_now; uint32_t opcode; - int b_res = MESH_STATUS_SUCCESS; - struct mesh_net_heartbeat *hb; uint16_t n_idx; uint8_t state; bool virt = false; @@ -769,7 +749,7 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, return false; net = node_get_net(node); - hb = mesh_net_heartbeat_get(net); + l_debug("CONFIG-SRV-opcode 0x%x size %u idx %3.3x", opcode, size, net_idx); @@ -1043,113 +1023,35 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, break; case OP_CONFIG_HEARTBEAT_PUB_SET: - l_debug("OP_CONFIG_HEARTBEAT_PUB_SET"); + l_debug("Config Heartbeat Publication Set"); if (size != 9) return true; - if (pkt[2] > 0x11 || pkt[3] > 0x10 || pkt[4] > 0x7f) - return true; - else if (IS_VIRTUAL(l_get_le16(pkt))) - b_res = MESH_STATUS_INVALID_ADDRESS; - else if (l_get_le16(pkt + 7) != mesh_net_get_primary_idx(net)) - /* Future work: check for valid subnets */ - b_res = MESH_STATUS_INVALID_NETKEY; - - n = mesh_model_opcode_set(OP_CONFIG_HEARTBEAT_PUB_STATUS, - msg); - msg[n++] = b_res; - - memcpy(&msg[n], pkt, 9); - - /* Ignore RFU bits in features */ - l_put_le16(l_get_le16(pkt + 5) & 0xf, &msg[n + 5]); - - /* Add octet count to status */ - n += 9; - - if (b_res != MESH_STATUS_SUCCESS) - break; - - hb->pub_dst = l_get_le16(pkt); - if (hb->pub_dst == UNASSIGNED_ADDRESS || - pkt[2] == 0 || pkt[3] == 0) { - /* - * We might still have a pub_dst here in case - * we need it for State Change heartbeat - */ - hb->pub_count = 0; - hb->pub_period = 0; - } else { - hb->pub_count = (pkt[2] != 0xff) ? - log_to_uint32(pkt[2], 1) : 0xffff; - hb->pub_period = log_to_uint32(pkt[3], 1); - } - - hb->pub_ttl = pkt[4]; - hb->pub_features = l_get_le16(pkt + 5) & 0xf; - hb->pub_net_idx = l_get_le16(pkt + 7); - update_hb_pub_timer(net, hb); - + n = hb_publication_set(node, pkt); break; case OP_CONFIG_HEARTBEAT_PUB_GET: if (size != 0) return true; - n = mesh_model_opcode_set(OP_CONFIG_HEARTBEAT_PUB_STATUS, msg); - msg[n++] = b_res; - l_put_le16(hb->pub_dst, msg + n); - n += 2; - msg[n++] = uint32_to_log(hb->pub_count); - msg[n++] = uint32_to_log(hb->pub_period); - msg[n++] = hb->pub_ttl; - l_put_le16(hb->pub_features, msg + n); - n += 2; - l_put_le16(hb->pub_net_idx, msg + n); - n += 2; + n = hb_publication_get(node, MESH_STATUS_SUCCESS); break; case OP_CONFIG_HEARTBEAT_SUB_SET: if (size != 5) return true; - l_debug("Set Sub Period (Log %2.2x) %d sec", - pkt[4], log_to_uint32(pkt[4], 1)); - - b_res = hb_subscription_set(net, l_get_le16(pkt), - l_get_le16(pkt + 2), - pkt[4]); - if (b_res < 0) - return true; + l_debug("Set HB Sub Period Log %2.2x", pkt[4]); - /* Fall through */ + n = hb_subscription_set(node, pkt); + break; case OP_CONFIG_HEARTBEAT_SUB_GET: - if (opcode == OP_CONFIG_HEARTBEAT_SUB_GET && size != 0) - return true; - - gettimeofday(&time_now, NULL); - time_now.tv_sec -= hb->sub_start; - if (time_now.tv_sec >= (long int) hb->sub_period) - time_now.tv_sec = 0; - else - time_now.tv_sec = hb->sub_period - time_now.tv_sec; - - l_debug("Sub Period (Log %2.2x) %d sec", - uint32_to_log(time_now.tv_sec), - (int) time_now.tv_sec); + if (size != 0) + return true; - n = mesh_model_opcode_set(OP_CONFIG_HEARTBEAT_SUB_STATUS, msg); - msg[n++] = b_res; - l_put_le16(hb->sub_src, msg + n); - n += 2; - l_put_le16(hb->sub_dst, msg + n); - n += 2; - msg[n++] = uint32_to_log(time_now.tv_sec); - msg[n++] = uint32_to_log(hb->sub_count); - msg[n++] = hb->sub_count ? hb->sub_min_hops : 0; - msg[n++] = hb->sub_max_hops; + n = hb_subscription_get(node, MESH_STATUS_SUCCESS); break; case OP_CONFIG_POLL_TIMEOUT_GET: @@ -1179,13 +1081,6 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, static void cfgmod_srv_unregister(void *user_data) { - struct mesh_node *node = user_data; - struct mesh_net *net = node_get_net(node); - struct mesh_net_heartbeat *hb = mesh_net_heartbeat_get(net); - - l_timeout_remove(hb->pub_timer); - l_timeout_remove(hb->sub_timer); - hb->pub_timer = hb->sub_timer = NULL; } static const struct mesh_model_ops ops = { diff --git a/mesh/net.c b/mesh/net.c index 9b4454fee..633727601 100644 --- a/mesh/net.c +++ b/mesh/net.c @@ -23,6 +23,8 @@ #define _GNU_SOURCE +#include + #include #include "mesh/mesh-defs.h" @@ -132,7 +134,10 @@ struct mesh_net { uint8_t count; } relay; - struct mesh_net_heartbeat heartbeat; + /* Heartbeat info */ + struct mesh_net_heartbeat_sub hb_sub; + struct mesh_net_heartbeat_pub hb_pub; + uint16_t features; struct l_queue *subnets; struct l_queue *msg_cache; @@ -255,35 +260,46 @@ static bool match_friend_key_id(const void *a, const void *b) (key_id == friend->net_key_upd); } -static void idle_mesh_heartbeat_send(void *net) +static void send_hb_publication(void *data) { - mesh_net_heartbeat_send(net); + struct mesh_net *net = data; + struct mesh_net_heartbeat_pub *pub = &net->hb_pub; + uint8_t msg[4]; + int n = 0; + + if (pub->dst == UNASSIGNED_ADDRESS) + return; + + msg[n++] = NET_OP_HEARTBEAT; + msg[n++] = pub->ttl; + l_put_be16(net->features, msg + n); + n += 2; + + mesh_net_transport_send(net, 0, 0, mesh_net_get_iv_index(net), + pub->ttl, 0, 0, pub->dst, msg, n); } static void trigger_heartbeat(struct mesh_net *net, uint16_t feature, - bool in_use) + bool enable) { - struct mesh_net_heartbeat *hb = &net->heartbeat; - - l_debug("%s: %4.4x --> %d", __func__, feature, in_use); + l_debug("HB: %4.4x --> %d", feature, enable); - if (in_use) { - if (net->heartbeat.features & feature) + if (enable) { + if (net->features & feature) return; /* no change */ - hb->features |= feature; + net->features |= feature; } else { - if (!(hb->features & feature)) + if (!(net->features & feature)) return; /* no change */ - hb->features &= ~feature; + net->features &= ~feature; } - if (!(hb->pub_features & feature)) - return; /* not interested in this feature */ - - l_idle_oneshot(idle_mesh_heartbeat_send, net, NULL); + if (!(net->hb_pub.features & feature)) + return; /* no interest in this feature */ + l_idle_oneshot(send_hb_publication, net, NULL); } static bool match_by_friend(const void *a, const void *b) @@ -616,8 +632,6 @@ struct mesh_net *mesh_net_new(struct mesh_node *node) net->destinations = l_queue_new(); net->app_keys = l_queue_new(); - memset(&net->heartbeat, 0, sizeof(net->heartbeat)); - if (!nets) nets = l_queue_new(); @@ -813,8 +827,8 @@ int mesh_net_del_key(struct mesh_net *net, uint16_t idx) appkey_delete_bound_keys(net, idx); /* Disable hearbeat publication on this subnet */ - if (idx == net->heartbeat.pub_net_idx) - net->heartbeat.pub_dst = UNASSIGNED_ADDRESS; + if (idx == net->hb_pub.net_idx) + net->hb_pub.dst = UNASSIGNED_ADDRESS; /* TODO: cancel beacon_enable on this subnet */ @@ -2017,25 +2031,23 @@ static bool ctl_received(struct mesh_net *net, uint16_t key_id, break; case NET_OP_HEARTBEAT: - if (net->heartbeat.sub_enabled && - src == net->heartbeat.sub_src) { + if (net->hb_sub.enabled && src == net->hb_sub.src) { uint8_t hops = pkt[0] - ttl + 1; print_packet("Rx-NET_OP_HEARTBEAT", pkt, len); - if (net->heartbeat.sub_count != 0xffff) - net->heartbeat.sub_count++; + if (net->hb_sub.count != 0xffff) + net->hb_sub.count++; - if (net->heartbeat.sub_min_hops > hops) - net->heartbeat.sub_min_hops = hops; + if (net->hb_sub.min_hops > hops) + net->hb_sub.min_hops = hops; - if (net->heartbeat.sub_max_hops < hops) - net->heartbeat.sub_max_hops = hops; + if (net->hb_sub.max_hops < hops) + net->hb_sub.max_hops = hops; l_debug("HB: cnt:%4.4x min:%2.2x max:%2.2x", - net->heartbeat.sub_count, - net->heartbeat.sub_min_hops, - net->heartbeat.sub_max_hops); + net->hb_sub.count, net->hb_sub.min_hops, + net->hb_sub.max_hops); } break; } @@ -3259,52 +3271,14 @@ int mesh_net_update_key(struct mesh_net *net, uint16_t idx, return MESH_STATUS_SUCCESS; } -static uint16_t get_features(struct mesh_net *net) -{ - uint16_t features = 0; - - if (net->relay.enable) - features |= FEATURE_RELAY; - - if (net->proxy_enable) - features |= FEATURE_PROXY; - - if (net->friend_enable) - features |= FEATURE_FRIEND; - - return features; -} - -struct mesh_net_heartbeat *mesh_net_heartbeat_get(struct mesh_net *net) -{ - return &net->heartbeat; -} - -void mesh_net_heartbeat_send(struct mesh_net *net) +struct mesh_net_heartbeat_sub *mesh_net_get_heartbeat_sub(struct mesh_net *net) { - struct mesh_net_heartbeat *hb = &net->heartbeat; - uint8_t msg[4]; - int n = 0; - - if (hb->pub_dst == UNASSIGNED_ADDRESS) - return; - - msg[n++] = NET_OP_HEARTBEAT; - msg[n++] = hb->pub_ttl; - l_put_be16(hb->features, msg + n); - n += 2; - - mesh_net_transport_send(net, 0, 0, mesh_net_get_iv_index(net), - hb->pub_ttl, 0, 0, hb->pub_dst, msg, n); + return &net->hb_sub; } -void mesh_net_heartbeat_init(struct mesh_net *net) +struct mesh_net_heartbeat_pub *mesh_net_get_heartbeat_pub(struct mesh_net *net) { - struct mesh_net_heartbeat *hb = &net->heartbeat; - - memset(hb, 0, sizeof(struct mesh_net_heartbeat)); - hb->sub_min_hops = 0xff; - hb->features = get_features(net); + return &net->hb_pub; } void mesh_net_set_iv_index(struct mesh_net *net, uint32_t index, bool update) @@ -3542,3 +3516,156 @@ void net_msg_add_replay_cache(struct mesh_net *net, uint16_t src, uint32_t seq, /* Optimize so that most recent conversations stay earliest in cache */ l_queue_push_head(net->replay_cache, rpe); } + +static void hb_sub_timeout_func(struct l_timeout *timeout, void *user_data) +{ + struct mesh_net *net = user_data; + struct mesh_net_heartbeat_sub *sub = &net->hb_sub; + + l_debug("HB Subscription Ended"); + l_timeout_remove(sub->timer); + sub->timer = NULL; + sub->enabled = false; +} + +static uint32_t log_to_uint32(uint8_t log) +{ + if (!log) + return 0x0000; + + return (1 << (log - 1)); +} + +int mesh_net_set_heartbeat_sub(struct mesh_net *net, uint16_t src, uint16_t dst, + uint8_t period_log) +{ + struct mesh_net_heartbeat_sub *sub = &net->hb_sub; + struct timeval time_now; + + if (!net) + return MESH_STATUS_UNSPECIFIED_ERROR; + + /* Check if the subscription should be disabled */ + if (IS_UNASSIGNED(src) || IS_UNASSIGNED(dst)) { + if (IS_GROUP(sub->dst)) + mesh_net_dst_unreg(net, sub->dst); + + sub->enabled = false; + sub->dst = UNASSIGNED_ADDRESS; + sub->src = UNASSIGNED_ADDRESS; + sub->count = 0; + sub->period = 0; + sub->min_hops = 0; + sub->max_hops = 0; + + } else if (!period_log && src == sub->src && dst == sub->dst) { + /* Preserve collected data, but disable */ + sub->enabled = false; + sub->period = 0; + + } else if (sub->dst != dst) { + if (IS_GROUP(sub->dst)) + mesh_net_dst_unreg(net, sub->dst); + + if (IS_GROUP(dst)) + mesh_net_dst_reg(net, dst); + + sub->enabled = !!period_log; + sub->src = src; + sub->dst = dst; + sub->count = 0; + sub->period = log_to_uint32(period_log); + sub->min_hops = 0x00; + sub->max_hops = 0x00; + gettimeofday(&time_now, NULL); + sub->start = time_now.tv_sec; + } + + /* TODO: Save to node config */ + + if (!sub->enabled) { + l_timeout_remove(sub->timer); + sub->timer = NULL; + return MESH_STATUS_SUCCESS; + } + + sub->min_hops = 0xff; + + if (!sub->timer) + sub->timer = l_timeout_create(sub->period, hb_sub_timeout_func, + net, NULL); + else + l_timeout_modify(sub->timer, sub->period); + + return MESH_STATUS_SUCCESS; +} + +static void hb_pub_timeout_func(struct l_timeout *timeout, void *user_data) +{ + struct mesh_net *net = user_data; + struct mesh_net_heartbeat_pub *pub = &net->hb_pub; + + send_hb_publication(net); + + if (pub->count != 0xffff) + pub->count--; + + if (pub->count > 0) + l_timeout_modify(pub->timer, pub->period); + else { + l_timeout_remove(pub->timer); + pub->timer = NULL; + } +} + +static void update_hb_pub_timer(struct mesh_net *net, + struct mesh_net_heartbeat_pub *pub) +{ + if (IS_UNASSIGNED(pub->dst) || pub->count == 0) { + l_timeout_remove(pub->timer); + pub->timer = NULL; + return; + } + + if (!pub->timer) + pub->timer = l_timeout_create(pub->period, + hb_pub_timeout_func, net, NULL); + else + l_timeout_modify(pub->timer, pub->period); +} + +int mesh_net_set_heartbeat_pub(struct mesh_net *net, uint16_t dst, + uint16_t features, uint16_t idx, uint8_t ttl, + uint8_t count_log, uint8_t period_log) +{ + struct mesh_subnet *subnet; + struct mesh_net_heartbeat_pub *pub = &net->hb_pub; + + if (!net) + return MESH_STATUS_UNSPECIFIED_ERROR; + + subnet = l_queue_find(net->subnets, match_key_index, + L_UINT_TO_PTR(idx)); + if (!subnet) + return MESH_STATUS_INVALID_NETKEY; + + pub->dst = dst; + + if (pub->dst == UNASSIGNED_ADDRESS) { + pub->count = 0; + pub->period = 0; + pub->ttl = 0; + } else { + pub->count = (count_log != 0xff) ? + log_to_uint32(count_log) : 0xffff; + pub->period = log_to_uint32(period_log); + } + + pub->ttl = ttl; + pub->features = features; + pub->net_idx = idx; + update_hb_pub_timer(net, pub); + + /* TODO: Save to node config */ + return MESH_STATUS_SUCCESS; +} diff --git a/mesh/net.h b/mesh/net.h index 3d374280f..91e07ef78 100644 --- a/mesh/net.h +++ b/mesh/net.h @@ -129,25 +129,27 @@ struct mesh_net_prov_caps { uint16_t input_action; } __packed; -struct mesh_net_heartbeat { - struct l_timeout *pub_timer; - struct l_timeout *sub_timer; - struct timeval sub_time; - bool sub_enabled; - uint32_t pub_period; - uint32_t sub_period; - uint32_t sub_start; - uint16_t pub_dst; - uint16_t pub_count; - uint16_t pub_features; +struct mesh_net_heartbeat_sub { + struct l_timeout *timer; + uint32_t start; + uint32_t period; uint16_t features; - uint16_t pub_net_idx; - uint16_t sub_src; - uint16_t sub_dst; - uint16_t sub_count; - uint8_t pub_ttl; - uint8_t sub_min_hops; - uint8_t sub_max_hops; + uint16_t src; + uint16_t dst; + uint16_t count; + bool enabled; + uint8_t min_hops; + uint8_t max_hops; +}; + +struct mesh_net_heartbeat_pub { + struct l_timeout *timer; + uint32_t period; + uint16_t dst; + uint16_t count; + uint16_t features; + uint16_t net_idx; + uint8_t ttl; }; struct mesh_key_set { @@ -328,9 +330,13 @@ void mesh_net_send_seg(struct mesh_net *net, uint32_t key_id, uint32_t iv_index, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dst, uint32_t hdr, const void *seg, uint16_t seg_len); -struct mesh_net_heartbeat *mesh_net_heartbeat_get(struct mesh_net *net); -void mesh_net_heartbeat_init(struct mesh_net *net); -void mesh_net_heartbeat_send(struct mesh_net *net); +struct mesh_net_heartbeat_sub *mesh_net_get_heartbeat_sub(struct mesh_net *net); +int mesh_net_set_heartbeat_sub(struct mesh_net *net, uint16_t src, uint16_t dst, + uint8_t period_log); +struct mesh_net_heartbeat_pub *mesh_net_get_heartbeat_pub(struct mesh_net *net); +int mesh_net_set_heartbeat_pub(struct mesh_net *net, uint16_t dst, + uint16_t features, uint16_t idx, uint8_t ttl, + uint8_t count_log, uint8_t period_log); bool mesh_net_key_list_get(struct mesh_net *net, uint8_t *buf, uint16_t *count); uint16_t mesh_net_get_primary_idx(struct mesh_net *net); uint32_t mesh_net_friend_timeout(struct mesh_net *net, uint16_t addr);