From patchwork Tue Aug 4 20:17:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252920 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 0D993C433E0 for ; Tue, 4 Aug 2020 20:17:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E1700207FC for ; Tue, 4 Aug 2020 20:17:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726580AbgHDURs (ORCPT ); Tue, 4 Aug 2020 16:17:48 -0400 Received: from mga09.intel.com ([134.134.136.24]:64989 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725981AbgHDURr (ORCPT ); Tue, 4 Aug 2020 16:17:47 -0400 IronPort-SDR: 65Qd8up8GwcOiaQJWWJeIDBMWwy9t9QNPJf3oUPi8Mlngoo7ky7VopwVn0M0s7ysb+dfAs2R9Y humhvfJqNHmA== X-IronPort-AV: E=McAfee;i="6000,8403,9703"; a="153565369" X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="153565369" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Aug 2020 13:17:46 -0700 IronPort-SDR: UfvKq+Z6u0vcQ7J4Qm/EdJsJp3283I0FX/vKgqLBHkc1z5PvaR99yTPaAhsvzrabmutLmLlkvw fKA+OaC/SuVw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="324783826" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.65]) by fmsmga002.fm.intel.com with ESMTP; 04 Aug 2020 13:17:46 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v3 02/10] mesh: Clean up handling of config model binding messages Date: Tue, 4 Aug 2020 13:17:36 -0700 Message-Id: <20200804201744.23327-2-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200804201744.23327-1-inga.stotland@intel.com> References: <20200804201744.23327-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 Tue Aug 4 20:17:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252919 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 7D0FFC433E3 for ; Tue, 4 Aug 2020 20:17:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6551A207FC for ; Tue, 4 Aug 2020 20:17:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726810AbgHDURt (ORCPT ); Tue, 4 Aug 2020 16:17:49 -0400 Received: from mga09.intel.com ([134.134.136.24]:64989 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726534AbgHDURs (ORCPT ); Tue, 4 Aug 2020 16:17:48 -0400 IronPort-SDR: QruiDq78fjaIlbxRNxYaTwQCzBEFD1B5jhfZUsy4OBco/beYh11cRtKYxH2EtDrm2GUkHgOGXf CbVbHPohtI8A== X-IronPort-AV: E=McAfee;i="6000,8403,9703"; a="153565377" X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="153565377" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Aug 2020 13:17:46 -0700 IronPort-SDR: 1v5ZKe0Eu8t3XtIK+GMdk/vgSrNPNWRdnPc1RU3YR/lLJbXb4eVIVNMZom93iuRjqyZZ8JOz2K +pqeEpsg4mxw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="324783831" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.65]) by fmsmga002.fm.intel.com with ESMTP; 04 Aug 2020 13:17:46 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v3 03/10] mesh: Clean up handling of config node identity message Date: Tue, 4 Aug 2020 13:17:37 -0700 Message-Id: <20200804201744.23327-3-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200804201744.23327-1-inga.stotland@intel.com> References: <20200804201744.23327-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 | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index 35d0325a9..c501b0a52 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -777,11 +777,7 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, break; case OP_NODE_IDENTITY_SET: - if (size != 3 || pkt[2] > 0x01) - return true; - - n_idx = l_get_le16(pkt); - if (n_idx > 0xfff) + if (size != 3) return true; /* Currently setting node identity not supported */ @@ -789,18 +785,13 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, /* Fall Through */ case OP_NODE_IDENTITY_GET: - if (size < 2) + if (opcode == OP_NODE_IDENTITY_GET && size != 2) return true; n_idx = l_get_le16(pkt); - if (n_idx > 0xfff) - return true; n = mesh_model_opcode_set(OP_NODE_IDENTITY_STATUS, msg); - - status = mesh_net_get_identity_mode(net, n_idx, &state); - - msg[n++] = status; + msg[n++] = mesh_net_get_identity_mode(net, n_idx, &state); l_put_le16(n_idx, msg + n); n += 2; From patchwork Tue Aug 4 20:17:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252918 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 602BCC433DF for ; Tue, 4 Aug 2020 20:17:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 50289207FC for ; Tue, 4 Aug 2020 20:17:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726927AbgHDURv (ORCPT ); Tue, 4 Aug 2020 16:17:51 -0400 Received: from mga09.intel.com ([134.134.136.24]:64991 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726804AbgHDURt (ORCPT ); Tue, 4 Aug 2020 16:17:49 -0400 IronPort-SDR: Y84rKC+WdpIY3/mwNE06/XNqOyKWhx49z9zytu6uDqDCWSGukSxbWcZP01FrEbm9aiOcBm9uJJ llQshrNDe3tg== X-IronPort-AV: E=McAfee;i="6000,8403,9703"; a="153565394" X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="153565394" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Aug 2020 13:17:48 -0700 IronPort-SDR: 8zBlRNszDlZ13myN52ktE+5K2fi+7V8QI3upRMXBsBid4aF3jr3hA+25iytvZybtlovWly4qRd /LuzoUtzFq9Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="324783846" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.65]) by fmsmga002.fm.intel.com with ESMTP; 04 Aug 2020 13:17:48 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v3 07/10] mesh: Clean up handling of config poll timeout message Date: Tue, 4 Aug 2020 13:17:41 -0700 Message-Id: <20200804201744.23327-7-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200804201744.23327-1-inga.stotland@intel.com> References: <20200804201744.23327-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 | 34 +++++++++++++++++++++++----------- mesh/cfgmod.h | 2 +- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index 6ca1c1dd1..9b1375317 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -638,6 +638,25 @@ static uint16_t cfg_get_appkeys_msg(struct mesh_node *node, const uint8_t *pkt) return n + 3 + sz; } +static uint16_t cfg_poll_timeout_msg(struct mesh_node *node, const uint8_t *pkt) +{ + uint16_t n, addr = l_get_le16(pkt); + uint32_t poll_to; + + if (!IS_UNICAST(addr)) + return 0; + + n = mesh_model_opcode_set(OP_CONFIG_POLL_TIMEOUT_STATUS, msg); + l_put_le16(addr, msg + n); + n += 2; + + poll_to = mesh_net_friend_timeout(node_get_net(node), addr); + msg[n++] = poll_to; + msg[n++] = poll_to >> 8; + msg[n++] = poll_to >> 16; + return n; +} + static uint16_t get_composition(struct mesh_node *node, uint8_t page, uint8_t *buf) { @@ -673,7 +692,7 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, struct mesh_net *net; const uint8_t *pkt = data; struct timeval time_now; - uint32_t opcode, tmp32; + uint32_t opcode; int b_res = MESH_STATUS_SUCCESS; struct mesh_net_heartbeat *hb; uint16_t n_idx; @@ -1109,18 +1128,11 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx, msg[n++] = hb->sub_max_hops; break; - case OP_CONFIG_POLL_TIMEOUT_LIST: - if (size != 2 || l_get_le16(pkt) == 0 || - l_get_le16(pkt) > 0x7fff) + case OP_CONFIG_POLL_TIMEOUT_GET: + if (size != 2) return true; - n = mesh_model_opcode_set(OP_CONFIG_POLL_TIMEOUT_STATUS, msg); - l_put_le16(l_get_le16(pkt), msg + n); - n += 2; - tmp32 = mesh_net_friend_timeout(net, l_get_le16(pkt)); - msg[n++] = tmp32; - msg[n++] = tmp32 >> 8; - msg[n++] = tmp32 >> 16; + n = cfg_poll_timeout_msg(node, pkt); break; case OP_NODE_RESET: diff --git a/mesh/cfgmod.h b/mesh/cfgmod.h index 7b6a95807..6d73656a7 100644 --- a/mesh/cfgmod.h +++ b/mesh/cfgmod.h @@ -66,7 +66,7 @@ #define OP_CONFIG_MODEL_SUB_LIST 0x802A #define OP_CONFIG_VEND_MODEL_SUB_GET 0x802B #define OP_CONFIG_VEND_MODEL_SUB_LIST 0x802C -#define OP_CONFIG_POLL_TIMEOUT_LIST 0x802D +#define OP_CONFIG_POLL_TIMEOUT_GET 0x802D #define OP_CONFIG_POLL_TIMEOUT_STATUS 0x802E /* Health opcodes in health-mod.h */ #define OP_CONFIG_HEARTBEAT_PUB_GET 0x8038 From patchwork Tue Aug 4 20:17:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252917 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 7A1D0C433DF for ; Tue, 4 Aug 2020 20:17:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6C6BD207FC for ; Tue, 4 Aug 2020 20:17:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726961AbgHDURw (ORCPT ); Tue, 4 Aug 2020 16:17:52 -0400 Received: from mga09.intel.com ([134.134.136.24]:64991 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726720AbgHDURu (ORCPT ); Tue, 4 Aug 2020 16:17:50 -0400 IronPort-SDR: W+t0JQX3978lC1+MtHDU7eh/BPLJZYIUL6ajf9H37i+0iGj3fNhtIKwDHvbA68WECrno9tc6tr lnsXl/sh2r8w== X-IronPort-AV: E=McAfee;i="6000,8403,9703"; a="153565397" X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="153565397" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Aug 2020 13:17:49 -0700 IronPort-SDR: pC75ObEXvPigEStMJPpDfrUKNWXNwTxviKjezXifrdK19TM7mnyvMjDT+6Wd/EXSPzHX6FvuBr 6I7+MKvF+DRA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="324783853" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.65]) by fmsmga002.fm.intel.com with ESMTP; 04 Aug 2020 13:17:49 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v3 09/10] mesh: Clean up handling of config KR phase messages Date: Tue, 4 Aug 2020 13:17:43 -0700 Message-Id: <20200804201744.23327-9-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200804201744.23327-1-inga.stotland@intel.com> References: <20200804201744.23327-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 | 55 +++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index 5b3ed3d97..5854f7a1c 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -420,6 +420,31 @@ 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; + + n = mesh_model_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_STATUS, msg); + + if (opcode == OP_CONFIG_KEY_REFRESH_PHASE_SET) { + phase = pkt[2]; + msg[n] = mesh_net_key_refresh_phase_set(net, idx, phase); + l_debug("Set KR Phase: net=%3.3x transition=%d", idx, phase); + } else { + msg[n] = mesh_net_key_refresh_phase_get(net, idx, &phase); + l_debug("Get KR Phase: net=%3.3x phase=%d", idx, phase); + } + + l_put_le16(idx, msg + n); + msg[n + 2] = (msg[n] != 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 +743,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 +950,16 @@ 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_PHASE_THREE) 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: From patchwork Tue Aug 4 20:17:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inga Stotland X-Patchwork-Id: 252916 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 5539EC433E0 for ; Tue, 4 Aug 2020 20:17:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3EB65207FC for ; Tue, 4 Aug 2020 20:17:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726963AbgHDURw (ORCPT ); Tue, 4 Aug 2020 16:17:52 -0400 Received: from mga09.intel.com ([134.134.136.24]:65000 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726861AbgHDURv (ORCPT ); Tue, 4 Aug 2020 16:17:51 -0400 IronPort-SDR: /r4LLgebyEGGxfUsbEsQ9I6fEzmitbGV765aa9CJyKfczDMmZ999Fjlp5ZbFHUB0y202KgM1JN bVWvmJXRzrrQ== X-IronPort-AV: E=McAfee;i="6000,8403,9703"; a="153565399" X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="153565399" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Aug 2020 13:17:50 -0700 IronPort-SDR: rKGEktD89CY9SMjnaWEwGk9YZLCX60jh912v8o7+jEUhWWJKigfRsyzso5WmeBg0QJ42wHqwoq 0rGfHv3xAprA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,434,1589266800"; d="scan'208";a="324783858" Received: from unknown (HELO ingas-nuc1.intel.com) ([10.254.118.65]) by fmsmga002.fm.intel.com with ESMTP; 04 Aug 2020 13:17:49 -0700 From: Inga Stotland To: linux-bluetooth@vger.kernel.org Cc: brian.gix@intel.com, Inga Stotland Subject: [PATCH BlueZ v3 10/10] mesh: Refactor heartbeat pub/sub Date: Tue, 4 Aug 2020 13:17:44 -0700 Message-Id: <20200804201744.23327-10-inga.stotland@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200804201744.23327-1-inga.stotland@intel.com> References: <20200804201744.23327-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 5854f7a1c..40ecec16a 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -445,50 +445,6 @@ static uint16_t cfg_key_refresh_phase(struct mesh_node *node, 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; @@ -507,85 +463,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); -static int hb_subscription_set(struct mesh_net *net, uint16_t src, - uint16_t dst, uint8_t period_log) + 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 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) @@ -738,10 +721,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; @@ -757,7 +737,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); @@ -1030,113 +1010,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: @@ -1166,13 +1068,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 b54c647cb..5bfaa181a 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; } @@ -3276,52 +3288,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) @@ -3559,3 +3533,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 2673b895a..6d707436e 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);