fix(lorawan): NbTrans retransmissions skipped after LinkADRReq nb_trans change#15546
Open
hallard wants to merge 1 commit intoARMmbed:masterfrom
Open
fix(lorawan): NbTrans retransmissions skipped after LinkADRReq nb_trans change#15546hallard wants to merge 1 commit intoARMmbed:masterfrom
hallard wants to merge 1 commit intoARMmbed:masterfrom
Conversation
…ns change The prev_QOS_level == QOS_level guard in post_process_tx_no_reception() caused the first unconfirmed uplink after a LinkADRReq changed nb_trans to be sent only once, violating LoRaWAN spec 4.3.1.1 which requires the new NbTrans to apply immediately to all subsequent frames. Root cause: get_QOS_level() has a state-updating side-effect that writes _prev_qos_level = nb_trans each time it is called. If a downlink was received during the frame that acknowledged the LinkADRReq, post_process_tx_no_reception was never entered, so _prev_qos_level was never updated. On the next data frame the condition prev_QOS_level != QOS_level therefore evaluated to false, skipping all NbTrans retransmissions and incrementing FCnt after a single TX. Fix: Remove the prev_QOS_level == QOS_level guard. The _qos_cnt counter (reset to 1 per frame in handle_tx) already correctly bounds retransmissions for every frame regardless of nb_trans transitions. Also reset ul_nb_rep_counter at the start of each new frame send (LoRaMac::send) so that nb_retries in the TX confirmation metadata reflects only the current frame, not a cumulative count across all previous frames (the original code never reset this counter between sends, so the commented-out assert at on_radio_tx_done would have fired on the second application message). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Summary
Fixes a LoRaWAN spec 4.3.1.1 compliance failure where the first unconfirmed uplink after a
LinkADRReqchangesnb_transis sent only once instead ofnb_transtimes, and FCnt is incremented after that single TX.Root cause
get_QOS_level()has a state-updating side-effect: it writes_prev_qos_level = nb_transeach time it is called.get_QOS_level()is only called frompost_process_tx_no_reception(), which is only entered when no downlink is received.Typical scenario when NS sends a
LinkADRReq:LinkADRReqis received →process_reception()handles it →post_process_tx_no_reception()is never called →_prev_qos_levelstays at its old value.nb_transis now updated to the new value.post_process_tx_no_reception():prev_QOS_level == QOS_level→ retransmits correctly.Fix
LoRaWANStack.cpp: Remove theprev_QOS_level == QOS_levelguard. The_qos_cntcounter — reset to1inhandle_tx()for every new application frame — already correctly bounds the number of retransmissions regardless ofnb_transtransitions.LoRaMac.cpp: Resetul_nb_rep_counterto0at the start of each new frame send (LoRaMac::send). Without this reset, the counter accumulates across all frames (it is only reset on join/disconnect), sonb_retriesin the TX confirmation grows unboundedly and the commented-outMBED_ASSERT(ul_nb_rep_counter <= nb_trans)inon_radio_tx_donewould fire on the second application message.Test plan
nb_trans= 1 (default): device sends 1 TX per frame, FCnt increments correctly.nb_trans= 3 viaLinkADRReqin a downlink: verify the first data frame after the change is sent 3 times with the same FCnt, then FCnt increments.nb_retriesin the TX confirmation equals the number of physical TXs for that frame only.🤖 Generated with Claude Code