diff mbox series

[BlueZ,1/4] mesh: Implement lower transport layer for segmentation and reassembly

Message ID 66ff99e5.630a0220.2b5d14.8e61@mx.google.com (mailing list archive)
State Superseded
Headers show
Series mesh: Fix segmentation behavior of Lower transport layer | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
tedd_an/CheckPatch fail ERROR:FUNCTION_WITHOUT_ARGS: Bad function definition - struct mesh_sar_tx *mesh_sar_tx_new() should probably be struct mesh_sar_tx *mesh_sar_tx_new(void) #399: FILE: mesh/net.c:619: +static struct mesh_sar_tx *mesh_sar_tx_new() ERROR:FUNCTION_WITHOUT_ARGS: Bad function definition - struct mesh_sar_rx *mesh_sar_rx_new() should probably be struct mesh_sar_rx *mesh_sar_rx_new(void) #421: FILE: mesh/net.c:641: +static struct mesh_sar_rx *mesh_sar_rx_new() WARNING:LONG_LINE_COMMENT: line length of 93 exceeds 80 columns #902: FILE: mesh/net.c:2207: + * [acknowledgment delay increment * segment reception interval] ERROR:SPACING: space required before the open parenthesis '(' #1003: FILE: mesh/net.c:2283: + if(IS_UNICAST(dst)) { WARNING:LINE_SPACING: Missing a blank line after declarations #1138: FILE: mesh/net.c:3565: + bool is_unicast = IS_UNICAST(dst); + sar_tx->ack_received = false; /github/workspace/src/src/13821809.patch total: 3 errors, 2 warnings, 1011 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/src/13821809.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS.
tedd_an/GitLint fail WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search 1: T1 Title exceeds max length (81>80): "[BlueZ,1/4] mesh: Implement lower transport layer for segmentation and reassembly"
tedd_an/BuildEll success Build ELL PASS
tedd_an/BluezMake fail BluezMake FAIL: tools/mgmt-tester.c: In function ‘main’: tools/mgmt-tester.c:12725:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without 12725 | int main(int argc, char *argv[]) | ^~~~ unit/test-mesh-crypto.c: In function ‘check_encrypt’: unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^ In file included from ./mesh/crypto.c:21, from unit/test-mesh-crypto.c:20: ./mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function) 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^~~~~~~ unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1100 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 4); | ^ In file included from ./mesh/crypto.c:21, from unit/test-mesh-crypto.c:20: ./mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:4690: all] Error 2
tedd_an/MakeCheck fail BlueZ Make Check FAIL:
tedd_an/MakeDistcheck fail Make Distcheck FAIL: Package cups was not found in the pkg-config search path. Perhaps you should add the directory containing `cups.pc' to the PKG_CONFIG_PATH environment variable No package 'cups' found ../../unit/test-mesh-crypto.c: In function ‘check_encrypt’: ../../unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^ In file included from ../../mesh/crypto.c:21, from ../../unit/test-mesh-crypto.c:20: ../../mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | ../../unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function) 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^~~~~~~ ../../unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in ../../unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1100 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 4); | ^ In file included from ../../mesh/crypto.c:21, from ../../unit/test-mesh-crypto.c:20: ../../mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | make[4]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1 make[4]: *** Waiting for unfinished jobs.... make[3]: *** [Makefile:11924: check-TESTS] Error 2 make[2]: *** [Makefile:12353: check-am] Error 2 make[1]: *** [Makefile:12355: check] Error 2 make: *** [Makefile:12276: distcheck] Error 1
tedd_an/CheckValgrind fail Check Valgrind FAIL: tools/mgmt-tester.c: In function ‘main’: tools/mgmt-tester.c:12725:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without 12725 | int main(int argc, char *argv[]) | ^~~~ unit/test-mesh-crypto.c: In function ‘check_encrypt’: unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^ In file included from ./mesh/crypto.c:21, from unit/test-mesh-crypto.c:20: ./mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function) 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^~~~~~~ unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1100 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 4); | ^ In file included from ./mesh/crypto.c:21, from unit/test-mesh-crypto.c:20: ./mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:12355: check] Error 2
tedd_an/CheckSmatch fail CheckSparse: FAIL: src/shared/crypto.c:271:21: warning: Variable length array is used. src/shared/crypto.c:272:23: warning: Variable length array is used. src/shared/gatt-helpers.c:768:31: warning: Variable length array is used. src/shared/gatt-helpers.c:830:31: warning: Variable length array is used. src/shared/gatt-helpers.c:1323:31: warning: Variable length array is used. src/shared/gatt-helpers.c:1354:23: warning: Variable length array is used. src/shared/gatt-server.c:278:25: warning: Variable length array is used. src/shared/gatt-server.c:618:25: warning: Variable length array is used. src/shared/gatt-server.c:716:25: warning: Variable length array is used. src/shared/bap.c:288:25: warning: array of flexible structures src/shared/bap.c: note: in included file: ./src/shared/ascs.h:88:25: warning: array of flexible structures src/shared/shell.c: note: in included file (through /usr/include/readline/readline.h): /usr/include/readline/rltypedefs.h:35:23: warning: non-ANSI function declaration of function 'Function' /usr/include/readline/rltypedefs.h:36:25: warning: non-ANSI function declaration of function 'VFunction' /usr/include/readline/rltypedefs.h:37:27: warning: non-ANSI function declaration of function 'CPFunction' /usr/include/readline/rltypedefs.h:38:29: warning: non-ANSI function declaration of function 'CPPFunction' src/shared/crypto.c:271:21: warning: Variable length array is used. src/shared/crypto.c:272:23: warning: Variable length array is used. src/shared/gatt-helpers.c:768:31: warning: Variable length array is used. src/shared/gatt-helpers.c:830:31: warning: Variable length array is used. src/shared/gatt-helpers.c:1323:31: warning: Variable length array is used. src/shared/gatt-helpers.c:1354:23: warning: Variable length array is used. src/shared/gatt-server.c:278:25: warning: Variable length array is used. src/shared/gatt-server.c:618:25: warning: Variable length array is used. src/shared/gatt-server.c:716:25: warning: Variable length array is used. src/shared/bap.c:288:25: warning: array of flexible structures src/shared/bap.c: note: in included file: ./src/shared/ascs.h:88:25: warning: array of flexible structures src/shared/shell.c: note: in included file (through /usr/include/readline/readline.h): /usr/include/readline/rltypedefs.h:35:23: warning: non-ANSI function declaration of function 'Function' /usr/include/readline/rltypedefs.h:36:25: warning: non-ANSI function declaration of function 'VFunction' /usr/include/readline/rltypedefs.h:37:27: warning: non-ANSI function declaration of function 'CPFunction' /usr/include/readline/rltypedefs.h:38:29: warning: non-ANSI function declaration of function 'CPPFunction' tools/mesh-cfgtest.c:1453:17: warning: unknown escape sequence: '\%' tools/sco-tester.c: note: in included file: ./lib/bluetooth.h:219:15: warning: array of flexible structures ./lib/bluetooth.h:224:31: warning: array of flexible structures tools/bneptest.c:634:39: warning: unknown escape sequence: '\%' tools/seq2bseq.c:57:26: warning: Variable length array is used. tools/obex-client-tool.c: note: in included file (through /usr/include/readline/readline.h): /usr/include/readline/rltypedefs.h:35:23: warning: non-ANSI function declaration of function 'Function' /usr/include/readline/rltypedefs.h:36:25: warning: non-ANSI function declaration of function 'VFunction' /usr/include/readline/rltypedefs.h:37:27: warning: non-ANSI function declaration of function 'CPFunction' /usr/include/readline/rltypedefs.h:38:29: warning: non-ANSI function declaration of function 'CPPFunction' android/avctp.c:505:34: warning: Variable length array is used. android/avctp.c:556:34: warning: Variable length array is used. unit/test-avrcp.c:373:26: warning: Variable length array is used. unit/test-avrcp.c:398:26: warning: Variable length array is used. unit/test-avrcp.c:414:24: warning: Variable length array is used. android/avrcp-lib.c:1085:34: warning: Variable length array is used. android/avrcp-lib.c:1583:34: warning: Variable length array is used. android/avrcp-lib.c:1612:34: warning: Variable length array is used. android/avrcp-lib.c:1638:34: warning: Variable length array is used. unit/test-mesh-crypto.c:1090:35: error: macro "SEG_MAX" requires 3 arguments, but only 2 given unit/test-mesh-crypto.c:1100:35: error: macro "SEG_MAX" requires 3 arguments, but only 2 given unit/test-mesh-crypto.c: In function ‘check_encrypt’: unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^ In file included from ./mesh/crypto.c:21, from unit/test-mesh-crypto.c:20: ./mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function) 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^~~~~~~ unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1100 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 4); | ^ In file included from ./mesh/crypto.c:21, from unit/test-mesh-crypto.c:20: ./mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:4690: all] Error 2
tedd_an/bluezmakeextell fail Make External ELL FAIL: unit/test-mesh-crypto.c: In function ‘check_encrypt’: unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^ In file included from ./mesh/crypto.c:21, from unit/test-mesh-crypto.c:20: ./mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function) 1090 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 8); | ^~~~~~~ unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given 1100 | seg_max = SEG_MAX(keys->segmented, app_msg_len + 4); | ^ In file included from ./mesh/crypto.c:21, from unit/test-mesh-crypto.c:20: ./mesh/net.h:41: note: macro "SEG_MAX" defined here 41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \ | make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:4690: all] Error 2
tedd_an/IncrementalBuild fail [BlueZ,1/4] mesh: Implement lower transport layer for segmentation and reassembly tools/mgmt-tester.c: In function ‘main’: tools/mgmt-tester.c:12725:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without 12725 | int main(int argc, char *argv[]) | ^~~~ unit/test-avdtp.c: In function ‘main’: unit/test-avdtp.c:766:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without 766 | int main(int argc, char *argv[]) | ^~~~ unit/test-avrcp.c: In function ‘main’: unit/test-avrcp.c:989:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without 989 | int main(int argc, char *argv[]) | ^~~~ mesh/net.c: In function ‘seg_rxed’: mesh/net.c:2156:36: error: unused variable ‘largest’ [-Werror=unused-variable] 2156 | uint32_t expected, this_seg_flag, largest, seqAuth; | ^~~~~~~ mesh/net.c: In function ‘mesh_net_app_send’: mesh/net.c:3483:10: error: unused variable ‘seg’ [-Werror=unused-variable] 3483 | uint8_t seg, seg_max; | ^~~ mesh/net.c: In function ‘send_next_seg_to’: mesh/net.c:1838:24: error: ‘interval_ms’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 1838 | sar_tx->seg_timeout = l_timeout_create_ms(interval_ms, send_next_seg_to, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1839 | net, NULL); | ~~~~~~~~~~ cc1: all warnings being treated as errors make[1]: *** [Makefile:7872: mesh/net.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:4690: all] Error 2
tedd_an/ScanBuild fail Scan Build FAIL

Commit Message

Junho Lee Oct. 4, 2024, 7:31 a.m. UTC
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  | 667 +++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 495 insertions(+), 219 deletions(-)

Comments

bluez.test.bot@gmail.com Oct. 4, 2024, 8:57 a.m. UTC | #1
This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=895433

---Test result---

Test Summary:
CheckPatch                    FAIL      2.40 seconds
GitLint                       FAIL      1.29 seconds
BuildEll                      PASS      24.45 seconds
BluezMake                     FAIL      79.14 seconds
MakeCheck                     FAIL      2038.44 seconds
MakeDistcheck                 FAIL      120.84 seconds
CheckValgrind                 FAIL      59.10 seconds
CheckSmatch                   FAIL      157.81 seconds
bluezmakeextell               FAIL      64.91 seconds
IncrementalBuild              FAIL      1490.12 seconds
ScanBuild                     FAIL      748.18 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,1/4] mesh: Implement lower transport layer for segmentation and reassembly
ERROR:FUNCTION_WITHOUT_ARGS: Bad function definition - struct mesh_sar_tx *mesh_sar_tx_new() should probably be struct mesh_sar_tx *mesh_sar_tx_new(void)
#399: FILE: mesh/net.c:619:
+static struct mesh_sar_tx *mesh_sar_tx_new()

ERROR:FUNCTION_WITHOUT_ARGS: Bad function definition - struct mesh_sar_rx *mesh_sar_rx_new() should probably be struct mesh_sar_rx *mesh_sar_rx_new(void)
#421: FILE: mesh/net.c:641:
+static struct mesh_sar_rx *mesh_sar_rx_new()

WARNING:LONG_LINE_COMMENT: line length of 93 exceeds 80 columns
#902: FILE: mesh/net.c:2207:
+			 *	[acknowledgment delay increment * segment reception interval]

ERROR:SPACING: space required before the open parenthesis '('
#1003: FILE: mesh/net.c:2283:
+	if(IS_UNICAST(dst)) {

WARNING:LINE_SPACING: Missing a blank line after declarations
#1138: FILE: mesh/net.c:3565:
+		bool is_unicast = IS_UNICAST(dst);
+		sar_tx->ack_received = false;

/github/workspace/src/src/13821809.patch total: 3 errors, 2 warnings, 1011 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13821809.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,4/4] mesh: Add features of Segmented Control message
WARNING:BRACES: braces {} are not necessary for any arm of this statement
#317: FILE: mesh/net.c:2253:
+		if (ctl) {
[...]
+		} else {
[...]

WARNING:LINE_SPACING: Missing a blank line after declarations
#469: FILE: mesh/net.c:3482:
+		struct mesh_sar_tx *drop_sar_tx;
+		payload->flags = 0xffffffff >> (31 - segN);

WARNING:LINE_SPACING: Missing a blank line after declarations
#494: FILE: mesh/net.c:3507:
+		bool is_unicast = IS_UNICAST(payload->remote);
+		sar_tx->ack_received = false;

/github/workspace/src/src/13821812.patch total: 0 errors, 3 warnings, 584 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13821812.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,1/4] mesh: Implement lower transport layer for segmentation and reassembly

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
1: T1 Title exceeds max length (81>80): "[BlueZ,1/4] mesh: Implement lower transport layer for segmentation and reassembly"
##############################
Test: BluezMake - FAIL
Desc: Build BlueZ
Output:

tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:12725:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
12725 | int main(int argc, char *argv[])
      |     ^~~~
unit/test-mesh-crypto.c: In function ‘check_encrypt’:
unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function)
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |              ^~~~~~~
unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in
unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1100 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 4);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4690: all] Error 2
##############################
Test: MakeCheck - FAIL
Desc: Run Bluez Make Check
Output:

unit/test-avdtp.c: In function ‘main’:
unit/test-avdtp.c:766:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
  766 | int main(int argc, char *argv[])
      |     ^~~~
unit/test-avrcp.c: In function ‘main’:
unit/test-avrcp.c:989:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
  989 | int main(int argc, char *argv[])
      |     ^~~~
unit/test-mesh-crypto.c: In function ‘check_encrypt’:
unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function)
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |              ^~~~~~~
unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in
unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1100 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 4);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1
make: *** [Makefile:12355: check] Error 2
##############################
Test: MakeDistcheck - FAIL
Desc: Run Bluez Make Distcheck
Output:

Package cups was not found in the pkg-config search path.
Perhaps you should add the directory containing `cups.pc'
to the PKG_CONFIG_PATH environment variable
No package 'cups' found
../../unit/test-mesh-crypto.c: In function ‘check_encrypt’:
../../unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |                                                      ^
In file included from ../../mesh/crypto.c:21,
                 from ../../unit/test-mesh-crypto.c:20:
../../mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
../../unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function)
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |              ^~~~~~~
../../unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in
../../unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1100 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 4);
      |                                                      ^
In file included from ../../mesh/crypto.c:21,
                 from ../../unit/test-mesh-crypto.c:20:
../../mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
make[4]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [Makefile:11924: check-TESTS] Error 2
make[2]: *** [Makefile:12353: check-am] Error 2
make[1]: *** [Makefile:12355: check] Error 2
make: *** [Makefile:12276: distcheck] Error 1
##############################
Test: CheckValgrind - FAIL
Desc: Run Bluez Make Check with Valgrind
Output:

tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:12725:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
12725 | int main(int argc, char *argv[])
      |     ^~~~
unit/test-mesh-crypto.c: In function ‘check_encrypt’:
unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function)
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |              ^~~~~~~
unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in
unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1100 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 4);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:12355: check] Error 2
##############################
Test: CheckSmatch - FAIL
Desc: Run smatch tool with source
Output:

src/shared/crypto.c:271:21: warning: Variable length array is used.
src/shared/crypto.c:272:23: warning: Variable length array is used.
src/shared/gatt-helpers.c:768:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:830:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:1323:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:1354:23: warning: Variable length array is used.
src/shared/gatt-server.c:278:25: warning: Variable length array is used.
src/shared/gatt-server.c:618:25: warning: Variable length array is used.
src/shared/gatt-server.c:716:25: warning: Variable length array is used.
src/shared/bap.c:288:25: warning: array of flexible structures
src/shared/bap.c: note: in included file:
./src/shared/ascs.h:88:25: warning: array of flexible structures
src/shared/shell.c: note: in included file (through /usr/include/readline/readline.h):
/usr/include/readline/rltypedefs.h:35:23: warning: non-ANSI function declaration of function 'Function'
/usr/include/readline/rltypedefs.h:36:25: warning: non-ANSI function declaration of function 'VFunction'
/usr/include/readline/rltypedefs.h:37:27: warning: non-ANSI function declaration of function 'CPFunction'
/usr/include/readline/rltypedefs.h:38:29: warning: non-ANSI function declaration of function 'CPPFunction'
src/shared/crypto.c:271:21: warning: Variable length array is used.
src/shared/crypto.c:272:23: warning: Variable length array is used.
src/shared/gatt-helpers.c:768:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:830:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:1323:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:1354:23: warning: Variable length array is used.
src/shared/gatt-server.c:278:25: warning: Variable length array is used.
src/shared/gatt-server.c:618:25: warning: Variable length array is used.
src/shared/gatt-server.c:716:25: warning: Variable length array is used.
src/shared/bap.c:288:25: warning: array of flexible structures
src/shared/bap.c: note: in included file:
./src/shared/ascs.h:88:25: warning: array of flexible structures
src/shared/shell.c: note: in included file (through /usr/include/readline/readline.h):
/usr/include/readline/rltypedefs.h:35:23: warning: non-ANSI function declaration of function 'Function'
/usr/include/readline/rltypedefs.h:36:25: warning: non-ANSI function declaration of function 'VFunction'
/usr/include/readline/rltypedefs.h:37:27: warning: non-ANSI function declaration of function 'CPFunction'
/usr/include/readline/rltypedefs.h:38:29: warning: non-ANSI function declaration of function 'CPPFunction'
tools/mesh-cfgtest.c:1453:17: warning: unknown escape sequence: '\%'
tools/sco-tester.c: note: in included file:
./lib/bluetooth.h:219:15: warning: array of flexible structures
./lib/bluetooth.h:224:31: warning: array of flexible structures
tools/bneptest.c:634:39: warning: unknown escape sequence: '\%'
tools/seq2bseq.c:57:26: warning: Variable length array is used.
tools/obex-client-tool.c: note: in included file (through /usr/include/readline/readline.h):
/usr/include/readline/rltypedefs.h:35:23: warning: non-ANSI function declaration of function 'Function'
/usr/include/readline/rltypedefs.h:36:25: warning: non-ANSI function declaration of function 'VFunction'
/usr/include/readline/rltypedefs.h:37:27: warning: non-ANSI function declaration of function 'CPFunction'
/usr/include/readline/rltypedefs.h:38:29: warning: non-ANSI function declaration of function 'CPPFunction'
android/avctp.c:505:34: warning: Variable length array is used.
android/avctp.c:556:34: warning: Variable length array is used.
unit/test-avrcp.c:373:26: warning: Variable length array is used.
unit/test-avrcp.c:398:26: warning: Variable length array is used.
unit/test-avrcp.c:414:24: warning: Variable length array is used.
android/avrcp-lib.c:1085:34: warning: Variable length array is used.
android/avrcp-lib.c:1583:34: warning: Variable length array is used.
android/avrcp-lib.c:1612:34: warning: Variable length array is used.
android/avrcp-lib.c:1638:34: warning: Variable length array is used.
unit/test-mesh-crypto.c:1090:35: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
unit/test-mesh-crypto.c:1100:35: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
unit/test-mesh-crypto.c: In function ‘check_encrypt’:
unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function)
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |              ^~~~~~~
unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in
unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1100 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 4);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4690: all] Error 2
##############################
Test: bluezmakeextell - FAIL
Desc: Build Bluez with External ELL
Output:

unit/test-mesh-crypto.c: In function ‘check_encrypt’:
unit/test-mesh-crypto.c:1090:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
unit/test-mesh-crypto.c:1090:14: error: ‘SEG_MAX’ undeclared (first use in this function)
 1090 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 8);
      |              ^~~~~~~
unit/test-mesh-crypto.c:1090:14: note: each undeclared identifier is reported only once for each function it appears in
unit/test-mesh-crypto.c:1100:54: error: macro "SEG_MAX" requires 3 arguments, but only 2 given
 1100 |    seg_max = SEG_MAX(keys->segmented, app_msg_len + 4);
      |                                                      ^
In file included from ./mesh/crypto.c:21,
                 from unit/test-mesh-crypto.c:20:
./mesh/net.h:41: note: macro "SEG_MAX" defined here
   41 | #define SEG_MAX(ctl, seg, len) ((ctl) ? CTL_SEG_MAX((seg), (len)) : \
      | 
make[1]: *** [Makefile:11270: unit/test_mesh_crypto-test-mesh-crypto.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4690: all] Error 2
##############################
Test: IncrementalBuild - FAIL
Desc: Incremental build with the patches in the series
Output:
[BlueZ,1/4] mesh: Implement lower transport layer for segmentation and reassembly

tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:12725:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
12725 | int main(int argc, char *argv[])
      |     ^~~~
unit/test-avdtp.c: In function ‘main’:
unit/test-avdtp.c:766:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
  766 | int main(int argc, char *argv[])
      |     ^~~~
unit/test-avrcp.c: In function ‘main’:
unit/test-avrcp.c:989:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
  989 | int main(int argc, char *argv[])
      |     ^~~~
mesh/net.c: In function ‘seg_rxed’:
mesh/net.c:2156:36: error: unused variable ‘largest’ [-Werror=unused-variable]
 2156 |  uint32_t expected, this_seg_flag, largest, seqAuth;
      |                                    ^~~~~~~
mesh/net.c: In function ‘mesh_net_app_send’:
mesh/net.c:3483:10: error: unused variable ‘seg’ [-Werror=unused-variable]
 3483 |  uint8_t seg, seg_max;
      |          ^~~
mesh/net.c: In function ‘send_next_seg_to’:
mesh/net.c:1838:24: error: ‘interval_ms’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
 1838 |  sar_tx->seg_timeout = l_timeout_create_ms(interval_ms, send_next_seg_to,
      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1839 |         net, NULL);
      |         ~~~~~~~~~~      
cc1: all warnings being treated as errors
make[1]: *** [Makefile:7872: mesh/net.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4690: all] Error 2
##############################
Test: ScanBuild - FAIL
Desc: Run Scan Build
Output:

src/shared/gatt-client.c:451:21: warning: Use of memory after it is freed
        gatt_db_unregister(op->client->db, op->db_id);
                           ^~~~~~~~~~
src/shared/gatt-client.c:696:2: warning: Use of memory after it is freed
        discovery_op_complete(op, false, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:996:2: warning: Use of memory after it is freed
        discovery_op_complete(op, success, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1102:2: warning: Use of memory after it is freed
        discovery_op_complete(op, success, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1296:2: warning: Use of memory after it is freed
        discovery_op_complete(op, success, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1361:2: warning: Use of memory after it is freed
        discovery_op_complete(op, success, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1636:6: warning: Use of memory after it is freed
        if (read_db_hash(op)) {
            ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1641:2: warning: Use of memory after it is freed
        discover_all(op);
        ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:2145:6: warning: Use of memory after it is freed
        if (read_db_hash(op)) {
            ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:2153:8: warning: Use of memory after it is freed
                                                        discovery_op_ref(op),
                                                        ^~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3242:2: warning: Use of memory after it is freed
        complete_write_long_op(req, success, 0, false);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3264:2: warning: Use of memory after it is freed
        request_unref(req);
        ^~~~~~~~~~~~~~~~~~
12 warnings generated.
src/shared/gatt-client.c:451:21: warning: Use of memory after it is freed
        gatt_db_unregister(op->client->db, op->db_id);
                           ^~~~~~~~~~
src/shared/gatt-client.c:696:2: warning: Use of memory after it is freed
        discovery_op_complete(op, false, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:996:2: warning: Use of memory after it is freed
        discovery_op_complete(op, success, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1102:2: warning: Use of memory after it is freed
        discovery_op_complete(op, success, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1296:2: warning: Use of memory after it is freed
        discovery_op_complete(op, success, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1361:2: warning: Use of memory after it is freed
        discovery_op_complete(op, success, att_ecode);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1636:6: warning: Use of memory after it is freed
        if (read_db_hash(op)) {
            ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1641:2: warning: Use of memory after it is freed
        discover_all(op);
        ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:2145:6: warning: Use of memory after it is freed
        if (read_db_hash(op)) {
            ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:2153:8: warning: Use of memory after it is freed
                                                        discovery_op_ref(op),
                                                        ^~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3242:2: warning: Use of memory after it is freed
        complete_write_long_op(req, success, 0, false);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3264:2: warning: Use of memory after it is freed
        request_unref(req);
        ^~~~~~~~~~~~~~~~~~
12 warnings generated.
tools/hciattach.c:817:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
        if ((n = read_hci_event(fd, resp, 10)) < 0) {
             ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:865:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
        if ((n = read_hci_event(fd, resp, 4)) < 0) {
             ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:887:8: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
                if ((n = read_hci_event(fd, resp, 10)) < 0) {
                     ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:909:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
        if ((n = read_hci_event(fd, resp, 4)) < 0) {
             ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:930:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
        if ((n = read_hci_event(fd, resp, 4)) < 0) {
             ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:974:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
        if ((n = read_hci_event(fd, resp, 6)) < 0) {
             ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 warnings generated.
src/oui.c:50:2: warning: Value stored to 'hwdb' is never read
        hwdb = udev_hwdb_unref(hwdb);
        ^      ~~~~~~~~~~~~~~~~~~~~~
src/oui.c:53:2: warning: Value stored to 'udev' is never read
        udev = udev_unref(udev);
        ^      ~~~~~~~~~~~~~~~~
2 warnings generated.
tools/hcidump.c:180:9: warning: Potential leak of memory pointed to by 'dp'
                                if (fds[i].fd == sock)
                                    ^~~
tools/hcidump.c:248:17: warning: Assigned value is garbage or undefined
                                dh->ts_sec  = htobl(frm.ts.tv_sec);
                                            ^ ~~~~~~~~~~~~~~~~~~~~
tools/hcidump.c:326:9: warning: 1st function call argument is an uninitialized value
                                if (be32toh(dp.flags) & 0x02) {
                                    ^~~~~~~~~~~~~~~~~
/usr/include/endian.h:46:22: note: expanded from macro 'be32toh'
#  define be32toh(x) __bswap_32 (x)
                     ^~~~~~~~~~~~~~
tools/hcidump.c:341:20: warning: 1st function call argument is an uninitialized value
                                frm.data_len = be32toh(dp.len);
                                               ^~~~~~~~~~~~~~~
/usr/include/endian.h:46:22: note: expanded from macro 'be32toh'
#  define be32toh(x) __bswap_32 (x)
                     ^~~~~~~~~~~~~~
tools/hcidump.c:346:14: warning: 1st function call argument is an uninitialized value
                                opcode = be32toh(dp.flags) & 0xffff;
                                         ^~~~~~~~~~~~~~~~~
/usr/include/endian.h:46:22: note: expanded from macro 'be32toh'
#  define be32toh(x) __bswap_32 (x)
                     ^~~~~~~~~~~~~~
tools/hcidump.c:384:17: warning: Assigned value is garbage or undefined
                        frm.data_len = btohs(dh.len);
                                     ^ ~~~~~~~~~~~~~
tools/hcidump.c:394:11: warning: Assigned value is garbage or undefined
                frm.len = frm.data_len;
                        ^ ~~~~~~~~~~~~
tools/hcidump.c:398:9: warning: 1st function call argument is an uninitialized value
                        ts = be64toh(ph.ts);
                             ^~~~~~~~~~~~~~
/usr/include/endian.h:51:22: note: expanded from macro 'be64toh'
#  define be64toh(x) __bswap_64 (x)
                     ^~~~~~~~~~~~~~
tools/hcidump.c:403:13: warning: 1st function call argument is an uninitialized value
                        frm.in = be32toh(dp.flags) & 0x01;
                                 ^~~~~~~~~~~~~~~~~
/usr/include/endian.h:46:22: note: expanded from macro 'be32toh'
#  define be32toh(x) __bswap_32 (x)
                     ^~~~~~~~~~~~~~
tools/hcidump.c:408:11: warning: Assigned value is garbage or undefined
                        frm.in = dh.in;
                               ^ ~~~~~
tools/hcidump.c:437:7: warning: Null pointer passed to 1st parameter expecting 'nonnull'
        fd = open(file, open_flags, 0644);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 warnings generated.
tools/rfcomm.c:234:3: warning: Value stored to 'i' is never read
                i = execvp(cmdargv[0], cmdargv);
                ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/rfcomm.c:234:7: warning: Null pointer passed to 1st parameter expecting 'nonnull'
                i = execvp(cmdargv[0], cmdargv);
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/rfcomm.c:354:8: warning: Although the value stored to 'fd' is used in the enclosing expression, the value is never actually read from 'fd'
                if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
                     ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/rfcomm.c:497:14: warning: Assigned value is garbage or undefined
        req.channel = raddr.rc_channel;
                    ^ ~~~~~~~~~~~~~~~~
tools/rfcomm.c:515:8: warning: Although the value stored to 'fd' is used in the enclosing expression, the value is never actually read from 'fd'
                if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
                     ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 warnings generated.
src/sdp-xml.c:126:10: warning: Assigned value is garbage or undefined
                buf[1] = data[i + 1];
                       ^ ~~~~~~~~~~~
src/sdp-xml.c:300:11: warning: Assigned value is garbage or undefined
                        buf[1] = data[i + 1];
                               ^ ~~~~~~~~~~~
src/sdp-xml.c:338:11: warning: Assigned value is garbage or undefined
                        buf[1] = data[i + 1];
                               ^ ~~~~~~~~~~~
3 warnings generated.
tools/ciptool.c:350:7: warning: 5th function call argument is an uninitialized value
        sk = do_connect(ctl, dev_id, &src, &dst, psm, (1 << CMTP_LOOPBACK));
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
tools/sdptool.c:941:26: warning: Result of 'malloc' is converted to a pointer of type 'uint32_t', which is incompatible with sizeof operand type 'int'
                        uint32_t *value_int = malloc(sizeof(int));
                        ~~~~~~~~~~            ^~~~~~ ~~~~~~~~~~~
tools/sdptool.c:980:4: warning: 1st function call argument is an uninitialized value
                        free(allocArray[i]);
                        ^~~~~~~~~~~~~~~~~~~
tools/sdptool.c:3777:2: warning: Potential leak of memory pointed to by 'si.name'
        return add_service(0, &si);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~
tools/sdptool.c:4112:4: warning: Potential leak of memory pointed to by 'context.svc'
                        return -1;
                        ^~~~~~~~~
4 warnings generated.
tools/avtest.c:225:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 3);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:235:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 4);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:244:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 3);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:258:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf,
                                ^     ~~~~~~~~~~~~~~
tools/avtest.c:265:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf,
                                ^     ~~~~~~~~~~~~~~
tools/avtest.c:272:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf,
                                ^     ~~~~~~~~~~~~~~
tools/avtest.c:279:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf,
                                ^     ~~~~~~~~~~~~~~
tools/avtest.c:291:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 4);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:295:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 2);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:304:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 3);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:308:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 2);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:317:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 3);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:324:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 2);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:346:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 4);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:350:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 2);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:359:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 3);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:363:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 2);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:376:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 4);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:380:5: warning: Value stored to 'len' is never read
                                len = write(sk, buf, 2);
                                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:387:4: warning: Value stored to 'len' is never read
                        len = write(sk, buf, 2);
                        ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:397:4: warning: Value stored to 'len' is never read
                        len = write(sk, buf, 2);
                        ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:562:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 2);
                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:570:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, invalid ? 2 : 3);
                ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/avtest.c:584:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 4 + sizeof(media_transport));
                ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/avtest.c:597:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 3);
                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:607:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 3);
                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:619:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 3);
                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:634:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 3);
                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:646:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 3);
                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:655:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 3);
                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:662:3: warning: Value stored to 'len' is never read
                len = write(sk, buf, 2);
                ^     ~~~~~~~~~~~~~~~~~
tools/avtest.c:698:2: warning: Value stored to 'len' is never read
        len = write(sk, buf, AVCTP_HEADER_LENGTH + sizeof(play_pressed));
        ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32 warnings generated.
tools/btproxy.c:836:15: warning: Null pointer passed to 1st parameter expecting 'nonnull'
                        tcp_port = atoi(optarg);
                                   ^~~~~~~~~~~~
tools/btproxy.c:839:8: warning: Null pointer passed to 1st parameter expecting 'nonnull'
                        if (strlen(optarg) > 3 && !strncmp(optarg, "hci", 3))
                            ^~~~~~~~~~~~~~
2 warnings generated.
tools/create-image.c:76:3: warning: Value stored to 'fd' is never read
                fd = -1;
                ^    ~~
tools/create-image.c:84:3: warning: Value stored to 'fd' is never read
                fd = -1;
                ^    ~~
tools/create-image.c:92:3: warning: Value stored to 'fd' is never read
                fd = -1;
                ^    ~~
tools/create-image.c:105:2: warning: Value stored to 'fd' is never read
        fd = -1;
        ^    ~~
4 warnings generated.
tools/btgatt-client.c:1824:2: warning: Value stored to 'argv' is never read
        argv += optind;
        ^       ~~~~~~
1 warning generated.
tools/btgatt-server.c:1212:2: warning: Value stored to 'argv' is never read
        argv -= optind;
        ^       ~~~~~~
1 warning generated.
tools/check-selftest.c:42:3: warning: Value stored to 'ptr' is never read
                ptr = fgets(result, sizeof(result), fp);
                ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
tools/gatt-service.c:294:2: warning: 2nd function call argument is an uninitialized value
        chr_write(chr, value, len);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
tools/obex-server-tool.c:133:13: warning: Null pointer passed to 1st parameter expecting 'nonnull'
        data->fd = open(name, O_WRONLY | O_CREAT | O_NOCTTY, 0600);
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/obex-server-tool.c:192:13: warning: Null pointer passed to 1st parameter expecting 'nonnull'
        data->fd = open(name, O_RDONLY | O_NOCTTY, 0);
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 warnings generated.
tools/btpclientctl.c:402:3: warning: Value stored to 'bit' is never read
                bit = 0;
                ^     ~
tools/btpclientctl.c:1655:2: warning: Null pointer passed to 2nd parameter expecting 'nonnull'
        memcpy(cp->data, ad_data, ad_len);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 warnings generated.
src/sdpd-request.c:211:13: warning: Result of 'malloc' is converted to a pointer of type 'char', which is incompatible with sizeof operand type 'uint16_t'
                                pElem = malloc(sizeof(uint16_t));
                                        ^~~~~~ ~~~~~~~~~~~~~~~~
src/sdpd-request.c:239:13: warning: Result of 'malloc' is converted to a pointer of type 'char', which is incompatible with sizeof operand type 'uint32_t'
                                pElem = malloc(sizeof(uint32_t));
                                        ^~~~~~ ~~~~~~~~~~~~~~~~
2 warnings generated.
android/avrcp-lib.c:1968:3: warning: 1st function call argument is an uninitialized value
                g_free(text[i]);
                ^~~~~~~~~~~~~~~
1 warning generated.
profiles/health/hdp.c:644:3: warning: Use of memory after it is freed
                hdp_tmp_dc_data_unref(dc_data);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
profiles/health/hdp.c:800:19: warning: Use of memory after it is freed
                path = g_strdup(chan->path);
                                ^~~~~~~~~~
profiles/health/hdp.c:1779:6: warning: Use of memory after it is freed
                                        hdp_tmp_dc_data_ref(hdp_conn),
                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
profiles/health/hdp.c:1836:30: warning: Use of memory after it is freed
        reply = g_dbus_create_error(data->msg, ERROR_INTERFACE ".HealthError",
                                    ^~~~~~~~~
4 warnings generated.
profiles/health/hdp_util.c:1052:2: warning: Use of memory after it is freed
        conn_data->func(conn_data->data, gerr);
        ^~~~~~~~~~~~~~~
1 warning generated.
attrib/gatt.c:970:2: warning: Potential leak of memory pointed to by 'long_write'
        return prepare_write(long_write);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
src/sdpd-request.c:211:13: warning: Result of 'malloc' is converted to a pointer of type 'char', which is incompatible with sizeof operand type 'uint16_t'
                                pElem = malloc(sizeof(uint16_t));
                                        ^~~~~~ ~~~~~~~~~~~~~~~~
src/sdpd-request.c:239:13: warning: Result of 'malloc' is converted to a pointer of type 'char', which is incompatible with sizeof operand type 'uint32_t'
                                pElem = malloc(sizeof(uint32_t));
                                        ^~~~~~ ~~~~~~~~~~~~~~~~
2 warnings generated.
src/sdp-xml.c:126:10: warning: Assigned value is garbage or undefined
                buf[1] = data[i + 1];
                       ^ ~~~~~~~~~~~
src/sdp-xml.c:300:11: warning: Assigned value is garbage or undefined
                        buf[1] = data[i + 1];
                               ^ ~~~~~~~~~~~
src/sdp-xml.c:338:11: warning: Assigned value is garbage or undefined
                        buf[1] = data[i + 1];
                               ^ ~~~~~~~~~~~
3 warnings generated.
src/sdp-client.c:353:14: warning: Access to field 'cb' results in a dereference of a null pointer
        (*ctxt)->cb = cb;
        ~~~~~~~~~~~~^~~~
1 warning generated.
src/gatt-database.c:1156:10: warning: Value stored to 'bits' during its initialization is never read
        uint8_t bits[] = { BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING,
                ^~~~     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
gobex/gobex-header.c:95:2: warning: Null pointer passed to 2nd parameter expecting 'nonnull'
        memcpy(to, from, count);
        ^~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
gobex/gobex-transfer.c:423:7: warning: Use of memory after it is freed
        if (!g_slist_find(transfers, transfer))
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
mesh/net.c: In function ‘seg_rxed’:
mesh/net.c:2156:36: error: unused variable ‘largest’ [-Werror=unused-variable]
 2156 |  uint32_t expected, this_seg_flag, largest, seqAuth;
      |                                    ^~~~~~~
mesh/net.c: In function ‘mesh_net_app_send’:
mesh/net.c:3483:10: error: unused variable ‘seg’ [-Werror=unused-variable]
 3483 |  uint8_t seg, seg_max;
      |          ^~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:7872: mesh/net.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4690: all] Error 2


---
Regards,
Linux Bluetooth
Brian Gix Oct. 13, 2024, 7:27 p.m. UTC | #2
Hi Junho,

There are some check-patch failures on your patchset.

Can you fix these (and any others you find with check-patch) and resubmit?
The ones below are only from patch 1 of 4...  patch 3 applied cleanly, 
but 2 and 4 also could not be applied until patch 1 is fixed.

Thanks,
Brian

On 10/4/24 12:31 AM, Junho Lee wrote:
> -			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:
> +			 *	[acknowledgment delay increment * segment reception interval]
WARNING:LONG_LINE_COMMENT: line over 80 characters
#774: FILE: mesh/net.c:2207:
+             *    [acknowledgment delay increment * segment reception 
interval]


>   	/* 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)) {
ERROR:SPACING: space required before the open parenthesis '('
#875: FILE: mesh/net.c:2283:
+    if(IS_UNICAST(dst)) {

> +	 * 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;
WARNING:LINE_SPACING: Missing a blank line after declarations
#1010: FILE: mesh/net.c:3565:
+        bool is_unicast = IS_UNICAST(dst);
+        sar_tx->ack_received = false;
Junho Lee Oct. 14, 2024, 5:31 a.m. UTC | #3
Hi Brian,

On Sun, Oct 13, 2024 at 12:27:18PM -0700, Brian Gix wrote:
> Hi Junho,
> 
> There are some check-patch failures on your patchset.
> 
> Can you fix these (and any others you find with check-patch) and resubmit?
> The ones below are only from patch 1 of 4...  patch 3 applied cleanly, but 2
> and 4 also could not be applied until patch 1 is fixed.
> 
> Thanks,
> Brian
> 

Sure. I had already fixed that part, but I didn't resubmit it because I
was writing in some unit tests as Luiz advised.

I resubmitted it a while ago, so please check it. If I run into any patch
issues again, I'll fix it and resubmit.

> On 10/4/24 12:31 AM, Junho Lee wrote:
> > -			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:
> > +			 *	[acknowledgment delay increment * segment reception interval]
> WARNING:LONG_LINE_COMMENT: line over 80 characters
> #774: FILE: mesh/net.c:2207:
> +             *    [acknowledgment delay increment * segment reception
> interval]
> 
> 
> >   	/* 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)) {
> ERROR:SPACING: space required before the open parenthesis '('
> #875: FILE: mesh/net.c:2283:
> +    if(IS_UNICAST(dst)) {
> 
> > +	 * 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;
> WARNING:LINE_SPACING: Missing a blank line after declarations
> #1010: FILE: mesh/net.c:3565:
> +        bool is_unicast = IS_UNICAST(dst);
> +        sar_tx->ack_received = false;
> 
>
diff mbox series

Patch

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..41e415b65 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()
+{
+	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()
+{
+	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;
 
-	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;
 
 	/*
 	 * 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:
+			 *	[acknowledgment delay increment * segment 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;
 }
 
@@ -3311,47 +3536,51 @@  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;
 }