Conversation
…ine detection mesh_construct_packet wrote vendor_id via struct field assignment, leaving the alignment padding byte (MeshPkt offset 21) as zero. parse_ble_packet_op_params reads through the flat val[] overlay, so vendor_id_lo landed in the padding slot as 0x00, causing every mesh command to be silently discarded. Fix: write op/vendor_id/params through att_cmd_mut().value.val[] directly. A prior fix changed MeshPkt.vendor_id from u16 to [u8;2] to eliminate the padding, which shifted internal_par2 from offset 40 to 39 and shrunk the broadcast AES payload from 0x1c to 0x1b bytes. Old firmware always uses 0x1c, so cross-firmware broadcast decryption broke. Fix: revert vendor_id to u16. mesh_node_flush_status computed elapsed time as a u32 subtraction of two values that are semantically u16 (system tick >> 16). After the 16-bit counter wraps (~134 s at 32 MHz) the subtraction underflows to ~4.3e9, exceeding the 1464-tick timeout threshold and simultaneously falsely expiring every node. Fix: wrapping_sub as u16, then widen to u32. LLVM emits (a-b)&0xFFFF; verified in the tc32 assembly output of a clean firmware build. mesh_node_update_status accepted sn_difference==0 and refreshed the node tick. Neighbours re-broadcast a powered-off node's last state indefinitely with its frozen sn, so the coordinator's timeout clock was permanently reset and offline notifications never fired. Fix: require sn_difference>0 to accept any update. Live nodes call mesh_node_keep_alive before each advertisement, guaranteeing a monotonically advancing sn; dead nodes produce only stale relays with a fixed sn.
📊 Coverage Report
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…ine detection
mesh_construct_packet wrote vendor_id via struct field assignment, leaving the alignment padding byte (MeshPkt offset 21) as zero. parse_ble_packet_op_params reads through the flat val[] overlay, so vendor_id_lo landed in the padding slot as 0x00, causing every mesh command to be silently discarded. Fix: write op/vendor_id/params through att_cmd_mut().value.val[] directly.
A prior fix changed MeshPkt.vendor_id from u16 to [u8;2] to eliminate the padding, which shifted internal_par2 from offset 40 to 39 and shrunk the broadcast AES payload from 0x1c to 0x1b bytes. Old firmware always uses 0x1c, so cross-firmware broadcast decryption broke. Fix: revert vendor_id to u16.
mesh_node_flush_status computed elapsed time as a u32 subtraction of two values that are semantically u16 (system tick >> 16). After the 16-bit counter wraps (~134 s at 32 MHz) the subtraction underflows to ~4.3e9, exceeding the 1464-tick timeout threshold and simultaneously falsely expiring every node. Fix: wrapping_sub as u16, then widen to u32. LLVM emits (a-b)&0xFFFF; verified in the tc32 assembly output of a clean firmware build.
mesh_node_update_status accepted sn_difference==0 and refreshed the node tick. Neighbours re-broadcast a powered-off node's last state indefinitely with its frozen sn, so the coordinator's timeout clock was permanently reset and offline notifications never fired. Fix: require sn_difference>0 to accept any update. Live nodes call mesh_node_keep_alive before each advertisement, guaranteeing a monotonically advancing sn; dead nodes produce only stale relays with a fixed sn.