From patchwork Mon Oct 14 07:54:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junho Lee X-Patchwork-Id: 13834281 Received: from mail-pg1-f172.google.com (mail-pg1-f172.google.com [209.85.215.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B83C1384BF for ; Mon, 14 Oct 2024 07:54:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728892466; cv=none; b=rvx3ai+7ybas2b7LeTLoQoGsTdgMswGEkHuyV88M6Wo5ubPqg0Br4lLZOpYfl2FgB8yjxorXifG6qkcAEl3BQy0Y6OG4y+MTbPRu9e5HuxvucyFxmHAilkTA/ZIWg/LGySzb45jNv+EDqmkl69C9U9ajY4ykRdiNPU0VAgsJmhE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728892466; c=relaxed/simple; bh=ju5tEs2YpReGfUl7kpmaentWLs1aOFTk3g3luw0i6fw=; h=Message-ID:Date:From:To:Subject:MIME-Version:Content-Type: Content-Disposition; b=QvRjMyWPak2EPWMMbxk1yrrTVxtoBCb79+FfZ9ItJw3VxReO6tGfT8M5aZGYlFp7cuaTJ0QpCa9IcW19VDVptZA7JPmA2jqWb7d2V1QusU4JWurV5v2LuUVudsf7tq2ziEQJok9ALQHlQNzA1GoyI1g2aSk50gc8PPMslgetYNE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=h7d3M5rT; arc=none smtp.client-ip=209.85.215.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="h7d3M5rT" Received: by mail-pg1-f172.google.com with SMTP id 41be03b00d2f7-7ea78037b7eso996748a12.0 for ; Mon, 14 Oct 2024 00:54:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728892463; x=1729497263; darn=vger.kernel.org; h=content-disposition:mime-version:subject:to:from:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=HLa9Q2R5k1JNGyIkrLC82/YIJbeR7nbIUsyxKIPo9qg=; b=h7d3M5rToaXok5E7jVkmsQ3B6Kc8/0q3hz3LphqMbJ5Pw8qpn1uac6qbYFMTDIMKtd k7ctn799KwPN3/BP5sG3Gcae2dlYxoHc2Crs63bV6eTYTn3GiIqr8VO70/nY533B+k1D coCaOzWuDKjHarwBKoeDN1ObcJMxwyRj22Gv9hLgNbPjP3f3uadaubQd4WK8fb/Sopwu qcyVLzses03eBVuVuRkByG7h3BZVGjdUX6xaq+3Yk+v3dVqZcIivqpx2Pqa0MxM0wLif QVdmUwK3hoKGtdkYXXQp/2YikCVvck+a8d41D9ZlLHR1N6XzTHlKDs7DAdsPwub3WrRW hodQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728892463; x=1729497263; h=content-disposition:mime-version:subject:to:from:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=HLa9Q2R5k1JNGyIkrLC82/YIJbeR7nbIUsyxKIPo9qg=; b=ZilDDOe6fnE5j7M5TfT8RXYNzf6uZWB8H0U84dj6CR88YWzHhYgUW/A3S+zwEFCiEF fIc9S0VNAfJ3LXFzCIVtDTdJfxn9v+XTuB/0V0Ll36vAhA46XmuB3e/c3rNfp+Ka4JU6 vELE3ZLr3EqxSPLoMHtP89//zgoDKWMclflEWW+YJG5HMif+LlbEJEBis7rbOt5oFb0i I5mzrOUZ7r5V0Ssz5E3OocF7LUz1v/qAFzBKA4q/r+scDwDG21a9jkrycK/ilnRosZTt dsyL74ePNAkA3aZugrZEndbE5NLC5EkwscLfQNuspyCbfGrd3mq3fYzqwkMIIPaGiafE z9hw== X-Gm-Message-State: AOJu0Yz8h6e/014whL6yFhhwh1aXnMvOAQKD/0u3mV8wkBGegLCOIqZJ 97TR/vmXq9RC8ApB51lwwX/LC5aTViAeM1Tvh/Si/aG4sgpdiLV6/o2GeQ== X-Google-Smtp-Source: AGHT+IGmbd3q6ZlEz+N0i7oHBRNJ/SSjKs+NC8uzZm4rD0u2yygSa5zjZ8oU0Or6p8UrGTHDlT23jg== X-Received: by 2002:a05:6a21:118a:b0:1d4:e523:b67e with SMTP id adf61e73a8af0-1d8bcf14960mr16716345637.14.1728892462332; Mon, 14 Oct 2024 00:54:22 -0700 (PDT) Received: from JUNHO-NEOSTACK. ([221.154.134.3]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71e5e2840ebsm2292771b3a.130.2024.10.14.00.54.21 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Oct 2024 00:54:21 -0700 (PDT) Message-ID: <670cce2d.050a0220.14053.42b2@mx.google.com> X-Google-Original-Message-ID: Date: Mon, 14 Oct 2024 16:54:19 +0900 From: Junho Lee To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ v3 1/4] mesh: Implement lower transport layer for segmentation and reassembly Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline These is implementations of segmentation and reassembly, except for the friend feature for LPN nodes, implemented according to Mesh Protocol 1.1 section 3.5.3. Sections 4.2.48 and 4.2.49 of Mesh Protocol 1.1 define the transmission interval, number of retransmissions, retransmission interval, ack transmission, number of ack retransmissions, ack retransmission interval, ack retransmission interval, and discard time for SAR, which is a mutable state, and required a SAR implementation that conforms to the specification. The existing segmentation and reassembly were implemented before the specification was officially released, so they were fixed. - In the previous implementation, the segments of the SAR were sent to the network layer immediately for every segO. This has been changed so that they are sent one after the other when the timer expires for each segment interval state. - In the previous implementation, the SAR retransmission feature for multicast sent all segments to the network layer a fixed four times. This has been changed to send as many SAR retransmissions for multicast as the number of states. - In the original implementation, the SAR retransmission feaure for unicast was persistent as long as the receiver was receiving additional segments. This has been changed to send as many SAR retransmissions for unicast as the number of states. - In the previous implementation, the SAR transfer feature for the same destination worked as a single thread, so if SAR transfers were duplicated, queuing was used to delay the transfer, but if the upper transport layer required successive SAR transfers, the queue would stack up infinitely. This was solved by discarding existing SAR transmissions when SAR transmissions for the same destination are required. - In the previous implementation, an ack was sent each time a segment was received for a SAR that had already been successfully received. This has been changed to sending an ACK only once within a certain period. --- mesh/mesh.c | 45 ++++ mesh/mesh.h | 2 + mesh/net.c | 672 +++++++++++++++++++++++++++++++++++----------------- 3 files changed, 498 insertions(+), 221 deletions(-) diff --git a/mesh/mesh.c b/mesh/mesh.c index 91cf25175..f89230b6c 100644 --- a/mesh/mesh.c +++ b/mesh/mesh.c @@ -95,6 +95,41 @@ static struct l_queue *pending_queue; static const char *storage_dir; +struct mesh_sar_transmitter { + uint8_t seg_int_step; + uint8_t unicast_rtx_cnt; + uint8_t unicast_rtx_without_prog_cnt; + uint8_t unicast_rtx_int_step; + uint8_t unicast_rtx_int_inc; + uint8_t multicast_rtx_cnt; + uint8_t multicast_rtx_int_step; +}; + +struct mesh_sar_receiver { + uint8_t seg_threshold; + uint8_t ack_delay_inc; + uint8_t ack_rtx_cnt; + uint8_t discard_timeout; + uint8_t receiver_seg_int_step; +}; + +static struct mesh_sar_transmitter mesh_sar_txr = { + .seg_int_step = 5, + .unicast_rtx_cnt = 2, + .unicast_rtx_without_prog_cnt = 2, + .unicast_rtx_int_step = 7, + .unicast_rtx_int_inc = 1, + .multicast_rtx_cnt = 2, + .multicast_rtx_int_step = 8 +}; +static struct mesh_sar_receiver mesh_sar_rxr = { + .seg_threshold = 3, + .ack_delay_inc = 1, + .ack_rtx_cnt = 0, + .discard_timeout = 1, + .receiver_seg_int_step = 5 +}; + /* Forward static decalrations */ static void def_attach(struct l_timeout *timeout, void *user_data); static void def_leave(struct l_timeout *timeout, void *user_data); @@ -203,6 +238,16 @@ uint8_t mesh_get_friend_queue_size(void) return mesh.friend_queue_sz; } +void mesh_get_sar_transmitter(void *sar_txr) +{ + memcpy(sar_txr, &mesh_sar_txr, sizeof(struct mesh_sar_transmitter)); +} + +void mesh_get_sar_receiver(void *sar_rxr) +{ + memcpy(sar_rxr, &mesh_sar_rxr, sizeof(struct mesh_sar_receiver)); +} + static void parse_settings(const char *mesh_conf_fname) { struct l_settings *settings; diff --git a/mesh/mesh.h b/mesh/mesh.h index c30a8d1f0..5d62f35c8 100644 --- a/mesh/mesh.h +++ b/mesh/mesh.h @@ -43,3 +43,5 @@ bool mesh_relay_supported(void); bool mesh_friendship_supported(void); uint16_t mesh_get_crpl(void); uint8_t mesh_get_friend_queue_size(void); +void mesh_get_sar_transmitter(void *sar_txr); +void mesh_get_sar_receiver(void *sar_rxr); diff --git a/mesh/net.c b/mesh/net.c index 05ca48326..48032c64d 100644 --- a/mesh/net.c +++ b/mesh/net.c @@ -30,6 +30,11 @@ #include "mesh/model.h" #include "mesh/appkey.h" #include "mesh/rpl.h" +#include "mesh/mesh.h" + +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif #define abs_diff(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) @@ -44,10 +49,6 @@ #define IV_UPDATE_SEQ_TRIGGER 0x800000 /* Half of Seq-Nums expended */ -#define SEG_TO 2 -#define MSG_TO 60 -#define SAR_DEL 10 - #define DEFAULT_TRANSMIT_COUNT 1 #define DEFAULT_TRANSMIT_INTERVAL 100 @@ -91,15 +92,34 @@ struct mesh_subnet { uint8_t kr_phase; }; +struct mesh_sar_transmitter { + uint8_t seg_int_step; + uint8_t unicast_rtx_cnt; + uint8_t unicast_rtx_without_prog_cnt; + uint8_t unicast_rtx_int_step; + uint8_t unicast_rtx_int_inc; + uint8_t multicast_rtx_cnt; + uint8_t multicast_rtx_int_step; +}; + +struct mesh_sar_receiver { + uint8_t seg_threshold; + uint8_t ack_delay_inc; + uint8_t ack_rtx_cnt; + uint8_t discard_timeout; + uint8_t receiver_seg_int_step; +}; + struct mesh_net { struct mesh_io *io; struct mesh_node *node; struct mesh_prov *prov; struct l_queue *app_keys; + struct mesh_sar_transmitter *sar_txr; + struct mesh_sar_receiver *sar_rxr; unsigned int pkt_id; unsigned int bea_id; unsigned int beacon_id; - unsigned int sar_id_next; bool friend_enable; bool snb_enable; @@ -138,7 +158,6 @@ struct mesh_net { struct l_queue *replay_cache; struct l_queue *sar_in; struct l_queue *sar_out; - struct l_queue *sar_queue; struct l_queue *frnd_msgs; struct l_queue *friends; struct l_queue *negotiations; @@ -152,15 +171,10 @@ struct mesh_msg { }; struct mesh_sar { - unsigned int id; - struct l_timeout *seg_timeout; - struct l_timeout *msg_timeout; uint32_t flags; - uint32_t last_nak; uint32_t iv_index; uint32_t seqAuth; uint16_t seqZero; - uint16_t app_idx; uint16_t net_idx; uint16_t src; uint16_t remote; @@ -169,13 +183,32 @@ struct mesh_sar { bool segmented; bool frnd; bool frnd_cred; - bool delete; uint8_t ttl; - uint8_t last_seg; uint8_t key_aid; uint8_t buf[4]; /* Large enough for ACK-Flags and MIC */ }; +struct mesh_sar_tx { + struct mesh_sar *sar; + struct l_timeout *seg_timeout; + uint16_t retrans_ms; + uint8_t int_ms; + uint8_t attempt_left; + uint8_t attempt_left_no_progress; + uint8_t segO; + uint8_t segN; + bool ack_received; +}; + +struct mesh_sar_rx { + struct mesh_sar *sar; + struct l_timeout *ack_timeout; + struct l_timeout *msg_timeout; + uint16_t ack_int_ms; + uint8_t ack_attempt_left; + uint8_t discard_to; +}; + struct mesh_destination { uint16_t dst; uint16_t ref_cnt; @@ -225,6 +258,65 @@ struct net_beacon_data { static struct l_queue *fast_cache; static struct l_queue *nets; +static uint8_t sar_tx_seg_int_ms(struct mesh_sar_transmitter *txr) +{ + return (txr->seg_int_step + 1) * 10; +} + +static uint8_t sar_tx_retrans_cnt(struct mesh_sar_transmitter *txr, + bool is_unicast, bool no_progress) +{ + if (is_unicast) { + return (no_progress ? + txr->unicast_rtx_without_prog_cnt : + txr->unicast_rtx_cnt); + } else { + return txr->multicast_rtx_cnt; + } +} + +/* Maximum retransmission interval is 50800 milliseconds. */ +static uint16_t sar_tx_retrans_timeout_ms(struct mesh_sar_transmitter *txr, + bool is_unicast, int ttl) +{ + if (is_unicast) { + return (txr->unicast_rtx_int_step + 1 + ((ttl > 0) ? + ((txr->unicast_rtx_int_inc + 1) * (ttl - 1)) : + 0)) * 25; + } else { + return (txr->multicast_rtx_int_step + 1) * 25; + } +} + +static uint8_t sar_rx_seg_threshold(struct mesh_sar_receiver *rxr) +{ + return rxr->seg_threshold; +} + +/* Maximum ack retransmission interval is 1360 milliseconds. */ +static uint16_t sar_rx_ack_timeout_ms(struct mesh_sar_receiver *rxr, int segN) +{ + return MIN(segN, rxr->ack_delay_inc * 2 + 3) * + (rxr->receiver_seg_int_step + 1) * 10 / 2; +} + +/* Maximum retransmission delay is 1360 milliseconds. */ +static uint16_t sar_rx_delay_ack_timeout_ms(struct mesh_sar_receiver *rxr) +{ + return (rxr->ack_delay_inc * 2 + 3) * + (rxr->receiver_seg_int_step + 1) * 10 / 2; +} + +static uint8_t sar_rx_discard_timeout(struct mesh_sar_receiver *rxr) +{ + return (rxr->discard_timeout + 1) * 5; +} + +static uint8_t sar_rx_ack_retrans_count(struct mesh_sar_receiver *rxr) +{ + return rxr->ack_rtx_cnt; +} + static void net_rx(void *net_ptr, void *user_data); static inline struct mesh_subnet *get_primary_subnet(struct mesh_net *net) @@ -521,11 +613,54 @@ static void mesh_sar_free(void *data) if (!sar) return; - l_timeout_remove(sar->seg_timeout); - l_timeout_remove(sar->msg_timeout); l_free(sar); } +static struct mesh_sar_tx *mesh_sar_tx_new(void) +{ + size_t size = sizeof(struct mesh_sar_tx); + struct mesh_sar_tx *sar_tx; + + sar_tx = l_malloc(size); + memset(sar_tx, 0, size); + return sar_tx; +} + +static void mesh_sar_tx_free(void *data) +{ + struct mesh_sar_tx *sar_tx = data; + + if (!sar_tx) + return; + + mesh_sar_free(sar_tx->sar); + l_timeout_remove(sar_tx->seg_timeout); + l_free(sar_tx); +} + +static struct mesh_sar_rx *mesh_sar_rx_new(void) +{ + size_t size = sizeof(struct mesh_sar_rx); + struct mesh_sar_rx *sar_rx; + + sar_rx = l_malloc(size); + memset(sar_rx, 0, size); + return sar_rx; +} + +static void mesh_sar_rx_free(void *data) +{ + struct mesh_sar_rx *sar_rx = data; + + if (!sar_rx) + return; + + mesh_sar_free(sar_rx->sar); + l_timeout_remove(sar_rx->ack_timeout); + l_timeout_remove(sar_rx->msg_timeout); + l_free(sar_rx); +} + static void subnet_free(void *data) { struct mesh_subnet *subnet = data; @@ -634,6 +769,11 @@ struct mesh_net *mesh_net_new(struct mesh_node *node) net = l_new(struct mesh_net, 1); + net->sar_txr = l_new(struct mesh_sar_transmitter, 1); + mesh_get_sar_transmitter(net->sar_txr); + net->sar_rxr = l_new(struct mesh_sar_receiver, 1); + mesh_get_sar_receiver(net->sar_rxr); + net->node = node; net->seq_num = DEFAULT_SEQUENCE_NUMBER; net->default_ttl = TTL_MASK; @@ -645,7 +785,6 @@ struct mesh_net *mesh_net_new(struct mesh_node *node) net->msg_cache = l_queue_new(); net->sar_in = l_queue_new(); net->sar_out = l_queue_new(); - net->sar_queue = l_queue_new(); net->frnd_msgs = l_queue_new(); net->destinations = l_queue_new(); net->app_keys = l_queue_new(); @@ -667,12 +806,14 @@ void mesh_net_free(void *user_data) if (!net) return; + l_free(net->sar_txr); + l_free(net->sar_rxr); + l_queue_destroy(net->subnets, subnet_free); l_queue_destroy(net->msg_cache, l_free); l_queue_destroy(net->replay_cache, l_free); - l_queue_destroy(net->sar_in, mesh_sar_free); - l_queue_destroy(net->sar_out, mesh_sar_free); - l_queue_destroy(net->sar_queue, mesh_sar_free); + l_queue_destroy(net->sar_in, mesh_sar_rx_free); + l_queue_destroy(net->sar_out, mesh_sar_tx_free); l_queue_destroy(net->frnd_msgs, l_free); l_queue_destroy(net->friends, mesh_friend_free); l_queue_destroy(net->negotiations, mesh_friend_free); @@ -1080,36 +1221,52 @@ static bool msg_in_cache(struct mesh_net *net, uint16_t src, uint32_t seq, return false; } -static bool match_sar_seq0(const void *a, const void *b) +static bool match_sar_tx_seq0(const void *a, const void *b) { - const struct mesh_sar *sar = a; + const struct mesh_sar_tx *sar_tx = a; uint16_t seqZero = L_PTR_TO_UINT(b); - return sar->seqZero == seqZero; + return sar_tx->sar->seqZero == seqZero; +} + +static bool match_sar_tx_remote(const void *a, const void *b) +{ + const struct mesh_sar_tx *sar_tx = a; + uint16_t remote = L_PTR_TO_UINT(b); + + return sar_tx->sar->remote == remote; } -static bool match_sar_remote(const void *a, const void *b) +static bool match_sar_rx_remote(const void *a, const void *b) { - const struct mesh_sar *sar = a; + const struct mesh_sar_rx *sar_rx = a; uint16_t remote = L_PTR_TO_UINT(b); - return sar->remote == remote; + return sar_rx->sar->remote == remote; } static bool match_msg_timeout(const void *a, const void *b) { - const struct mesh_sar *sar = a; + const struct mesh_sar_rx *sar_rx = a; const struct l_timeout *msg_timeout = b; - return sar->msg_timeout == msg_timeout; + return sar_rx->msg_timeout == msg_timeout; +} + +static bool match_ack_timeout(const void *a, const void *b) +{ + const struct mesh_sar_rx *sar_rx = a; + const struct l_timeout *ack_timeout = b; + + return sar_rx->ack_timeout == ack_timeout; } static bool match_seg_timeout(const void *a, const void *b) { - const struct mesh_sar *sar = a; + const struct mesh_sar_tx *sar_tx = a; const struct l_timeout *seg_timeout = b; - return sar->seg_timeout == seg_timeout; + return sar_tx->seg_timeout == seg_timeout; } static bool match_dest_dst(const void *a, const void *b) @@ -1501,156 +1658,193 @@ static void send_net_ack(struct mesh_net *net, struct mesh_sar *sar, sizeof(msg)); } -static void inseg_to(struct l_timeout *seg_timeout, void *user_data) +static void delay_seg_ack_to(struct l_timeout *ack_timeout, void *user_data) { struct mesh_net *net = user_data; - struct mesh_sar *sar = l_queue_find(net->sar_in, - match_seg_timeout, seg_timeout); + struct mesh_sar_rx *sar_rx = l_queue_find(net->sar_in, + match_ack_timeout, ack_timeout); - l_timeout_remove(seg_timeout); - if (!sar) + l_timeout_remove(ack_timeout); + if (!sar_rx) return; - /* Send NAK */ - l_debug("Timeout %p %3.3x", sar, sar->app_idx); - send_net_ack(net, sar, sar->flags); - - sar->seg_timeout = l_timeout_create(SEG_TO, inseg_to, net, NULL); + sar_rx->ack_timeout = NULL; } -static void inmsg_to(struct l_timeout *msg_timeout, void *user_data) +static void seg_ack_to(struct l_timeout *ack_timeout, void *user_data) { struct mesh_net *net = user_data; - struct mesh_sar *sar = l_queue_find(net->sar_in, - match_msg_timeout, msg_timeout); + struct mesh_sar_rx *sar_rx = l_queue_find(net->sar_in, + match_ack_timeout, ack_timeout); - if (!sar) { - l_timeout_remove(msg_timeout); + l_timeout_remove(ack_timeout); + if (!sar_rx) return; - } - if (!sar->delete) { - /* - * Incomplete timer expired, cancel SAR and start - * delete timer - */ - l_timeout_remove(sar->seg_timeout); - sar->seg_timeout = NULL; - sar->delete = true; - l_timeout_modify(sar->msg_timeout, SAR_DEL); - return; - } + sar_rx->ack_timeout = NULL; + + send_net_ack(net, sar_rx->sar, sar_rx->sar->flags); - l_queue_remove(net->sar_in, sar); - mesh_sar_free(sar); + if (sar_rx->ack_attempt_left) { + sar_rx->ack_attempt_left--; + sar_rx->ack_timeout = l_timeout_create(sar_rx->ack_int_ms, + seg_ack_to, net, NULL); + } } -static void outmsg_to(struct l_timeout *msg_timeout, void *user_data) +static void seg_rx_completed_to(struct l_timeout *msg_timeout, void *user_data) { struct mesh_net *net = user_data; - struct mesh_sar *sar = l_queue_remove_if(net->sar_out, + struct mesh_sar_rx *sar_rx = l_queue_find(net->sar_in, match_msg_timeout, msg_timeout); l_timeout_remove(msg_timeout); - if (!sar) + if (!sar_rx) return; - sar->msg_timeout = NULL; - mesh_sar_free(sar); -} + sar_rx->msg_timeout = NULL; -static void outseg_to(struct l_timeout *seg_timeout, void *user_data); + l_queue_remove(net->sar_in, sar_rx); + mesh_sar_rx_free(sar_rx); +} -static void send_queued_sar(struct mesh_net *net, uint16_t dst) +static void seg_rx_discard_to(struct l_timeout *msg_timeout, void *user_data) { - struct mesh_sar *sar = l_queue_remove_if(net->sar_queue, - match_sar_remote, L_UINT_TO_PTR(dst)); + struct mesh_net *net = user_data; + struct mesh_sar_rx *sar_rx = l_queue_find(net->sar_in, + match_msg_timeout, msg_timeout); - if (!sar) + l_timeout_remove(msg_timeout); + if (!sar_rx) return; - /* Out to current outgoing, and immediate expire Seg TO */ - l_queue_push_head(net->sar_out, sar); - sar->seg_timeout = NULL; - sar->msg_timeout = l_timeout_create(MSG_TO, outmsg_to, net, NULL); - outseg_to(NULL, net); + sar_rx->msg_timeout = NULL; + + l_debug("Discard pending SAR for %04x", sar_rx->sar->seqZero); + l_queue_remove(net->sar_in, sar_rx); + mesh_sar_rx_free(sar_rx); } -static void ack_received(struct mesh_net *net, bool timeout, - uint16_t src, uint16_t dst, - uint16_t seq0, uint32_t ack_flag) +static void ack_rxed(struct mesh_net *net, uint16_t src, uint16_t dst, + uint16_t seq0, uint32_t ack_flag) { - struct mesh_sar *outgoing; - uint32_t seg_flag = 0x00000001; - uint32_t ack_copy = ack_flag; - uint16_t i; + struct mesh_sar_tx *sar_tx; + struct mesh_sar *sar; + uint32_t flags_copy; - l_debug("ACK Rxed (%x) (to:%d): %8.8x", seq0, timeout, ack_flag); + l_debug("ACK Rxed (%x): %8.8x", seq0, ack_flag); - outgoing = l_queue_find(net->sar_out, match_sar_seq0, + sar_tx = l_queue_find(net->sar_out, match_sar_tx_seq0, L_UINT_TO_PTR(seq0)); - if (!outgoing) { + if (!sar_tx) { l_debug("Not Found: %4.4x", seq0); return; } + sar = sar_tx->sar; + /* * TODO -- If we receive from different * SRC than we are sending to, make sure the OBO flag is set */ - if ((!timeout && !ack_flag) || - (outgoing->flags & ack_flag) == outgoing->flags) { - l_debug("ob_sar_removal (%x)", outgoing->flags); + if (!ack_flag) { + l_debug("Cancel sending segments. (%x)", sar->flags); + l_queue_remove(net->sar_out, sar_tx); + mesh_sar_tx_free(sar_tx); + return; + } - /* Note: ack_flags == 0x00000000 is a remote Cancel request */ + flags_copy = sar->flags & ~ack_flag; - l_queue_remove(net->sar_out, outgoing); - send_queued_sar(net, outgoing->remote); - mesh_sar_free(outgoing); + if (flags_copy == sar->flags) { + /* Already received ack. */ + return; + } + sar_tx->ack_received = true; + sar->flags = flags_copy; + + if (!flags_copy) { + /* Complete SAR transmission. Receiver has all segs. */ + l_queue_remove(net->sar_out, sar_tx); + mesh_sar_tx_free(sar_tx); return; } +} + +static void send_next_seg_to(struct l_timeout *seg_timeout, void *user_data) +{ + struct mesh_net *net = user_data; + struct mesh_sar_tx *sar_tx = l_queue_find(net->sar_out, + match_seg_timeout, seg_timeout); + uint8_t interval_ms = 0; - outgoing->last_nak |= ack_flag; + l_timeout_remove(seg_timeout); + if (!sar_tx) + return; - ack_copy &= outgoing->flags; + sar_tx->seg_timeout = NULL; - for (i = 0; i <= SEG_MAX(true, outgoing->len); i++, seg_flag <<= 1) { - if (seg_flag & ack_flag) { - l_debug("Skipping Seg %d of %d", - i, SEG_MAX(true, outgoing->len)); + /* Complete transmission to unicast address. Receiver has all segs. */ + if (!sar_tx->sar->flags) + goto free; + + while (sar_tx->segO <= sar_tx->segN) { + if (!((1 << sar_tx->segO) & sar_tx->sar->flags)) { + /* Skip received segments. */ + sar_tx->segO++; continue; } - ack_copy |= seg_flag; - - l_debug("Resend Seg %d net:%p dst:%x app_idx:%3.3x", - i, net, outgoing->remote, outgoing->app_idx); + if (!send_seg(net, net->tx_cnt, net->tx_interval, sar_tx->sar, + sar_tx->segO)) { + l_error("Failed to send SAR"); + goto free; + } - send_seg(net, net->tx_cnt, net->tx_interval, outgoing, i); + sar_tx->segO++; + interval_ms = sar_tx->int_ms; + break; } - l_timeout_remove(outgoing->seg_timeout); - outgoing->seg_timeout = l_timeout_create(SEG_TO, outseg_to, net, NULL); -} + if (sar_tx->segO > sar_tx->segN) { + if (!sar_tx->attempt_left) { + if (IS_UNICAST(sar_tx->sar->remote)) { + l_warn("Ran out of SAR retransmit attempts"); + goto free; + } else { + /* Complete transmission to multicast address.*/ + goto free; + } + } else if (!sar_tx->attempt_left_no_progress) { + l_warn("Ran out of SAR retransmit without progress attempts"); + goto free; + } -static void outseg_to(struct l_timeout *seg_timeout, void *user_data) -{ - struct mesh_net *net = user_data; - struct mesh_sar *sar = l_queue_find(net->sar_out, - match_seg_timeout, seg_timeout); + sar_tx->segO = 0; + sar_tx->attempt_left--; + if (!sar_tx->ack_received) + sar_tx->attempt_left_no_progress--; + else + sar_tx->attempt_left_no_progress = sar_tx_retrans_cnt( + net->sar_txr, + true, true); + sar_tx->ack_received = false; + interval_ms = sar_tx->retrans_ms; + } - l_timeout_remove(seg_timeout); - if (!sar) - return; + sar_tx->seg_timeout = l_timeout_create_ms(interval_ms, send_next_seg_to, + net, NULL); - sar->seg_timeout = NULL; +out: + return; - /* Re-Send missing segments by faking NACK */ - ack_received(net, true, sar->remote, sar->src, - sar->seqZero, sar->last_nak); +free: + l_queue_remove(net->sar_out, sar_tx); + mesh_sar_tx_free(sar_tx); + goto out; } static bool match_replay_cache(const void *a, const void *b) @@ -1956,130 +2150,165 @@ static bool seg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, uint8_t segO, uint8_t segN, const uint8_t *data, uint8_t size) { - struct mesh_sar *sar_in = NULL; + struct mesh_sar_rx *sar_in = NULL; + struct mesh_sar *sar = NULL; uint16_t seg_off = 0; - uint32_t expected, this_seg_flag, largest, seqAuth; - bool reset_seg_to = true; + uint32_t expected, this_seg_flag, seqAuth; /* * DST could receive additional Segments after * completing due to a lost ACK, so re-ACK and discard */ - sar_in = l_queue_find(net->sar_in, match_sar_remote, + sar_in = l_queue_find(net->sar_in, match_sar_rx_remote, L_UINT_TO_PTR(src)); /* Discard *old* incoming-SAR-in-progress if this segment newer */ seqAuth = seq_auth(seq, seqZero); - if (sar_in && (sar_in->seqAuth != seqAuth || - sar_in->iv_index != iv_index)) { + if (sar_in && (sar_in->sar->seqAuth != seqAuth || + sar_in->sar->iv_index != iv_index)) { bool newer; - if (iv_index > sar_in->iv_index) + if (iv_index > sar_in->sar->iv_index) newer = true; - else if (iv_index == sar_in->iv_index) - newer = seqAuth > sar_in->seqAuth; + else if (iv_index == sar_in->sar->iv_index) + newer = seqAuth > sar_in->sar->seqAuth; else newer = false; if (newer) { /* Cancel Old, start New */ + l_debug("Discard SAR duplicated from src: 0x%04x", src); l_queue_remove(net->sar_in, sar_in); - mesh_sar_free(sar_in); + mesh_sar_rx_free(sar_in); sar_in = NULL; } else /* Ignore Old */ + l_debug("Ignore old seqAuth"); return false; } expected = 0xffffffff >> (31 - segN); if (sar_in) { + sar = sar_in->sar; l_debug("RXed (old: %04x %06x size:%d) %d of %d", seqZero, seq, size, segO, segN); /* Sanity Check--> certain things must match */ - if (SEG_MAX(true, sar_in->len) != segN || - sar_in->key_aid != key_aid) + if (SEG_MAX(true, sar->len) != segN || + sar->key_aid != key_aid) return false; - if (sar_in->flags == expected) { - /* Re-Send ACK for full msg */ - send_net_ack(net, sar_in, expected); + if (sar->flags == expected) { + /* + * According to MshPRTv1.1: 3.5.3.4, if the destination + * is a unicast address and a segment is received for a + * completed message, it sends one acknowledgment within + * a period of: + * [ack delay increment * seg reception interval] + */ + l_debug("Got segment for already complete msg"); + if (IS_UNICAST(dst) && sar_in->ack_timeout == NULL) { + send_net_ack(net, sar, expected); + sar_in->ack_timeout = l_timeout_create_ms( + sar_rx_delay_ack_timeout_ms( + net->sar_rxr), + delay_seg_ack_to, net, NULL); + } return true; - } else if (sar_in->delete) - /* Ignore cancelled */ - return false; + } } else { uint16_t len = MAX_SEG_TO_LEN(segN); l_debug("RXed (new: %04x %06x size: %d len: %d) %d of %d", seqZero, seq, size, len, segO, segN); l_debug("Queue Size: %d", l_queue_length(net->sar_in)); - sar_in = mesh_sar_new(len); - sar_in->seqAuth = seqAuth; - sar_in->iv_index = iv_index; - sar_in->src = dst; - sar_in->remote = src; - sar_in->seqZero = seqZero; - sar_in->key_aid = key_aid; - sar_in->len = len; - sar_in->last_seg = 0xff; - sar_in->net_idx = net_idx; - sar_in->msg_timeout = l_timeout_create(MSG_TO, - inmsg_to, net, NULL); - - l_debug("First Seg %4.4x", sar_in->flags); + sar = mesh_sar_new(len); + sar->seqAuth = seqAuth; + sar->iv_index = iv_index; + sar->src = dst; + sar->remote = src; + sar->seqZero = seqZero; + sar->key_aid = key_aid; + sar->len = len; + sar->net_idx = net_idx; + + sar_in = mesh_sar_rx_new(); + sar_in->sar = sar; + + if (IS_UNICAST(dst)) { + /* + * According to MshPRTv1.1: 3.5.3.4, if the destination + * is a unicast address, it sends the acks for received + * segments, and additionally retransmits the acks when + * segN exceeds the threshold. + */ + sar_in->ack_int_ms = sar_rx_ack_timeout_ms(net->sar_rxr, + segN); + + if (segN > sar_rx_seg_threshold(net->sar_rxr)) { + sar_in->ack_attempt_left = + sar_rx_ack_retrans_count(net->sar_rxr); + } else { + sar_in->ack_attempt_left = 0; + } + } + + sar_in->discard_to = sar_rx_discard_timeout(net->sar_rxr); + + l_debug("First Seg %4.4x", sar->flags); l_queue_push_head(net->sar_in, sar_in); } - seg_off = segO * MAX_SEG_LEN; - memcpy(sar_in->buf + seg_off, data, size); this_seg_flag = 0x00000001 << segO; - /* Don't reset Seg TO or NAK if we already have this seg */ - if (this_seg_flag & sar_in->flags) - reset_seg_to = false; + /* Ignore this seg if it already exists.*/ + if (this_seg_flag & sar->flags) + return false; + + l_timeout_remove(sar_in->ack_timeout); + sar_in->ack_timeout = NULL; + l_timeout_remove(sar_in->msg_timeout); + sar_in->msg_timeout = NULL; - sar_in->flags |= this_seg_flag; - sar_in->ttl = ttl; + seg_off = segO * MAX_SEG_LEN; + memcpy(sar->buf + seg_off, data, size); + sar->flags |= this_seg_flag; + sar->ttl = ttl; /* Msg length only definitive on last segment */ if (segO == segN) - sar_in->len = segN * MAX_SEG_LEN + size; + sar->len = segN * MAX_SEG_LEN + size; + + /* Send ACK only if DST is unicast address. */ + if (IS_UNICAST(dst)) { + sar_in->ack_timeout = l_timeout_create_ms(sar_in->ack_int_ms, + seg_ack_to, + net, NULL); + } - if (sar_in->flags == expected) { + if (sar->flags == expected) { /* Got it all */ - send_net_ack(net, sar_in, expected); + send_net_ack(net, sar, expected); msg_rxed(net, frnd, iv_index, ttl, seq, net_idx, - sar_in->remote, dst, key_aid, true, szmic, - sar_in->seqZero, sar_in->buf, sar_in->len); + sar->remote, dst, key_aid, true, szmic, + sar->seqZero, sar->buf, sar->len); - /* Kill Inter-Seg timeout */ - l_timeout_remove(sar_in->seg_timeout); - sar_in->seg_timeout = NULL; - - /* Start delete timer */ - sar_in->delete = true; - l_timeout_modify(sar_in->msg_timeout, SAR_DEL); + /* + * Delay SAR removal to be able to acknowledge a transaction + * when repeated segments are received. + */ + sar_in->msg_timeout = l_timeout_create(sar_in->discard_to, + seg_rx_completed_to, + net, NULL); return true; } - if (reset_seg_to) { - /* Restart Inter-Seg Timeout */ - l_timeout_remove(sar_in->seg_timeout); - - /* if this is the largest outstanding segment, send NAK now */ - largest = (0xffffffff << segO) & expected; - if ((largest & sar_in->flags) == largest) - send_net_ack(net, sar_in, sar_in->flags); - - sar_in->seg_timeout = l_timeout_create(SEG_TO, - inseg_to, net, NULL); - } else - largest = 0; + sar_in->msg_timeout = l_timeout_create(sar_in->discard_to, + seg_rx_discard_to, + net, NULL); - l_debug("NAK: %d expected:%08x largest:%08x flags:%08x", - reset_seg_to, expected, largest, sar_in->flags); + l_debug("expected:%08x flags:%08x", expected, sar->flags); return false; } @@ -2393,8 +2622,7 @@ static enum _relay_advice packet_received(void *user_data, friend_ack_rxed(net, iv_index, net_seq, net_src, net_dst, msg); else - ack_received(net, false, - net_src, net_dst, + ack_rxed(net, net_src, net_dst, net_seqZero, l_get_be32(msg + 3)); } else { @@ -2565,8 +2793,7 @@ static void iv_upd_to(struct l_timeout *upd_timeout, void *user_data) switch (net->iv_upd_state) { case IV_UPD_UPDATING: - if (l_queue_length(net->sar_out) || - l_queue_length(net->sar_queue)) { + if (l_queue_length(net->sar_out)) { l_debug("don't leave IV Update until sar_out empty"); l_timeout_modify(net->iv_update_timeout, 10); break; @@ -3194,8 +3421,6 @@ static bool send_seg(struct mesh_net *net, uint8_t cnt, uint16_t interval, send_msg_pkt(net, cnt, interval, packet, packet_len + 1); - msg->last_seg = segO; - return true; } @@ -3255,7 +3480,7 @@ bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src, bool szmic, const void *msg, uint16_t msg_len) { struct mesh_sar *payload = NULL; - uint8_t seg, seg_max; + uint8_t seg_max; bool result; if (!net || msg_len > 384) @@ -3311,47 +3536,52 @@ bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src, payload->segmented = segmented; if (segmented) { + struct mesh_sar_tx *drop_sar_tx; payload->flags = 0xffffffff >> (31 - seg_max); payload->seqZero = seq & SEQ_ZERO_MASK; - payload->id = ++net->sar_id_next; /* Single thread SAR messages to same Unicast DST */ - if (l_queue_find(net->sar_out, match_sar_remote, - L_UINT_TO_PTR(dst))) { - /* Delay sending Outbound SAR unless prior - * SAR to same DST has completed */ - - l_debug("OB-Queued SeqZero: %4.4x", payload->seqZero); - l_queue_push_tail(net->sar_queue, payload); - return true; + drop_sar_tx = l_queue_find(net->sar_out, match_sar_tx_remote, + L_UINT_TO_PTR(dst)); + if (drop_sar_tx) { + /* Cancel incomplete prior SAR on the same dst */ + l_debug("Cancel incompleted SAR: SeqZero %4.4x", + drop_sar_tx->sar->seqZero); + l_queue_remove(net->sar_out, drop_sar_tx); + mesh_sar_tx_free(drop_sar_tx); } } - result = true; - - if (!IS_UNICAST(dst) && segmented) { - int i; + result = send_seg(net, cnt, interval, payload, 0); - for (i = 0; i < 4; i++) { - for (seg = 0; seg <= seg_max && result; seg++) - result = send_seg(net, cnt, interval, payload, - seg); - } + /* + * Set the timeout to send the next seg or retransmit if the payload is + * segmented. Flush if it is not segmented or if the transmission + * failed. + */ + if (result && segmented) { + struct mesh_sar_tx *sar_tx = mesh_sar_tx_new(); + bool is_unicast = IS_UNICAST(dst); + + sar_tx->ack_received = false; + sar_tx->int_ms = sar_tx_seg_int_ms(net->sar_txr); + sar_tx->attempt_left = sar_tx_retrans_cnt(net->sar_txr, + is_unicast, false); + sar_tx->attempt_left_no_progress = sar_tx_retrans_cnt( + net->sar_txr, + is_unicast, true); + sar_tx->retrans_ms = sar_tx_retrans_timeout_ms(net->sar_txr, + is_unicast, + ttl); + sar_tx->sar = payload; + l_queue_push_head(net->sar_out, sar_tx); + sar_tx->seg_timeout = l_timeout_create_ms(sar_tx->int_ms, + send_next_seg_to, net, NULL); + sar_tx->segO = 1; /* The 0th seg is already sent. */ + sar_tx->segN = seg_max; } else { - for (seg = 0; seg <= seg_max && result; seg++) - result = send_seg(net, cnt, interval, payload, seg); - } - - /* Reliable: Cache; Unreliable: Flush*/ - if (result && segmented && IS_UNICAST(dst)) { - l_queue_push_head(net->sar_out, payload); - payload->seg_timeout = - l_timeout_create(SEG_TO, outseg_to, net, NULL); - payload->msg_timeout = - l_timeout_create(MSG_TO, outmsg_to, net, NULL); - payload->id = ++net->sar_id_next; - } else mesh_sar_free(payload); + } return result; } From patchwork Mon Oct 14 07:54:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junho Lee X-Patchwork-Id: 13834282 Received: from mail-pl1-f176.google.com (mail-pl1-f176.google.com [209.85.214.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C5E161384BF for ; Mon, 14 Oct 2024 07:54:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728892478; cv=none; b=jos04GA8Pzb3kwOKJB06cqu0pXdgH7HGIeEXI6whhCjzPn2f/rmf6jnvhhyEMKX1z7p3wYk4awN77VZDyo+jEAKoRhAxvVcBxiFYH+gS3focUsM0eVieu0EU/hQrpmJYYqsHYolhpNjkFiXvWvahUNL7P5qu6ZLjs1Fo7065o6g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728892478; c=relaxed/simple; bh=faK6XWq8mtyX5B6ULPT7a+PZyqj05h2pVIOwz15J7RE=; h=Message-ID:Date:From:To:Subject:MIME-Version:Content-Type: Content-Disposition; b=D1cngT49ueQNvZoCbI/fKCHGsQM3F9qPdLqAAZqy1vE7RwPgEEXe0vR8mlmkHG2N4baf6+NySaAHLD1fm7MtGydpQx5dp1OiuR1KRx5h5rsuvsdRxN8M6QerJqrJhEMpeoiHb6x2z3cm9fF2nDLjL19TZ6457uAaI2I6SdauUMQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=PE3k/doj; arc=none smtp.client-ip=209.85.214.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PE3k/doj" Received: by mail-pl1-f176.google.com with SMTP id d9443c01a7336-20ceb8bd22fso4961015ad.3 for ; Mon, 14 Oct 2024 00:54:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728892476; x=1729497276; darn=vger.kernel.org; h=content-disposition:mime-version:subject:to:from:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=tRx3IC4NYZcXkgJI8J3F4oa+SBfBLkFGe9LUx01FzGc=; b=PE3k/dojAiycHoFGu25yzHcqrZeVKxsyhADmDf4i3srK7wDRoIm00wr2ys85cOcBU6 dHOK1PDncTj2ggwG2yg/wRxJu4h3aE1gJFlP2+IoWNVwruv2KpudrtcMcoKPqx00Lvvl F9B+Um0HxCaWtpfur39fuIJdA9Ijy4RUTK/H8tyTl3yuJlRuIcc+MI0lhpenqDwUXrE7 3+/qUewK8SximV92r0IB+dhn7Tk9y44AU93F0wi0p9vWY5seDz2BRIIASuaMgYxny7+g 9nGfvXPUp9bU3kLQEYgaWUJHUH7wnIX/Rtf9mGbh3VOi9/jQYlAVWmNvjsVIJm1oLaAx ewwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728892476; x=1729497276; h=content-disposition:mime-version:subject:to:from:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=tRx3IC4NYZcXkgJI8J3F4oa+SBfBLkFGe9LUx01FzGc=; b=my0KVtajHmF+JJBqQok7mI08bXOCCh/Dw8d5j5PD1zbKUMLxK9lDb3vgy7WSV52t1c YbMfOKf5X8GxfqlaaMXKwBRPiodPJTxY1ATyNoxCw7bNBwXSBqGMXB3UkZANW4SMW+nc 5eohUlk7oMfU63FDuSF4NJfo1c94stwLmC+LFXPjRaz05HHQ2whvQ2v0upvJNyd+yobx kMnJ8R9Htnr9hDdWlavntmctIRKceDy8DH1c+NDa2XLf96t5j9I9IDlFmkr+FTNC5XTD zGZTRyhs4okRpeBVbW5NIo3rvqV5FO9R+y6JQ8DIJSVRKzekCMT7ir07asn2c7KAhezK 3SxQ== X-Gm-Message-State: AOJu0YyYCSbj2x0+N29SW6W7yITfiLOTqEUliWZesz2vX9kq/NfT6N6a lY3vLNk10gBj9YQBy8tD+R8kvDbm5y4nimqQBK0lT3OKKz/aWrsInwmh1w== X-Google-Smtp-Source: AGHT+IHeQOr9DTw/BiLC5AieNL2LS9ObZ76MOvxV6GS8dRbNzS6ltjRNElpAje878PhfjHxfnYjhBA== X-Received: by 2002:a17:903:22d1:b0:20c:79f1:fee9 with SMTP id d9443c01a7336-20cbb183470mr141789125ad.11.1728892475542; Mon, 14 Oct 2024 00:54:35 -0700 (PDT) Received: from JUNHO-NEOSTACK. ([221.154.134.3]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7ea4496735dsm6333796a12.84.2024.10.14.00.54.34 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Oct 2024 00:54:35 -0700 (PDT) Message-ID: <670cce3b.630a0220.81d6b.2ce4@mx.google.com> X-Google-Original-Message-ID: Date: Mon, 14 Oct 2024 16:54:32 +0900 From: Junho Lee To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ v3 2/4] mesh: Add mesh conf for SAR Transmitter and Receiver Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline This allows you to set the SAR Transitter state and SAR Receiver state in the mesh conf file. --- mesh/mesh-main.conf | 107 ++++++++++++++++++++++++++++++++++++++++++++ mesh/mesh.c | 80 ++++++++++++++++++++++++++++++--- 2 files changed, 181 insertions(+), 6 deletions(-) diff --git a/mesh/mesh-main.conf b/mesh/mesh-main.conf index aca9e6fa5..01f4c3d23 100644 --- a/mesh/mesh-main.conf +++ b/mesh/mesh-main.conf @@ -41,3 +41,110 @@ # Setting this value to zero means there's no timeout. # Defaults to 60. #ProvTimeout = 60 + + +[SARTransmitter] + +# Transmission interval step between segments of a message. +# Interval is measured in milliseconds and calculated using the following +# formula: +# +# (SegIntervalStep + 1) * 10 ms. +# +# Valid range 0-15. +# Defaults to 5. +#SegIntervalStep = 5 + +# Maximum number of retransmissions of segments to a unicast destination. +# Valid range 0-15. +# Defaults to 2. +#UnicastRetransCount = 2 + +# Maximum number of retransmissions of segments to a unicast destination when no +# acknowledgment is newly received during the retransmission interval. +# This value sould be set to greater than AckRetransCount on a peer node. +# Valid range 0-15. +# Defaults to 2. +#UnicastRetransWithoutProgressCount = 2 + +# Retransmission interval step between segments of a meesage to a unicast +# destination. +# Interval is measured in milliseconds and calculated using the following +# formula: +# +# (UnicastRetransIntervalStep + 1) * 25 ms +# +# Valid range 0-15. +# Defaults to 7. +#UnicastRetransIntervalStep = 7 + +# Interval step between segments of a message to a unicast destination that +# increases proportionally to (ttl - 1) when ttl is over 0. +# Increment is measured in milliseconds and calculated using the following +# formula: +# +# (UnicastRetransIntervalIncrement + 1) * 25 ms +# +# Valid range 0-15. +# Defaults to 1. +#UnicastRetransIntervalIncrement = 1 + +# Maximum number of retransmissions of segments to a multicast destination. +# Valid range 0-15. +# Defaults to 2. +#MulticastRetransCount = 2 + +# Retransmission interval step between segments of a meesage to a multicast +# destination. +# Interval is measured in milliseconds and calculated using the following +# formula: +# +# (MulticastRetransIntervalStep + 1) * 25 ms +# +# Valid range 0-15. +# Defaults to 8. +#MulticastRetransIntervalStep = 8 + +[SARReceiver] + +# Threshold number of segments in a message to retransmit acknowledgment +# messages. If the number of segments in a message exceeds SegmentsThreshold, +# retransmit the Acknowledgment message by AckRetransCount. +# Valid range 0-31. +# Defaults to 3 +#SegmentsThreshold = 3 + +# Interval increment between acknowledgment messages. +# Increment is measured in segments and calculated using the following formula: +# +# AckDelayIncrement + 1.5 +# +# Valid range 0-7 +# Defaults to 1 +#AckDelayIncrement = 1 + +# Maximum number of retransmissions of acknowledgment messages. +# Valid range 0-3 +# Defaults to 0 +#AckRetransCount = 0 + +# Timeout to discard a segmented message when no more new segments of the +# message are coming in. +# Timeout is measured in seconds and calculated using the following formula: +# +# (DiscardTimeout + 1) * 5 sec +# +# Valid range 0-15 +# Defaults to 1 +#DiscardTimeout = 1 + +# Interval between received segments of a message. This is used to control rate +# of transmission of acknowledgment messages. +# Increment is measured in milliseconds and calculated using the following +# formula: +# +# (ReceiverSegIntervalStep + 1) * 10 ms +# +# Valid range 0-15 +# Defaults to 5 +#ReceiverSegIntervalStep = 5 diff --git a/mesh/mesh.c b/mesh/mesh.c index f89230b6c..17236c110 100644 --- a/mesh/mesh.c +++ b/mesh/mesh.c @@ -248,16 +248,11 @@ void mesh_get_sar_receiver(void *sar_rxr) memcpy(sar_rxr, &mesh_sar_rxr, sizeof(struct mesh_sar_receiver)); } -static void parse_settings(const char *mesh_conf_fname) +static void parse_mesh_general(const struct l_settings *settings) { - struct l_settings *settings; char *str; uint32_t value; - settings = l_settings_new(); - if (!l_settings_load_from_file(settings, mesh_conf_fname)) - goto done; - str = l_settings_get_string(settings, "General", "Beacon"); if (str) { if (!strcasecmp(str, "true")) @@ -290,6 +285,79 @@ static void parse_settings(const char *mesh_conf_fname) if (l_settings_get_uint(settings, "General", "ProvTimeout", &value)) mesh.prov_timeout = value; +} + +static void parse_mesh_sar(const struct l_settings *settings) +{ + uint32_t value; + + if (l_settings_get_uint(settings, "SARTransmitter", "SegIntervalStep", + &value) && value <= 15) + mesh_sar_txr.seg_int_step = value; + + if (l_settings_get_uint(settings, "SARTransmitter", + "UnicastRetransCount", + &value) && value <= 15) + mesh_sar_txr.unicast_rtx_cnt = value; + + if (l_settings_get_uint(settings, "SARTransmitter", + "UnicastRetransWithoutProgressCount", + &value) && value <= 15) + mesh_sar_txr.unicast_rtx_without_prog_cnt = value; + + if (l_settings_get_uint(settings, "SARTransmitter", + "UnicastRetransIntervalStep", + &value) && value <= 15) + mesh_sar_txr.unicast_rtx_int_step = value; + + if (l_settings_get_uint(settings, "SARTransmitter", + "UnicastRetransIntervalIncrement", + &value) && value <= 15) + mesh_sar_txr.unicast_rtx_int_inc = value; + + if (l_settings_get_uint(settings, "SARTransmitter", + "MulticastRetransCount", + &value) && value <= 15) + mesh_sar_txr.multicast_rtx_cnt = value; + + if (l_settings_get_uint(settings, "SARTransmitter", + "MulticastRetransIntervalStep", + &value) && value <= 15) + mesh_sar_txr.multicast_rtx_int_step = value; + + if (l_settings_get_uint(settings, "SARReceiver", "SegmentsThreshold", + &value) && value <= 31) + mesh_sar_rxr.seg_threshold = value; + + if (l_settings_get_uint(settings, "SARReceiver", "AckDelayIncrement", + &value) && value <= 7) + mesh_sar_rxr.ack_delay_inc = value; + + if (l_settings_get_uint(settings, "SARReceiver", "AckRetransCount", + &value) && value <= 3) + mesh_sar_rxr.ack_rtx_cnt = value; + + if (l_settings_get_uint(settings, "SARReceiver", "DiscardTimeout", + &value) && value <= 15) + mesh_sar_rxr.discard_timeout = value; + + if (l_settings_get_uint(settings, "SARReceiver", + "ReceiverSegIntervalStep", + &value) && value <= 15) + mesh_sar_rxr.receiver_seg_int_step = value; +} + +static void parse_settings(const char *mesh_conf_fname) +{ + struct l_settings *settings; + + settings = l_settings_new(); + if (!l_settings_load_from_file(settings, mesh_conf_fname)) + goto done; + + parse_mesh_general(settings); + parse_mesh_sar(settings); + done: l_settings_free(settings); } From patchwork Mon Oct 14 07:55:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junho Lee X-Patchwork-Id: 13834283 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6304014F125 for ; Mon, 14 Oct 2024 07:55:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728892512; cv=none; b=JodulEsjT/sTGMayUMxBtNCWdlqX3qnNfo2BszwE5/x6ilsywiuzFt1T/ZYJ9U0gCfMJuy0CbW0yvywAO3V95KfU8xyBAXNwAyHSHstnZyvOkA3b/18APLp8SMg5XyE5DDNWdjHqNkwlhwFcu5THOvoTVzR5Rt1LFKveCqNI3oc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728892512; c=relaxed/simple; bh=22rmkplHJOZuJfQerTHUr1KtHf0Zubet17D6hFOCe7o=; h=Message-ID:Date:From:To:Subject:MIME-Version:Content-Type: Content-Disposition; b=a48TZDeHOZ5l36i5IY9WMzN8Z7BKAh+YFbFzA+FymsZlDE0sXINuX6NVVo+DfRs830ZAtXexFa4PfuymJJsED9S7A6B0yEjUVYduRWNcbponxRZfypFSQXMBm1zJcffezWzwhn+C4gPaqlpkNjWhN8ss9p8j+F/+LEs7BhCMke0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RRpVp0GH; arc=none smtp.client-ip=209.85.215.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RRpVp0GH" Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-7ae3d7222d4so3338591a12.3 for ; Mon, 14 Oct 2024 00:55:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728892510; x=1729497310; darn=vger.kernel.org; h=content-disposition:mime-version:subject:to:from:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=5cahgCFq8ehz8N/gd6lTB5/KBKLYT/QE1Od2NZO1lEw=; b=RRpVp0GHcfuhuCVE0OrALFmydPahFEwhD8p2aNdrKfUUpuZ1ZcJCT7Hk15bXCSt2I8 g/EdKaos5TRpUtbKRdzwQB+TAtaR2ytv7WYbRs85rJujOrXxYdbJnk7J8Xigx23f8N0g mRGhj7kh3f/s31EHS/BAtJr/G8WPbj7cDgdWMxSBPFDsqYc5baDoyeGrl/98y+laCMMD pZQIBcOexTYoAFcn/Su8aHWz23xwg67AmC+D97M9ng1uBbny2RyVpbYxYwGRwDrQPCwV c+95pj2TlaSGXrXgHgIxakLn8aFqRmpmdkJqymM9NY1nQyLR4uIoPOrsWc5vfIWyUNZv Hamg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728892510; x=1729497310; h=content-disposition:mime-version:subject:to:from:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5cahgCFq8ehz8N/gd6lTB5/KBKLYT/QE1Od2NZO1lEw=; b=MpIfDCJBtt7Ly1lPhm7g2Qu6ZKRI0IMfrYudTroeErUpQ62Tq+xrqv05UUBh7KPsJ2 2nriRmKkl8+2qyw2m+c57ruhRAdfq3LUJ1ypgatw3P9E3uqrwtK5utEmY0YYROcTAbAS AxeXpVVmRXzD6IHfasyuN6KQY1IoMDm0HAGiBgsoIV3Nh4wTLiYeA2yTD5AOxAf9d8TK SwUDhwa5mJlx2wKFr/6NDv+MWNQyRHaXMmwVAV6R/Sl0i7WbpcyHJ30H0LNtD2IElMsD pXIV3dgJzey1osk2Lou7HjgqzpkI7Pjt0tuINFI7EtGbT5cpoNByMswIEdcM4HfFPabd Yorg== X-Gm-Message-State: AOJu0YwArbh8XaccAP9qJ0E3/lC8R3pzlsjN1LmMFWJsaTkVXajRLXyE QSC1yrC6Q+7rcblSTt4Lol8DQvCXkcrPwiiZ3mpg8rWLJ+vHHTPGp/zzPg== X-Google-Smtp-Source: AGHT+IGBBcIQ1JZsUgMNglKHibUBSIEKGw+yMUoZmsCbqXYey0lhJGXbX2v9OUHRba6IOU04UcHSCQ== X-Received: by 2002:a05:6a20:43a9:b0:1cc:da14:316a with SMTP id adf61e73a8af0-1d8bcf2f4f0mr14946117637.20.1728892510270; Mon, 14 Oct 2024 00:55:10 -0700 (PDT) Received: from JUNHO-NEOSTACK. ([221.154.134.3]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7ea8885df80sm1262337a12.74.2024.10.14.00.55.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Oct 2024 00:55:09 -0700 (PDT) Message-ID: <670cce5d.650a0220.14e0cd.22b4@mx.google.com> X-Google-Original-Message-ID: Date: Mon, 14 Oct 2024 16:55:07 +0900 From: Junho Lee To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ v3 3/4] mesh: Fix inserting NULL into bool type arguments to false Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline Inserting NULL into a variable of type bool is undefined behavior and inconsistent. --- mesh/net.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mesh/net.c b/mesh/net.c index 48032c64d..82c812b73 100644 --- a/mesh/net.c +++ b/mesh/net.c @@ -2649,7 +2649,7 @@ static enum _relay_advice packet_received(void *user_data, msg, app_msg_len); } } else { - seg_rxed(net, NULL, iv_index, net_ttl, + seg_rxed(net, false, iv_index, net_ttl, net_seq, net_idx, net_src, net_dst, key_aid, net_szmic, net_seqZero, net_segO, net_segN, @@ -2657,10 +2657,10 @@ static enum _relay_advice packet_received(void *user_data, } } else { - msg_rxed(net, NULL, iv_index, net_ttl, net_seq, net_idx, - net_src, net_dst, key_aid, false, - false, net_seq & SEQ_ZERO_MASK, msg, - app_msg_len); + msg_rxed(net, false, iv_index, net_ttl, net_seq, + net_idx, net_src, net_dst, key_aid, + false, false, net_seq & SEQ_ZERO_MASK, + msg, app_msg_len); } /* If this is one of our Unicast addresses, disallow relay */ From patchwork Mon Oct 14 07:55:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junho Lee X-Patchwork-Id: 13834284 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DBACB14D444 for ; Mon, 14 Oct 2024 07:55:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728892526; cv=none; b=fEiiV68ryfvGyS4oNqU/JRewkaXxaY9HJL9e555+/q+VIOE/ym9kdhpx4cSSW3k0BMzFQm7E8YIUfZ9qQY73GjAm8U4YSx6cpQYLxlV+YW/E7A2PpQSuJRzicg030Hwn+A6OipVZuoy+s9iay59TiJ8RFYPQUDrvq6kJnm5/vy4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728892526; c=relaxed/simple; bh=JmYb6ifQ86UeWoGHhjqShvZG20k92ozqfJ6YZ15xk4M=; h=Message-ID:Date:From:To:Subject:MIME-Version:Content-Type: Content-Disposition; b=cqFHDE4kEGmoDqmD8FAuXeTZj5duH94TDY7iEb15pEdLlvzOrA/DYaQtWpglX7GMOUdI4aU8AuNfGG2QDmwRd8pxk4VubQOj8Svol0apMBIqWwUwR6ad0kXkA/eKQQLX+fv9wmYAUtGp0/yvSp0yI9/H8cAWUEnGhtrXP9k5ErQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Xe32S2Lk; arc=none smtp.client-ip=209.85.210.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Xe32S2Lk" Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-71e7086c231so1462b3a.0 for ; Mon, 14 Oct 2024 00:55:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728892524; x=1729497324; darn=vger.kernel.org; h=content-disposition:mime-version:subject:to:from:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=yIhx+0artsZ/LvTOSJX5T7M/xobMHq3FpjBhY04kOaY=; b=Xe32S2LkZXPbZU7UM+Iw5vJCVfdNGrIUo2u1o6SFTWLc2a6SWy54ilbHRRMaAHvT3J rMFtpIxbjWHXyO90aWT8Zf8v1/nYmE6QckNH0Y81UeSEXkonv3PsaqdFm9CbygtO79pl WyHcHRxxNG4ikv2ue3uBcYlMqM+IkNCZn94BQxO8hx1dVs9Lgl/kaLwoSuFcabhVo+rx oqrEf+tBJuIVhKvQ8eGBqF/+HbPvTotvAZKQU+AJEjTkVlbhT/FqOlNvIspTqPpqf+tE 5+h1Rfwt+1icswOL/9z4Pa93rgebhHhyZSktSjjxuk+gAS23lZUpBz5Q3ak6oBBW4O4H 1Zfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728892524; x=1729497324; h=content-disposition:mime-version:subject:to:from:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=yIhx+0artsZ/LvTOSJX5T7M/xobMHq3FpjBhY04kOaY=; b=qPCKLbFtIKx3rrLAV4bBDBwPyQ8g4SxAcGKl+cBY4wjT7SPsWWxMm/Jji3BZQUkEGa XJXiNOLYtfDx33cNf8ZI67CHxpqPVXLzX07d2BDm9WncFKNKqSq3a1kiCO0GK0XEgteu atMzADL4KPsKC5+JUkwRblPBRXzxWaJIgTf/EiA7Mta54m778O5qGQ9ayzBnFWBjXpsf sRnW8hoqkz8Tnksv6sD3pkKaqfoxKrekACf7C42ti2OCfzEXB8ei6xicZttaUUkzcV+g RXYiarLZpp05qNS4LoTV5frrUf5uuPW4I3V65DHfPQ9/fRdmzqhGp87V/je31YPSMKki OW0w== X-Gm-Message-State: AOJu0Yw4VkBykRguoigHv/90ii9DsvTheAuDyox8lbX2KkdSQ9JRI+J+ Oibv5sDdqj5WqGADrJVr3k5VHM4YP+XS2j4fXpc7jvyy7LMQO0aNzNyUAA== X-Google-Smtp-Source: AGHT+IFvJicj2nEI02mgLJSNqE10V4LDQhJAduDZlUS97qQVzOwH4LH6u03tkmHeZ5Z+pfoLso1D9Q== X-Received: by 2002:a05:6a00:2d16:b0:71e:6c65:e7c8 with SMTP id d2e1a72fcca58-71e6c65e904mr1519890b3a.23.1728892523357; Mon, 14 Oct 2024 00:55:23 -0700 (PDT) Received: from JUNHO-NEOSTACK. ([221.154.134.3]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71e4ad1b9f7sm4274733b3a.190.2024.10.14.00.55.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Oct 2024 00:55:23 -0700 (PDT) Message-ID: <670cce6b.a70a0220.57c0d.a50a@mx.google.com> X-Google-Original-Message-ID: Date: Mon, 14 Oct 2024 16:55:20 +0900 From: Junho Lee To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ v3 4/4] mesh: Add features of Segmented Control message Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline According to Mesh Protocol v1.1, with the addition of Transport Control messages with variable length PDU such as 'Friend Subscription List Add' and 'Friend Subscription List Remove', it is necessary to support segmentation in the Lower Transport layer because the Upper Transport Control PDU can be larger than the size of a single Network PDU. This is achieved by performing the segmentation function for Transport Control messages, where the segmentation of Transport Control messages is the same as for Access messages, but with different message fields and lengths, so the segmentation is controlled by branching. It was written to perform the function as little as possible without changing the existing design. We avoided modifying arguments outside of static functions, and kept the existing working design unchanged. However, some macro definitions had to be modified because they were written based on Access messages, so we changed them to work by comparing the Transport Control message flag. This commit does not support segmentation for control messages as a friend of Low Power Nodes. This should be added later. --- mesh/crypto.c | 69 +++++----- mesh/net.c | 279 +++++++++++++++++++++++++--------------- mesh/net.h | 33 ++++- unit/test-mesh-crypto.c | 6 +- 4 files changed, 248 insertions(+), 139 deletions(-) diff --git a/mesh/crypto.c b/mesh/crypto.c index b712a2654..08548031b 100644 --- a/mesh/crypto.c +++ b/mesh/crypto.c @@ -532,7 +532,8 @@ bool mesh_crypto_packet_build(bool ctl, uint8_t ttl, uint8_t *packet, uint8_t *packet_len) { uint32_t hdr; - size_t n; + size_t hdr_offset = 9; + size_t payload_offset = 10; if (seq > SEQ_MASK) return false; @@ -543,50 +544,44 @@ bool mesh_crypto_packet_build(bool ctl, uint8_t ttl, l_put_be16(src, packet + 5); l_put_be16(dst, packet + 7); - n = 9; - if (!ctl) { - uint32_t tmp = segmented ? 0x1 : 0; + hdr = (segmented ? 0x1 : 0) << SEG_HDR_SHIFT; + + if (segmented) { + hdr |= (seqZero & SEQ_ZERO_MASK) << SEQ_ZERO_HDR_SHIFT; + hdr |= (segO & SEG_MASK) << SEGO_HDR_SHIFT; + hdr |= (segN & SEG_MASK) << SEGN_HDR_SHIFT; + payload_offset += 3; + } - hdr = tmp << SEG_HDR_SHIFT; + if (!ctl) { hdr |= (key_aid & KEY_ID_MASK) << KEY_HDR_SHIFT; if (segmented) { hdr |= szmic << SZMIC_HDR_SHIFT; - hdr |= (seqZero & SEQ_ZERO_MASK) << SEQ_ZERO_HDR_SHIFT; - hdr |= (segO & SEG_MASK) << SEGO_HDR_SHIFT; - hdr |= (segN & SEG_MASK) << SEGN_HDR_SHIFT; } - l_put_be32(hdr, packet + n); - - /* Only first octet is valid for unsegmented messages */ - if (segmented) - n += 4; - else - n += 1; - - memcpy(packet + n, payload, payload_len); - - l_put_be32(0x00000000, packet + payload_len + n); - if (packet_len) - *packet_len = payload_len + n + 4; } else { if ((opcode & OPCODE_MASK) != opcode) return false; - hdr = opcode << KEY_HDR_SHIFT; - l_put_be32(hdr, packet + n); - n += 1; + hdr |= opcode << OPCODE_HDR_SHIFT; + } + + l_put_be32(hdr, packet + hdr_offset); - memcpy(packet + n, payload, payload_len); - n += payload_len; + memcpy(packet + payload_offset, payload, payload_len); - l_put_be64(0x0000000000000000, packet + n); + if (!ctl) { + l_put_be32(0x00000000, packet + payload_offset + payload_len); if (packet_len) - *packet_len = n + 8; + *packet_len = payload_offset + payload_len + 4; + } else { + l_put_be64(0x0000000000000000, packet + payload_offset + + payload_len); + if (packet_len) + *packet_len = payload_offset + payload_len + 8; } - return true; } @@ -665,6 +660,22 @@ bool mesh_crypto_packet_parse(const uint8_t *packet, uint8_t packet_len, if (payload_len) *payload_len = packet_len - 9; + } else if (is_segmented) { + if (seqZero) + *seqZero = (hdr >> SEQ_ZERO_HDR_SHIFT) & + SEQ_ZERO_MASK; + + if (segO) + *segO = (hdr >> SEGO_HDR_SHIFT) & SEG_MASK; + + if (segN) + *segN = (hdr >> SEGN_HDR_SHIFT) & SEG_MASK; + + if (payload) + *payload = packet + 13; + + if (payload_len) + *payload_len = packet_len - 13; } else { if (payload) *payload = packet + 10; diff --git a/mesh/net.c b/mesh/net.c index 82c812b73..215db995c 100644 --- a/mesh/net.c +++ b/mesh/net.c @@ -179,12 +179,20 @@ struct mesh_sar { uint16_t src; uint16_t remote; uint16_t len; - bool szmic; bool segmented; + bool ctl; bool frnd; bool frnd_cred; uint8_t ttl; - uint8_t key_aid; + union { + struct { + uint8_t key_aid; + bool szmic; + }; /* Access message */ + struct { + uint8_t opcode; + }; /* Transport Control message */ + }; uint8_t buf[4]; /* Large enough for ACK-Flags and MIC */ }; @@ -1964,7 +1972,7 @@ static bool msg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, hdr |= (uint32_t) 0x01 << SEG_HDR_SHIFT; hdr |= szmic << SZMIC_HDR_SHIFT; hdr |= (seqZero & SEQ_ZERO_MASK) << SEQ_ZERO_HDR_SHIFT; - hdr |= SEG_MAX(true, size) << SEGN_HDR_SHIFT; + hdr |= SEG_MAX(false, true, size) << SEGN_HDR_SHIFT; } if (friend_packet_queue(net, iv_index, false, frnd_ttl, @@ -2141,11 +2149,18 @@ static void friend_seg_rxed(struct mesh_net *net, frnd_msg->cnt_in++; } +static bool ctl_rxed(struct mesh_net *net, uint32_t net_key_id, + uint32_t iv_index, uint8_t ttl, + uint32_t seq, uint16_t src, + uint16_t dst, uint8_t opcode, + int8_t rssi, const uint8_t *pkt, + uint8_t len); + static bool seg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, uint8_t ttl, uint32_t seq, uint16_t net_idx, - uint16_t src, uint16_t dst, - uint8_t key_aid, + uint16_t src, uint16_t dst, bool ctl, + uint8_t opcode, uint8_t key_aid, bool szmic, uint16_t seqZero, uint8_t segO, uint8_t segN, const uint8_t *data, uint8_t size) @@ -2194,10 +2209,15 @@ static bool seg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, l_debug("RXed (old: %04x %06x size:%d) %d of %d", seqZero, seq, size, segO, segN); /* Sanity Check--> certain things must match */ - if (SEG_MAX(true, sar->len) != segN || - sar->key_aid != key_aid) + if (SEG_MAX(ctl, true, sar->len) != segN) return false; + if (!ctl && sar->key_aid != key_aid) { + return false; + } else if (ctl && sar->opcode != opcode) { + return false; + } + if (sar->flags == expected) { /* * According to MshPRTv1.1: 3.5.3.4, if the destination @@ -2217,7 +2237,7 @@ static bool seg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, return true; } } else { - uint16_t len = MAX_SEG_TO_LEN(segN); + uint16_t len = MAX_SEG_TO_LEN(ctl, segN); l_debug("RXed (new: %04x %06x size: %d len: %d) %d of %d", seqZero, seq, size, len, segO, segN); @@ -2228,9 +2248,12 @@ static bool seg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, sar->src = dst; sar->remote = src; sar->seqZero = seqZero; - sar->key_aid = key_aid; sar->len = len; sar->net_idx = net_idx; + if (ctl) + sar->opcode = opcode; + else + sar->key_aid = key_aid; sar_in = mesh_sar_rx_new(); sar_in->sar = sar; @@ -2270,14 +2293,14 @@ static bool seg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, l_timeout_remove(sar_in->msg_timeout); sar_in->msg_timeout = NULL; - seg_off = segO * MAX_SEG_LEN; + seg_off = segO * MAX_SEG_LEN(ctl); memcpy(sar->buf + seg_off, data, size); sar->flags |= this_seg_flag; sar->ttl = ttl; /* Msg length only definitive on last segment */ if (segO == segN) - sar->len = segN * MAX_SEG_LEN + size; + sar->len = segN * MAX_SEG_LEN(ctl) + size; /* Send ACK only if DST is unicast address. */ if (IS_UNICAST(dst)) { @@ -2290,9 +2313,21 @@ static bool seg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, /* Got it all */ send_net_ack(net, sar, expected); - msg_rxed(net, frnd, iv_index, ttl, seq, net_idx, - sar->remote, dst, key_aid, true, szmic, - sar->seqZero, sar->buf, sar->len); + if (!ctl) { + msg_rxed(net, frnd, iv_index, ttl, seq, net_idx, + sar->remote, dst, key_aid, true, szmic, + sar->seqZero, sar->buf, sar->len); + } else { + struct mesh_subnet *subnet = l_queue_find(net->subnets, + match_key_index, + L_UINT_TO_PTR(net_idx)); + if (!subnet) + return false; + + ctl_rxed(net, subnet->net_key_tx, iv_index, ttl, + seq, sar->remote, dst, + opcode, 0, sar->buf, sar->len); + } /* * Delay SAR removal to be able to acknowledge a transaction @@ -2312,7 +2347,7 @@ static bool seg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index, return false; } -static bool ctl_received(struct mesh_net *net, uint32_t net_key_id, +static bool ctl_rxed(struct mesh_net *net, uint32_t net_key_id, uint32_t iv_index, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dst, @@ -2324,7 +2359,11 @@ static bool ctl_received(struct mesh_net *net, uint32_t net_key_id, uint8_t n = 0; uint16_t net_idx; - if (ttl > 1) { + /* TODO: If length is greater than 11, it must be segmented, so it must + * be able to handle Segmented Control messages when acting as a friend + * node. + */ + if (ttl > 1 && len <= 11) { uint32_t hdr = opcode << OPCODE_HDR_SHIFT; uint8_t frnd_ttl = ttl - 1; @@ -2625,8 +2664,15 @@ static enum _relay_advice packet_received(void *user_data, ack_rxed(net, net_src, net_dst, net_seqZero, l_get_be32(msg + 3)); + } else if (net_segmented) { + seg_rxed(net, false, iv_index, net_ttl, + net_seq, net_idx, net_src, + net_dst, net_ctl, net_opcode, + key_aid, net_szmic, net_seqZero, + net_segO, net_segN, + msg, app_msg_len); } else { - ctl_received(net, net_key_id, iv_index, net_ttl, + ctl_rxed(net, net_key_id, iv_index, net_ttl, net_seq, net_src, net_dst, net_opcode, rssi, msg, app_msg_len); @@ -2651,8 +2697,9 @@ static enum _relay_advice packet_received(void *user_data, } else { seg_rxed(net, false, iv_index, net_ttl, net_seq, net_idx, net_src, - net_dst, key_aid, net_szmic, - net_seqZero, net_segO, net_segN, + net_dst, net_ctl, net_opcode, + key_aid, net_szmic, net_seqZero, + net_segO, net_segN, msg, app_msg_len); } @@ -3371,16 +3418,16 @@ static bool send_seg(struct mesh_net *net, uint8_t cnt, uint16_t interval, uint8_t gatt_data[30]; uint8_t *packet = gatt_data; uint8_t packet_len; - uint8_t segN = SEG_MAX(msg->segmented, msg->len); - uint16_t seg_off = SEG_OFF(segO); + uint8_t segN = SEG_MAX(msg->ctl, msg->segmented, msg->len); + uint16_t seg_off = SEG_OFF(msg->ctl, segO); uint32_t seq_num; if (msg->segmented) { /* Send each segment on unique seq_num */ seq_num = mesh_net_next_seq_num(net); - if (msg->len - seg_off > SEG_OFF(1)) - seg_len = SEG_OFF(1); + if (msg->len - seg_off > SEG_OFF(msg->ctl, 1)) + seg_len = SEG_OFF(msg->ctl, 1); else seg_len = msg->len - seg_off; } else { @@ -3396,12 +3443,12 @@ static bool send_seg(struct mesh_net *net, uint8_t cnt, uint16_t interval, l_debug("segN %d segment %d seg_off %d", segN, segO, seg_off); /* TODO: Are we RXing on an LPN's behalf? Then set RLY bit */ - if (!mesh_crypto_packet_build(false, msg->ttl, seq_num, msg->src, - msg->remote, 0, msg->segmented, - msg->key_aid, msg->szmic, false, - msg->seqZero, segO, segN, - msg->buf + seg_off, seg_len, - packet + 1, &packet_len)) { + if (!mesh_crypto_packet_build(msg->ctl, msg->ttl, seq_num, msg->src, + msg->remote, msg->opcode, + msg->segmented, msg->key_aid, + msg->szmic, false, msg->seqZero, + segO, segN, msg->buf + seg_off, + seg_len, packet + 1, &packet_len)) { l_error("Failed to build packet"); return false; } @@ -3424,6 +3471,63 @@ static bool send_seg(struct mesh_net *net, uint8_t cnt, uint16_t interval, return true; } +static bool mesh_net_send(struct mesh_net *net, struct mesh_sar *payload, + uint8_t segN) +{ + bool result = false; + + if (payload->segmented) { + struct mesh_sar_tx *drop_sar_tx; + + payload->flags = 0xffffffff >> (31 - segN); + payload->seqZero = payload->seqAuth & SEQ_ZERO_MASK; + + /* Single thread SAR messages to same Unicast DST */ + drop_sar_tx = l_queue_find(net->sar_out, match_sar_tx_remote, + L_UINT_TO_PTR(payload->remote)); + if (drop_sar_tx) { + /* Cancel incomplete prior SAR on the same dst */ + l_debug("Cancel incompleted SAR: SeqZero %4.4x", + drop_sar_tx->sar->seqZero); + l_queue_remove(net->sar_out, drop_sar_tx); + mesh_sar_tx_free(drop_sar_tx); + } + } + + result = send_seg(net, net->tx_cnt, net->tx_interval, payload, 0); + + /* + * Set the timeout to send the next seg or retransmit if the payload is + * segmented. Flush if it is not segmented or if the transmission + * failed. + */ + if (result && payload->segmented) { + struct mesh_sar_tx *sar_tx = mesh_sar_tx_new(); + bool is_unicast = IS_UNICAST(payload->remote); + + sar_tx->ack_received = false; + sar_tx->int_ms = sar_tx_seg_int_ms(net->sar_txr); + sar_tx->attempt_left = sar_tx_retrans_cnt(net->sar_txr, + is_unicast, false); + sar_tx->attempt_left_no_progress = sar_tx_retrans_cnt( + net->sar_txr, + is_unicast, true); + sar_tx->retrans_ms = sar_tx_retrans_timeout_ms(net->sar_txr, + is_unicast, + payload->ttl); + sar_tx->sar = payload; + l_queue_push_head(net->sar_out, sar_tx); + sar_tx->seg_timeout = l_timeout_create_ms(sar_tx->int_ms, + send_next_seg_to, net, NULL); + sar_tx->segO = 1; /* The 0th seg is already sent. */ + sar_tx->segN = segN; + } else { + mesh_sar_free(payload); + } + + return result; +} + void mesh_net_send_seg(struct mesh_net *net, uint32_t net_key_id, uint32_t iv_index, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dst, uint32_t hdr, @@ -3497,7 +3601,7 @@ bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src, /* Long and sizmic messages *require* segmenting */ segmented |= szmic; - seg_max = SEG_MAX(segmented, msg_len); + seg_max = SEG_MAX(false, segmented, msg_len); segmented |= !!(seg_max); /* First enqueue to any Friends and internal models */ @@ -3524,6 +3628,7 @@ bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src, payload = mesh_sar_new(msg_len); memcpy(payload->buf, msg, msg_len); payload->len = msg_len; + payload->ctl = false; payload->src = src; payload->remote = dst; payload->ttl = ttl; @@ -3535,53 +3640,7 @@ bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src, payload->seqAuth = seq; payload->segmented = segmented; - if (segmented) { - struct mesh_sar_tx *drop_sar_tx; - payload->flags = 0xffffffff >> (31 - seg_max); - payload->seqZero = seq & SEQ_ZERO_MASK; - - /* Single thread SAR messages to same Unicast DST */ - drop_sar_tx = l_queue_find(net->sar_out, match_sar_tx_remote, - L_UINT_TO_PTR(dst)); - if (drop_sar_tx) { - /* Cancel incomplete prior SAR on the same dst */ - l_debug("Cancel incompleted SAR: SeqZero %4.4x", - drop_sar_tx->sar->seqZero); - l_queue_remove(net->sar_out, drop_sar_tx); - mesh_sar_tx_free(drop_sar_tx); - } - } - - result = send_seg(net, cnt, interval, payload, 0); - - /* - * Set the timeout to send the next seg or retransmit if the payload is - * segmented. Flush if it is not segmented or if the transmission - * failed. - */ - if (result && segmented) { - struct mesh_sar_tx *sar_tx = mesh_sar_tx_new(); - bool is_unicast = IS_UNICAST(dst); - - sar_tx->ack_received = false; - sar_tx->int_ms = sar_tx_seg_int_ms(net->sar_txr); - sar_tx->attempt_left = sar_tx_retrans_cnt(net->sar_txr, - is_unicast, false); - sar_tx->attempt_left_no_progress = sar_tx_retrans_cnt( - net->sar_txr, - is_unicast, true); - sar_tx->retrans_ms = sar_tx_retrans_timeout_ms(net->sar_txr, - is_unicast, - ttl); - sar_tx->sar = payload; - l_queue_push_head(net->sar_out, sar_tx); - sar_tx->seg_timeout = l_timeout_create_ms(sar_tx->int_ms, - send_next_seg_to, net, NULL); - sar_tx->segO = 1; /* The 0th seg is already sent. */ - sar_tx->segN = seg_max; - } else { - mesh_sar_free(payload); - } + result = mesh_net_send(net, payload, seg_max); return result; } @@ -3640,11 +3699,18 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t net_key_id, uint16_t dst, const uint8_t *msg, uint16_t msg_len) { - uint32_t use_seq = seq; - uint8_t pkt_len; - uint8_t pkt[30]; + struct mesh_sar *payload; + uint8_t opcode, seg_max; + bool segmented = false; bool result = false; + /* + * Check maximum message length: + * Parameter length(8) * Maximum # of segments(32) + Header size(1) + */ + if (!net || msg_len > 257) + return; + if (!net->src_addr) return; @@ -3657,10 +3723,19 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t net_key_id, if (ttl == DEFAULT_TTL) ttl = net->default_ttl; - /* Range check the Opcode and msg length*/ - if (*msg & 0xc0 || (9 + msg_len + 8 > 29)) + /* + * Mesh Protocol v1.1: An unassigned address shall not be used in the + * SRC field or the DST field of a Network PDU. + */ + if (IS_UNASSIGNED(src) || IS_UNASSIGNED(dst)) return; + segmented |= msg[0] & SEGMENTED; + seg_max = SEG_MAX(true, segmented, msg_len - 1); + segmented |= !!(seg_max); + + opcode = msg[0] & OPCODE_MASK; + /* * MshPRFv1.0.1 section 3.4.5.2, Interface output filter: * If TTL is set to 1, message shall be dropped. @@ -3681,36 +3756,38 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t net_key_id, /* Deliver to Local entities if applicable */ if (!(dst & 0x8000) && src >= net->src_addr && src <= net->last_addr) - result = ctl_received(net, net_key_id, iv_index, ttl, + result = ctl_rxed(net, net_key_id, iv_index, ttl, mesh_net_next_seq_num(net), src, dst, msg[0], 0, msg + 1, msg_len - 1); if (!net_key_id) { + seq = mesh_net_next_seq_num(net); + + if (result || (dst >= net->src_addr && dst <= net->last_addr)) + return; + } else { struct mesh_subnet *subnet = l_queue_find(net->subnets, - match_key_index, L_UINT_TO_PTR(net_idx)); + match_key_id, L_UINT_TO_PTR(net_key_id)); if (!subnet) return; - net_key_id = subnet->net_key_tx; - use_seq = mesh_net_next_seq_num(net); - - if (result || (dst >= net->src_addr && dst <= net->last_addr)) - return; + net_idx = subnet->idx; } - if (!mesh_crypto_packet_build(true, ttl, use_seq, src, dst, msg[0], - false, 0, false, false, 0, 0, 0, msg + 1, - msg_len - 1, pkt + 1, &pkt_len)) - return; - - if (!net_key_encrypt(net_key_id, iv_index, pkt + 1, pkt_len)) { - l_error("Failed to encode packet"); - return; - } + payload = mesh_sar_new(msg_len - 1); + memcpy(payload->buf, msg + 1, msg_len - 1); + payload->len = msg_len - 1; + payload->ctl = true; + payload->ttl = ttl; + payload->src = src; + payload->remote = dst; + payload->opcode = opcode; + payload->net_idx = net_idx; + payload->iv_index = iv_index; + payload->seqAuth = seq; + payload->segmented = segmented; - if (!(IS_UNASSIGNED(dst))) - send_msg_pkt(net, net->tx_cnt, net->tx_interval, pkt, - pkt_len + 1); + mesh_net_send(net, payload, seg_max); } int mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t idx, diff --git a/mesh/net.h b/mesh/net.h index d385ba16e..285c8e355 100644 --- a/mesh/net.h +++ b/mesh/net.h @@ -26,13 +26,32 @@ struct mesh_node; #define KEY_CACHE_SIZE 64 #define FRND_CACHE_MAX 32 -#define MAX_UNSEG_LEN 15 /* msg_len == 11 + sizeof(MIC) */ -#define MAX_SEG_LEN 12 /* UnSeg length - 3 octets overhead */ -#define SEG_MAX(seg, len) ((!seg && len <= MAX_UNSEG_LEN) ? 0 : \ - (((len) - 1) / MAX_SEG_LEN)) - -#define SEG_OFF(seg) ((seg) * MAX_SEG_LEN) -#define MAX_SEG_TO_LEN(seg) ((seg) ? SEG_OFF((seg) + 1) : MAX_UNSEG_LEN) +#define MAX_CTL_UNSEG_LEN 11 /* msg_len == 7 + sizeof(MIC) */ +#define MAX_CTL_SEG_LEN 8 /* UnSeg length - 3 octets overhead */ +#define CTL_SEG_MAX(seg, len) ((!(seg) && (len) <= MAX_CTL_UNSEG_LEN) ? 0 : \ + (((len) - 1) / MAX_CTL_SEG_LEN)) + +#define MAX_ACC_UNSEG_LEN 15 /* msg_len == 11 + sizeof(MIC) */ +#define MAX_ACC_SEG_LEN 12 /* UnSeg length - 3 octets overhead */ +#define ACC_SEG_MAX(seg, len) ((!(seg) && (len) <= MAX_ACC_UNSEG_LEN) ? 0 : \ + (((len) - 1) / MAX_ACC_SEG_LEN)) + +#define MAX_UNSEG_LEN(ctl) ((ctl) ? MAX_CTL_UNSEG_LEN : MAX_ACC_UNSEG_LEN) +#define MAX_SEG_LEN(ctl) ((ctl) ? MAX_CTL_SEG_LEN : MAX_ACC_SEG_LEN) +#define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ + ACC_SEG_MAX((seg), (len))) + +#define CTL_SEG_OFF(seg) ((seg) * MAX_CTL_SEG_LEN) +#define MAX_CTL_SEG_TO_LEN(seg) ((seg) ? CTL_SEG_OFF((seg) + 1) : \ + MAX_CTL_UNSEG_LEN) + +#define ACC_SEG_OFF(seg) ((seg) * MAX_ACC_SEG_LEN) +#define MAX_ACC_SEG_TO_LEN(seg) ((seg) ? ACC_SEG_OFF((seg) + 1) : \ + MAX_ACC_UNSEG_LEN) + +#define SEG_OFF(ctl, seg) ((ctl) ? CTL_SEG_OFF(seg) : ACC_SEG_OFF(seg)) +#define MAX_SEG_TO_LEN(ctl, seg) ((ctl) ? MAX_CTL_SEG_TO_LEN(seg) : \ + MAX_ACC_SEG_TO_LEN(seg)) #define SEGMENTED 0x80 #define UNSEGMENTED 0x00 diff --git a/unit/test-mesh-crypto.c b/unit/test-mesh-crypto.c index 39632d973..2a2431057 100644 --- a/unit/test-mesh-crypto.c +++ b/unit/test-mesh-crypto.c @@ -1087,7 +1087,8 @@ static void check_encrypt(const struct mesh_crypto_test *keys) app_msg = l_util_from_hexstring(keys->app_msg, &app_msg_len); if (keys->szmic) { - seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); + seg_max = SEG_MAX(false, keys->segmented, + app_msg_len + 8); enc_msg = l_malloc(app_msg_len + 8); status = mesh_crypto_payload_encrypt(aad, app_msg, @@ -1097,7 +1098,8 @@ static void check_encrypt(const struct mesh_crypto_test *keys) keys->szmic, keys->akf ? app_key : dev_key); } else { - seg_max = SEG_MAX(keys->segmented, app_msg_len + 4); + seg_max = SEG_MAX(false, keys->segmented, + app_msg_len + 4); enc_msg = l_malloc(app_msg_len + 4); status = mesh_crypto_payload_encrypt(aad, app_msg,