Skip to content

feat(server): add bandwidth-measure generation counter - #1963

Merged
Marc-André Moreau (mamoreau-devolutions) merged 3 commits into
Devolutions:masterfrom
lamco-admin:feat/bandwidth-measure-generation-counter
Sep 28, 2026
Merged

Marc-André Moreau (mamoreau-devolutions) merged 3 commits into
Devolutions:masterfrom
lamco-admin:feat/bandwidth-measure-generation-counter

Conversation

@glamberson

@glamberson Greg Lamberson (glamberson) commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • autodetect_bandwidth_handle() (feat(server): expose measured bandwidth to the embedder #1734) exposes the latest Bandwidth
    Measure figure, but a consumer doing its own smoothing/filtering on
    top of it (e.g. rejecting noisy low samples unless real demand
    existed) needs to know when a new measurement window has closed,
    not just what the figure currently reads. The figure itself is a bad
    freshness signal: a quiet link reads the same low value for several
    consecutive windows in a row, so diffing it cannot tell "fresh
    window, same result" apart from "stale, no new window yet".
  • Adds autodetect_bandwidth_generation, mirroring
    autodetect_bandwidth's exact shape: an Arc<AtomicU32> field,
    autodetect_bandwidth_generation_handle() accessor, and
    with_autodetect_bandwidth_generation_handle() builder method. It
    increments on every completed Bandwidth Measure transaction,
    successful or not: a completed-but-unusable window still needs to
    advance the generation so a consumer's own stale-demand bookkeeping
    gets cleared instead of carrying over into the next window. The
    server increments it with Release after storing the figure, so a
    consumer that loads it with Acquire reads a bandwidth value at
    least as new as the generation it saw.
  • Along the way, upgrades the existing bandwidth-measured debug log
    from just the computed bandwidth_kbps to the whole Bandwidth
    Measure Results response, which carries the raw
    byte_count/time_delta_ms inputs. Useful on its
    own for anyone diagnosing why the figure looks noisy against a
    bursty traffic source (as this crate's own damage-driven server
    usage does): the raw inputs make it immediately visible whether a
    low reading came from a genuinely idle window or a short one that
    happened to close early.

Validation

cargo xtask check fmt/lints/tests/typos/locks all pass. testsuite-core
covers the generation handle's default and injection; the increment itself
runs in the private connection loop, which no harness reaches.

Notes

No public API break: both changes are purely additive to
RdpServerBuilder and RdpServer.

@github-actions github-actions Bot added kind/protocol Affects RDP or related protocol behavior risk/medium Behavioral change that does not substantially alter a core public API size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure needs-review A human reviewer is the current next actor labels Sep 12, 2026

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.

Copilot review overview

🟡 Changes recommended

The relaxed atomics cannot provide coherent generation/value snapshots, and the new transitions lack tests.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)
What changed in this PR

Adds a generation counter so embedders can detect completed bandwidth-measurement windows.

Changes:

  • Exposes configurable bandwidth-generation handles.
  • Increments generation for successful and unusable measurements.
  • Adds raw measurement inputs to debug logging.

Protocol review found no wire-format changes. Prose verification was skipped because no standalone documentation changed.

File Description
crates/​ironrdp-server/​src/​server.rs Stores, exposes, and updates generation state.
crates/​ironrdp-server/​src/​builder.rs Adds generation-handle injection.

Comment thread crates/ironrdp-server/src/server.rs Outdated
Comment thread crates/ironrdp-server/src/server.rs Outdated
bandwidth_kbps alone reads as noise on a damage-driven video source: a
single 1.25s measurement window catches either near-idle traffic (a
handful of cursor/autodetect PDUs, ~1.8KB) or a real EGFX frame landing
in it (tens of KB), so the same unthrottled link reports anywhere from
~11kbps to ~600kbps depending on what the encoder happened to be doing
in that specific window. Logging time_delta_ms/byte_count alongside the
computed figure makes that bimodality visible instead of looking like a
calculation bug -- the formula (byte_count*8/time_delta_ms) was already
correct; the volatility is inherent to counting real traffic over a
short window against a bursty source, not a defect.
The bandwidth figure alone repeats too often to tell a fresh
measurement window apart from a stale one (a quiet link reads the
same low figure for several consecutive windows). Expose a counter
that increments on every completed Bandwidth Measure transaction,
successful or not, so a consumer can gate its own filtering logic on
"a new window just closed" instead of diffing the value itself.
@glamberson
Greg Lamberson (glamberson) force-pushed the feat/bandwidth-measure-generation-counter branch from bcbbb9a to ee87cf1 Compare September 22, 2026 22:30
@github-actions github-actions Bot removed kind/protocol Affects RDP or related protocol behavior needs-review A human reviewer is the current next actor labels Sep 22, 2026

@github-actions github-actions Bot 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.

Independently verified: the additive generation counter mirrors the existing autodetect handle family (builder field, initializers, RdpServer::new parameter, default, accessor) and increments at both Bandwidth Measure completion branches, consistent with AutoDetectManager's clearing semantics. No protocol or API break found. Three low-severity quality issues remain: the bundled log enrichment adds an unreachable!() panic in the PDU-handling loop to extract two debug fields (dead branch today, but a cross-crate invariant with a panic-free, shorter alternative); no test pins the increment-on-both-branches semantics (the None branch advances the generation while the figure reads u32::MAX); and the documented read-generation-then-bandwidth pairing has no cross-atomic ordering guarantee under Relaxed on weakly ordered targets. The two specialist let-else findings describe the same defect and were merged into one published finding.

Comment thread crates/ironrdp-server/src/server.rs Outdated
Comment thread crates/ironrdp-server/src/server.rs Outdated
Comment thread crates/ironrdp-server/src/server.rs
@github-actions github-actions Bot added the ai-reviewed/1 One automated review completed label Sep 22, 2026
…g panic path

The generation counter is now incremented with Release after the
bandwidth store, and the accessor documents an Acquire load and an
at-least-as-new guarantee rather than an exact pair. The bandwidth log
records the whole response instead of destructuring it behind an
unreachable!(). Adds default and injection tests for the generation
handle.
@github-actions github-actions Bot added the triage/overlap Possible overlap with another pull request; advisory only label Sep 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request may overlap with #1964.

Both pull requests currently modify the server's handling of PDUs received on the MCS message channel in crates/ironrdp-server/src/server.rs. This PR edits the AutoDetectOutcome::Bandwidth arms inside handle_message_channel_data; #1964 reworks that same function's decode dispatch of message channel data. The shared region means the two would need to be reconciled, though their purposes differ: a bandwidth freshness counter versus recognizing the Initiate Multitransport Response.

This notice is advisory only. Automated review continues as usual, and how these pull requests relate is for maintainers and authors to decide.

Note

LLM-assisted content (no human feedback).

@mamoreau-devolutions
Marc-André Moreau (mamoreau-devolutions) merged commit ded2caa into Devolutions:master Sep 28, 2026
42 checks passed

This branch was successfully deployed

1 active deployment
llm-providers — fcab3b73 Deployed Sep 23, 2026 by glamberson via Classify pull request #589
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-reviewed/1 One automated review completed needs-review A human reviewer is the current next actor risk/medium Behavioral change that does not substantially alter a core public API size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure triage/overlap Possible overlap with another pull request; advisory only

Development

Successfully merging this pull request may close these issues.

3 participants