From 8607720219d63e812333dee0bc27e57ef7a5c67b Mon Sep 17 00:00:00 2001 From: Nils Andreas Svee Date: Fri, 14 Aug 2026 15:00:38 +0700 Subject: [PATCH] docs(server): describe single allowance as one instant --- README.md | 11 ++++++----- crates/irtt-cli/src/cmd/server/args.rs | 4 ++-- crates/irtt-server/AGENTS.md | 4 +++- crates/irtt-server/src/config.rs | 20 ++++++++++++++------ crates/irtt-server/src/lib.rs | 7 ++++--- crates/irtt-server/src/negotiate.rs | 11 +++++++---- 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 601a898..eeda0a7 100644 --- a/README.md +++ b/README.md @@ -213,11 +213,12 @@ irtt-server \ ``` `--timestamp-allowance` takes `dual` (the default, honoring every requested -placement), `single`, which provides at most one timestamp and answers a request -for both receive and send timestamps with the midpoint, or `none`, which provides -no timestamps. The requested clock source is never changed. `--no-dscp` -negotiates any requested DSCP to zero, so clients are told their echo replies -will be unmarked, and they are sent unmarked. +placement), `single`, which provides at most one timestamp instant and answers a +request for both receive and send timestamps with the midpoint, or `none`, which +provides no timestamps. The requested clock source is never changed, so a single +instant is still reported once per requested clock. `--no-dscp` negotiates any +requested DSCP to zero, so clients are told their echo replies will be unmarked, +and they are sent unmarked. To require authentication, pass the shared key both sides use: diff --git a/crates/irtt-cli/src/cmd/server/args.rs b/crates/irtt-cli/src/cmd/server/args.rs index b0cf3be..3378c96 100644 --- a/crates/irtt-cli/src/cmd/server/args.rs +++ b/crates/irtt-cli/src/cmd/server/args.rs @@ -85,7 +85,7 @@ pub struct ServerArgs { long, value_name = "MODE", value_enum, - long_help = "How many timestamps this server will provide.\n\ndual: honor a request for send, receive, both or midpoint timestamps.\nsingle: provide at most one timestamp; a request for both is negotiated to midpoint.\nnone: provide no timestamps at all.\n\nThe requested clock source is never changed, only the timestamp placement. Omit this flag to honor every requested placement." + long_help = "How many timestamps this server will provide.\n\ndual: honor a request for send, receive, both or midpoint timestamps.\nsingle: provide at most one timestamp instant; a request for both is negotiated to midpoint.\nnone: provide no timestamps at all.\n\nThe requested clock source is never changed, only which instants are reported, so a single instant is still reported once per requested clock. Omit this flag to honor every requested placement." )] pub timestamp_allowance: Option, @@ -105,7 +105,7 @@ pub struct ServerArgs { pub enum TimestampAllowanceArg { /// Honor every requested timestamp placement. Dual, - /// Provide at most one timestamp; both becomes midpoint. + /// Provide at most one timestamp instant; both becomes midpoint. Single, /// Provide no timestamps. None, diff --git a/crates/irtt-server/AGENTS.md b/crates/irtt-server/AGENTS.md index 7ed58a2..1c64007 100644 --- a/crates/irtt-server/AGENTS.md +++ b/crates/irtt-server/AGENTS.md @@ -272,7 +272,9 @@ of open negotiation, and neither reaches the runtime. interesting row; the rest is in the clean spec's Section 11.4. - **`Clock` is never rewritten.** The evidence describes an allowance on timestamp *placement*, not on clock domains, and the echo layout already carries no - timestamp field once the placement is none. Rewriting the clock would answer + timestamp field once the placement is none. So `Single` bounds reported + *instants*, not field count: on `Clock::Both` a negotiated midpoint still emits + a wall and a monotonic field. Do not document it as one field. Rewriting the clock would answer with a session the client did not ask for. - **Restriction runs before the effective-session executability check**, and that ordering is load-bearing: it is what makes a request selecting timestamps with diff --git a/crates/irtt-server/src/config.rs b/crates/irtt-server/src/config.rs index 76e5649..583bed6 100644 --- a/crates/irtt-server/src/config.rs +++ b/crates/irtt-server/src/config.rs @@ -69,9 +69,14 @@ pub enum TimestampAllowance { /// No timestamps at all: every request is negotiated to /// [`StampAt::None`](irtt_proto::StampAt::None). None, - /// At most one timestamp field. A request for both receive and send becomes - /// [`StampAt::Midpoint`](irtt_proto::StampAt::Midpoint); every mode that is - /// already single is left alone. + /// At most one timestamp *instant*. A request for both receive and send + /// becomes [`StampAt::Midpoint`](irtt_proto::StampAt::Midpoint); every + /// placement that already names a single instant is left alone. + /// + /// This restricts placement, not field count: the reply still carries one + /// field per negotiated clock domain, so a session on + /// [`Clock::Both`](irtt_proto::Clock::Both) receives both a wall and a + /// monotonic midpoint field. Single, /// Every requested placement is honored. This is the default, and the /// behavior of a server that configures nothing. @@ -266,9 +271,12 @@ impl ServerConfig { /// not with whichever of the two the server felt like keeping. /// /// The requested [`Clock`](irtt_proto::Clock) is left exactly as it was in - /// every case. The allowance restricts placement, and the echo layout simply - /// carries no timestamp field once the placement is - /// [`StampAt::None`](irtt_proto::StampAt::None). + /// every case. The allowance restricts which *instants* are reported, and + /// each reported instant still carries one field per negotiated clock domain + /// — [`Single`] on [`Clock::Both`](irtt_proto::Clock::Both) reports a wall + /// and a monotonic midpoint. Only [`None`] removes timestamp fields + /// outright, and it does so because the echo layout carries none once the + /// placement is [`StampAt::None`](irtt_proto::StampAt::None). /// /// Restriction runs *before* the effective-session check, which is what /// makes a [`None`] allowance accept a request that selected timestamps diff --git a/crates/irtt-server/src/lib.rs b/crates/irtt-server/src/lib.rs index d568ba1..5d1a68f 100644 --- a/crates/irtt-server/src/lib.rs +++ b/crates/irtt-server/src/lib.rs @@ -70,9 +70,10 @@ //! negotiates exactly what it always did. //! //! [`TimestampAllowance`] reduces the requested timestamp placement: `Single` -//! provides at most one timestamp, answering a request for both instants with -//! the midpoint, and `None` provides no timestamps at all. The requested clock -//! is never rewritten. [`ServerConfig::with_dscp_allowed`] refuses to provide +//! provides at most one timestamp instant, answering a request for both instants +//! with the midpoint, and `None` provides no timestamps at all. The requested +//! clock is never rewritten, so a single placement still reports one field per +//! negotiated clock domain. [`ServerConfig::with_dscp_allowed`] refuses to provide //! traffic-class marking, negotiating any requested DSCP value to zero, after //! which the session's replies leave unmarked like any other zero-DSCP session. //! diff --git a/crates/irtt-server/src/negotiate.rs b/crates/irtt-server/src/negotiate.rs index a8e6b5c..3bbe7c4 100644 --- a/crates/irtt-server/src/negotiate.rs +++ b/crates/irtt-server/src/negotiate.rs @@ -129,10 +129,13 @@ pub(crate) fn negotiate_params(mut requested: Params, config: &ServerConfig) -> /// /// The mapping is the observed one, from the clean specification's Section 11.4. /// Only one row substitutes rather than removes: under [`Single`], a request for -/// both instants is answered with [`StampAt::Midpoint`] — one timestamp that -/// still describes both — and not with whichever of Send or Receive an -/// implementation happened to prefer. Every already-single placement passes -/// through, and [`None`] removes all of them. +/// both instants is answered with [`StampAt::Midpoint`] — one instant that still +/// describes both — and not with whichever of Send or Receive an implementation +/// happened to prefer. Every already-single placement passes through, and +/// [`None`] removes all of them. +/// +/// The allowance bounds reported *instants*, not fields: the clock is untouched, +/// so a negotiated midpoint on `Clock::Both` still reports one field per domain. /// /// [`Single`]: TimestampAllowance::Single /// [`None`]: TimestampAllowance::None