Skip to content

Ignore uplink tokens from previous gateway connections - #8080

Merged
halimi merged 2 commits into
v3.37from
fix/gs-prior-uplink-tokens
Nov 2, 2026
Merged

halimi merged 2 commits into
v3.37from
fix/gs-prior-uplink-tokens

Conversation

@halimi

@halimi halimi commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

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 blocked for up to days (~94 h in the support case).

Changes

  • The scheduler ignores uplink tokens of uplink messages received before it was created, for all frontends. Debug logs show when an uplink token is ignored and when it synchronizes the clock.
  • Debug logging of the raw xtime, session ID and concentrator time of incoming LoRa Basics Station messages (join-requests, uplinks, TX confirmations) and of the xtime of outgoing downlinks, to collect data on concentrator time jumps.

Testing

Steps
  • go test ./pkg/gatewayserver/...
  • TestScheduleSyncViaUplinkToken now 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
  • If a gateway has not sent an uplink yet since it reconnected, a downlink with an uplink token from before the reconnect now fails with no_clock_sync instead 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 xtime session.

Checklist

  • Scope: The referenced issue is addressed, there are no unrelated changes.
  • Compatibility: The changes are backwards compatible with existing API, storage, configuration and CLI, according to the compatibility commitments in README.md for the chosen target branch.
  • Documentation: Relevant documentation is added or updated.
  • Testing: The steps/process to test this feature are clearly explained including testing for regressions.
  • Infrastructure: If infrastructural changes (e.g., new RPC, configuration) are needed, a separate issue is created in the infrastructural repositories.
  • Changelog: Significant features, behavior changes, deprecations and fixes are added to CHANGELOG.md.
  • Commits: Commit messages follow guidelines in CONTRIBUTING.md, there are no fixup commits left.

🤖 Generated with Claude Code

halimi and others added 2 commits October 30, 2026 19:12
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>
@halimi
halimi requested a review from a team as a code owner October 30, 2026 18:12
@halimi
halimi requested a review from vlasebian October 30, 2026 18:12
@github-actions github-actions Bot added the c/gateway server This is related to the Gateway Server label Oct 30, 2026
@halimi
halimi requested a balanced review from Copilot October 30, 2026 18:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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

@halimi
halimi merged commit 629a1ed into v3.37 Nov 2, 2026
14 checks passed
@halimi
halimi deleted the fix/gs-prior-uplink-tokens branch November 2, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c/gateway server This is related to the Gateway Server

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants