Skip to content

Gateway Server computes incorrect concentrator_timestamp for Class C downlink, causing TOO_EARLY TxAck #7889

@zyuupup0907-bot

Description

@zyuupup0907-bot

Summary

When scheduling a Class C downlink via UDP Packet Forwarder, the Gateway Server occasionally computes a concentrator_timestamp that jumps far into the future, resulting in a TOO_EARLY TxAcknowledgment from the gateway.

Environment

  • Version: ttn-lw-gateway-server 3.35.2-SNAPSHOT-58357ea7da
  • Protocol: UDP (Semtech UDP Packet Forwarder)
  • Frequency Plan: EU_863_870_TTN
  • Device Class: Class C

What happened

While sending multicast downlinks to a Class C device, the concentrator_timestamp in the scheduled downlink message suddenly jumped from a normal value to an abnormally large one, and the gateway responded with TOO_EARLY.

Normal downlink (immediately before the problematic one)

"scheduled": {
  "frequency": "869525000",
  "timestamp": 2358424571,
  "concentrator_timestamp": "2358424571544"
}

TxAck result: success

Problematic downlink (next one, ~3 seconds later)

"scheduled": {
  "frequency": "869525000",
  "timestamp": 1297309563,
  "concentrator_timestamp": "5592276859385"
}

TxAck result: TOO_EARLY

Observed pattern

All previous downlinks had concentrator_timestamp values incrementing by ~3 seconds (consistent with the downlink interval):

2289389020638
2292412083309
2295423923511
2298431708900
2301387336930
2304395826750
2307411974818
2310416532287
2313438416167
2316424247158
2319463594163
2322476410236
2325503037508
2328417827289
2331408244003
2334461982748
2337467716776
2343072132934
2344621501038
2346401874715
2349443675934
2352470826616
2355487505503
2358424571544  ← last normal
5592276859385  ← sudden jump (~54 minutes into the future)

The jump from 2358424571544 to 5592276859385 is a delta of ~3233 seconds (~54 minutes), completely inconsistent with the expected ~3 second interval.

Analysis

The 32-bit timestamp field dropped from 2358424571 to 1297309563. The Gateway Server computed a future send time that crossed the 32-bit microsecond counter boundary (2^32 = 4294967296), and when converting to the 64-bit concentrator_timestamp, it accounted for a rollover:

1297309563 + 4294967296 ≈ 5592276859 → matches the concentrator_timestamp prefix of 5592276859385

The schedule attempt shows this was a Class C downlink:

"request": {
  "class": "CLASS_C",
  "rx2_data_rate": { "lora": { "bandwidth": 125000, "spreading_factor": 12, "coding_rate": "4/5" } },
  "rx2_frequency": "869525000",
  "priority": "NORMAL",
  "frequency_plan_id": "EU_863_870_TTN"
}

For Class C downlinks, the Gateway Server computes the send timestamp itself (unlike Class A where it's derived from the uplink RX window). It appears the GS used a stale or incorrect concentrator clock reference when calculating the 32-bit timestamp for this downlink, producing a value (1297309563) far in the past relative to the current concentrator counter (~2.36 billion). The rollover detection then interpreted this as a future time, resulting in the abnormally large concentrator_timestamp.

Expected behavior

The concentrator_timestamp should have been approximately 2361424571544 (previous value + ~3 seconds), and the downlink should have been transmitted successfully.

Steps to reproduce

  1. Set up a gateway connected via UDP Packet Forwarder
  2. Schedule Class C downlinks at a regular interval (~3 seconds)
  3. Continue for an extended period (the gateway had been connected for ~20 minutes before the issue occurred)
  4. Observe that eventually a downlink gets an incorrect concentrator_timestamp and fails with TOO_EARLY

Additional context

  • The gateway had been connected since 2026-04-09T11:25:09Z, and the issue occurred at 2026-04-09T11:45:20Z (~20 minutes after connection).
  • The gateway's uplink timestamp values at the time were in the ~2.3-2.4 billion range, which is past the halfway point of the 32-bit counter.
  • Round trip times were stable (median ~132ms), so network instability is unlikely to be the cause.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs/triageWe still need to triage this

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions