Skip to main content Link Menu Expand (external link) Document Search Copy Copied

2. GSK feature overview

A GSK is a symmetric session key an Endpoint and a Gateway share on a sub-GHz link, established after the Endpoint is registered and network-synchronized.

The stack owns the lifecycle: it establishes the session, keeps it in non-volatile memory, waits for an idle window because activating a GSK interrupts the SubG-CSS link, and stops using the key on any failure or expiry (§2.2).

You control three things: how quiet the link must be first, how many consecutive unacknowledged ack-requested uplinks mean the session is unusable, and how long the Endpoint waits before retrying after a fallback (§3).

SubG-CSS (LoRa). A session runs only on the medium data rate (MDR), so activating one moves the link from the region’s low data rate (LDR) mode to MDR, changing it in three ways. An application may also select MDR itself at initialization, with sid_sub_ghz_links_config.link3_data_rate = SID_LINK3_DATA_RATE_MDR; it then gets the data-rate and RX-window-separation gains below without a session.

  • About 6× the nominal uplink data rate, and roughly 5× less airtime for the same payload. Budget airtime from the Amazon Sidewalk Specification, downlink included. The maximum application payload does not change: sid_get_mtu() returns the same fixed value per link type, whatever the data rate and whether or not a session is active. A faster PHY is not a larger traffic allowance: the network’s traffic limits are unchanged.
  • Link-layer acknowledgement and up to 3 link-layer retries per message. No public API exposes either: a live session turns them on, and without one the link runs with both off on either data rate. The retries are MAC retransmissions of one message: worst case 4 transmissions of the same message, not 4 messages.
  • The 500 ms and 1000 ms asynchronous RX-window separations become legal on Profile A/B (Table 2.1). Profile B holds rx_window_count at SID_RX_WINDOW_CNT_INFINITE, so windows keep opening at the separation and the worst-case wait for a downlink is about one separation. 500 ms is a tenth of the LDR worst case. On SID_LINK3_PROFILE_A the Endpoint opens rx_window_count windows after an application uplink, so the separation sets the span of that burst rather than the number of windows in it: 500 ms brings the first window forward but closes the downlink opportunity ten times sooner than 5000 ms. Raise rx_window_count (SID_RX_WINDOW_CNT_PROFILE_A_MAX is 60) to hold the opportunity open; the separation buys nothing at rx_window_count = SID_RX_WINDOW_CNT_ZERO — the same numeric 0 that Profile B reads as SID_RX_WINDOW_CNT_INFINITE. SID_LINK3_PROFILE_C listens continuously at either data rate and gets no latency benefit.

To run a 500 ms or 1000 ms downlink separation, set sid_device_profile.unicast_params.l3_mdr_rx_window_interval_ms with SID_OPTION_900MHZ_SET_DEVICE_PROFILE (§4). It applies while the link runs MDR; at LDR the window is fixed, so this field is the only separation you choose:

LoRa profile LDR window Accepted l3_mdr_rx_window_interval_ms
SID_LINK3_PROFILE_A, SID_LINK3_PROFILE_B SID_LINK3_RX_WINDOW_SEPARATION_3 (5000 ms), fixed 0 (no MDR preference), SID_LINK3_RX_WINDOW_SEPARATION_5 (500 ms), SID_LINK3_RX_WINDOW_SEPARATION_2 (1000 ms) or SID_LINK3_RX_WINDOW_SEPARATION_3 (5000 ms)
SID_LINK3_PROFILE_C continuous accepted, but has no effect

Table 2.1: RX-window separation by profile and data rate.

The call needs a registered device and an initialized LoRa link. With SubG-CSS in link_mask but no SubG-FSK, sid_init() initializes the link, so you may set the field before sid_start(); with both sub-GHz links the stack initializes LoRa only when it alternates onto it, so set it once SID_LINK_TYPE_3 appears in link_status_mask (§2.3). Before that, and on a started link that is not yet synchronized, the call returns SID_ERROR_INVALID_STATE (-40). Set it once: the stack re-applies the stored value on every entry to MDR, including at boot (§4), so no teardown loses it. Leave the field 0 to keep whatever the link is already using. Any other value returns SID_ERROR_INCOMPATIBLE_PARAMS (-12). You may set the field before the link has ever reached MDR, and a change made while already there applies without waiting for the next switch.

MDR costs range, and receive time at 500 ms. No range figure in metres is published for either data rate: derive the LDR-versus-MDR link-budget delta from the per-region modulation and data-rate figures in the Amazon Sidewalk Specification and your radio’s sensitivity numbers. Size the RF budget at MDR; a device that closes the link there also closes it on the region’s more sensitive LDR. On Profile B, 500 ms also opens ten times as many receive windows as 5000 ms; on Profile A the count is rx_window_count either way and only the span changes. Each is cheaper at MDR, but the product is more receive time, so measure it on a battery product (Amazon Sidewalk Power Optimization Developer Guide).

Any teardown withdraws MDR and returns the link to LDR, where the live window is 5000 ms again until the link next reaches MDR. An application that selected MDR keeps both the data rate and the window. A region that does not offer MDR fails every establishment attempt: the link stays on LDR and the Endpoint re-attempts each retry_interval_sec (§7), so settle MDR availability on the bench, not in a specification.

MDR is not available in the EU region. The gate is in the SDK, not a per-fleet network decision: with the regulatory region set to the EU — or not yet established when the LoRa link initializes — the LoRa link runs LDR whatever sid_sub_ghz_links_config.link3_data_rate asks for, so an EU LoRa link never establishes a GSK session. LDR is not one waveform across regions: the EU variant is a narrower-band, lower-data-rate configuration with an asymmetric uplink and downlink. Size EU link budget and airtime against that variant, from the regional parameters in the Amazon Sidewalk Specification, never against the LDR-versus-MDR comparison above.

The application owns the regulatory region: your porting layer supplies it through struct sid_device_info_callbacks.get_info with SID_DEVICE_INFO_TYPE_REGION (4) and an enum sid_device_region value.

The move to MDR happens before any session exists. A device at the edge of MDR coverage therefore runs ordinary traffic on the weaker link, unacknowledged, until session material arrives or the attempt gives up, up to a couple of minutes later. If it gives up, and the application did not select MDR (above), the link returns to LDR on its own, with no reboot needed. Size MDR coverage for the fringe of your deployment, not its centre.

SubG-FSK. A session moves uplink authentication into the Gateway on both SID_LINK2_PROFILE_1 and SID_LINK2_PROFILE_2. A session is bound to the Gateway that established it: a Gateway the Endpoint holds no session for uses the non-GSK path until a fresh establishment, while reconnecting to a Gateway it already holds one for resumes that session with no fresh establishment. GSK therefore suits a stationary Endpoint that holds one Gateway. A mobile product pays the most: each Gateway it holds no session for costs an idle window and an establishment (§2.2). Consent still governs forwarding, as in non-GSK mode.

The steady state your application sees on SubG-FSK is otherwise unchanged: the same PHY, maximum payload, throughput and range, no new API, no GSK-specific branch, and nothing to configure beyond the three fields in §3. The one exception: on SID_LINK2_PROFILE_2 with a session active, an in-place synchronous RX-window interval change no longer takes the link out of network synchronization, so your application sees no bounce.

2.2 Session lifecycle

flowchart TD
    N["Non-GSK mode"]
    R["Establishment requested"]
    P["Establishment in progress"]
    A["Session active, SID_STATE_READY"]
    N -->|"registered, link network-synced, network enabled GSK for this PHY"| R
    R -->|"link quiet both ways for idle_timeout_sec"| P
    R -.->|"link busy resets the quiet window"| R
    P -->|"establishment succeeds"| A
    P -->|"establishment fails"| N
    A -->|"expiry, missed acks, or PHY cannot carry GSK"| N
    N -.->|"reboot in coverage with a stored session, no link bounce"| A

Figure 2.1: GSK session establishment. The application cannot read these states; the only visible effects are the status changes described below. Network synchronization means joined, not merely connected; the enabled PHY is SubG-FSK or the SubG-CSS MDR data rate. Only SubG-CSS bounces: it moves the PHY to MDR, so the link leaves link_status_mask and returns (not if the application already selected MDR, §2.1); on SubG-FSK a successful establishment changes nothing in the reported status.

The idle window. Establishment is requested when a GSK-capable link connects and when it reaches network synchronization, but starts only once the link has been quiet for idle_timeout_sec. The window counts sub-GHz message traffic in both directions, not raw radio activity: an application uplink or downlink restarts it, as do the keep-alive and its acknowledgement and any join, registration or time-synchronization exchange; FSK beacon and synchronization reception, link-layer acknowledgements and MAC retransmissions do not. The keep-alive interval is therefore a hard ceiling on a usable idle_timeout_sec (§4). One exception: when a join or time-synchronization exchange fails under the key, the re-request starts immediately, mid-traffic. A successful one restarts the quiet window like any other traffic.

Reboot. A stored session survives a reboot: in coverage it costs no link bounce. Out of coverage the session is discarded and re-established when coverage returns, which costs one bounce on SubG-CSS and none on SubG-FSK (§7).

When a session ends. A session ends when its lifetime expires, a run of ack-requested uplinks goes unacknowledged, an establishment fails, the link moves to a PHY that cannot carry GSK, or the Gateway serving the Endpoint stops using the session. Whatever ends it, the ending is the same: the Endpoint stops using the key and continues in non-GSK mode; on SubG-CSS the link bounces on the way, unless the application selected MDR (§2.1), while on SubG-FSK nothing changes in the reported status. Connectivity never depends on a session — a link in non-GSK mode carries your traffic as it always did.

The desync fallback is the one ending you configure. The stack counts consecutive ack-requested uplinks it transmitted on a link in GSK mode whose end-to-end acknowledgement never arrived; at app_ack_miss_threshold it discards the key. Any ack-requested uplink feeds the counter, not only yours — Table 6.1 lists the sources (§6). The keep-alive is independent of GSK: it counts its own consecutive missed acknowledgements against its own default of 3, and tears down and rejoins the link on that count alone, whether or not GSK is enabled, active, or even compiled in (§6). A GSK-authenticated downlink resets the count; a downlink the Endpoint accepts on the network key alone does not.

Counted uplinks are lost. Each exhausted either its own num_retries or its ttl_in_seconds and was released, and none is retransmitted after the fallback. Your own messages among them normally surface through on_send_error with SID_ERROR_TIMEOUT (-2), but do not expect that callback to account for every counted uplink — the stack’s own ack-requested uplinks are counted too (above). A message that never reached the air — -38 or -40 — is not counted, and a re-send is a new message that can be counted again.

Recovery is not immediate (§3, §7). A factory reset discards all GSK state and notifies on_factory_reset; after re-registration expect one establishment and one link bounce.

Not supported: the application cannot force an establishment, discard a session, read the session state or the remaining lifetime, choose the lifetime, or choose which links carry a session (§7).

Only one sub-GHz link is on air at a time. The stack de-initializes one to start the other, so SubG-FSK and SubG-CSS are never network-synchronized at once, and establishment runs on whichever is active. Bluetooth LE runs independently and never carries a session. The Amazon Sidewalk Multi-link Application Note covers the alternation and SID_OPTION_SET_LINK_POLICY_MULTI_LINK_POLICY (9).

  • A session belongs to the device, not to a link, and is used on whichever GSK-enabled sub-GHz link is active. A link whose PHY the network has not enabled runs in non-GSK mode, so one sub-GHz link in GSK mode and the other in non-GSK mode as the links alternate is normal.
  • The tunables are single device-wide values, and a switch between sub-GHz links does not postpone the fallback. Size idle_timeout_sec against the smallest keep-alive interval of any enabled sub-GHz link, and read detection latency for your slowest link (§6).
  • Teardown is device-wide, even though only SubG-CSS shows it: there you see the link’s bit clear and set again in link_status_mask (§2.2). Do not design a failover state machine that treats either link as unaffected.

Back to top

©2023 Amazon.com, Inc. or its affiliates (collectively, “Amazon”). All Rights Reserved.