Repository navigation
Ignore uplink tokens from previous gateway connections - #8080
Merged
Merged
Conversation
A downlink scheduled right after a gateway reconnected could carry the uplink token of an uplink message received on the previous connection. As the new scheduler had no clock sync yet, the token synchronized its clock to the previous concentrator time base, which may have changed in between, for example because the gateway restarted. The emission was recorded in that time base, and once the first uplink moved the clock to the new time base, it blocked its sub-band for up to days. Ignore uplink tokens of uplink messages received before the scheduler was created, for all frontends, and log uplink token clock syncs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Log the raw xtime, session ID and concentrator time of incoming LoRa Basics Station messages and of outgoing downlink messages at debug level, to diagnose concentrator time jumps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues were identified for the change to reject uplink tokens predating scheduler creation.
No open issues 🎉
What changed in this PR
This PR prevents Gateway Server schedulers from using uplink tokens from previous connections to restore an outdated concentrator clock, avoiding prolonged sub band is blocked errors after reconnects.
Changes:
- Reject uplink tokens received before scheduler creation across all frontends.
- Update clock-sync tests and add coverage for rejecting pre-connection tokens.
- Add diagnostic clock logging and document the reconnect fix.
| File | Description |
|---|---|
pkg/gatewayserver/scheduling/scheduler.go |
Track scheduler creation time, reject older tokens, and log token-based clock synchronization. |
pkg/gatewayserver/scheduling/scheduler_test.go |
Adjust token timing and test rejection of older tokens. |
pkg/gatewayserver/io/semtechws/lbslns/upstream.go |
Log incoming Basics Station clock and session values. |
pkg/gatewayserver/io/semtechws/lbslns/downstream.go |
Log computed downlink xtime and associated clock values. |
CHANGELOG.md |
Document the fix for prolonged scheduling failures after reconnects. |
Review effort: Balanced
7 tasks done
johanstokking
approved these changes
Oct 31, 2026
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
References: https://github.com/TheThingsIndustries/lorawan-stack-support/issues/1517
Carved out of #8079, as requested in #8079 (comment).
A reconnect creates a new scheduler without clock sync. A downlink scheduled right after the reconnect, for example a class C downlink, could carry the uplink token of an uplink message received on the previous connection. The token then synchronized the new clock to the previous concentrator time base, which may have changed in between, for example because the gateway restarted, and the emission was recorded in that time base. Once the first uplink on the new connection moved the clock to the new time base, that emission appeared far in the future and blocked its sub-band with
sub band is blockedfor up to days (~94 h in the support case).Changes
xtime, session ID and concentrator time of incoming LoRa Basics Station messages (join-requests, uplinks, TX confirmations) and of thextimeof outgoing downlinks, to collect data on concentrator time jumps.Testing
Steps
go test ./pkg/gatewayserver/...TestScheduleSyncViaUplinkTokennow creates the scheduler before the uplink for the cases that sync via uplink token, and has a new case for an uplink token from before the scheduler was created, which is ignored.Results
All tests in
pkg/gatewayserver/...pass.Regressions
no_clock_syncinstead of using the old time base. This also applies to frontends whose time base did not change, such as a Semtech UDP Packet Forwarder gateway that reconnected without restarting. Class A downlinks are unaffected, as the uplink they answer synchronizes the clock on the new connection.Notes for Reviewers
The new logs should tell whether that gateway rolls over at 32 bits or starts a new
xtimesession.Checklist
README.mdfor the chosen target branch.CHANGELOG.md.CONTRIBUTING.md, there are no fixup commits left.🤖 Generated with Claude Code