| Internet-Draft | TARE | October 2026 |
| Cummings | Expires 28 April 2027 | [Page] |
Network Time Protocol (NTP) offset measurements can contain bias associated with differences in packet serialization delay in the forward and reverse directions. This document describes TARE (Time Asymmetry Regression Estimator), a client-side experimental method that estimates a packet-length-dependent component of measured NTP offset using regression over exchanges with varied packet lengths. A client may use the estimate to produce two named outputs (Section 6.1): Output A, an offset normalized to a selected reference packet length, which does not reduce the length-dependent bias at that length; and Output B, the intercept of the fitted model at zero length of a documented length layer, an extrapolated quantity whose meaning depends on the validity of the model.¶
TARE does not, by itself, determine or remove fixed propagation-delay asymmetry, distinguish that asymmetry from true clock offset, or guarantee improved synchronization accuracy. This document defines an experimental measurement model, calibration procedure, validity checks, fallback behavior, and evaluation plan. It does not define new NTP packet fields or require server changes.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 28 April 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Network Time Protocol (NTP) estimates clock offset from timestamps exchanged between a client and a server. The usual offset estimate depends on the difference between forward and reverse path delays. When the paths have unequal delays, the estimate can be biased even if the timestamps themselves are accurate.¶
One component of path delay is serialization delay: the time required to transmit a packet over a link. Serialization delay depends on packet length and link rate. If forward and reverse path rates or effective transmitted lengths differ, changing packet length can change the measured offset. This creates a potentially observable relationship between packet length and measured offset.¶
TARE (Time Asymmetry Regression Estimator) is an experimental client-side method for estimating that relationship. The name refers to the effect of forward and reverse rate asymmetry on measured offset; the method estimates only the packet-length- dependent component of that effect, not path asymmetry in general. A client collects measurements at several packet lengths, fits a model, and uses the fitted length-dependent term to normalize measurements to a reference length. TARE is an estimator layered above existing NTP exchanges; it does not require a new wire format.¶
The method rests on a limited claim. A regression can estimate a length-dependent component only when that component is sufficiently stable and distinguishable from other time-varying effects. The regression intercept does not, in general, reveal the true clock offset. Fixed propagation asymmetry and true clock offset are confounded in ordinary two-way measurements. TARE results are relative to the selected server (Section 6.5).¶
This document specifies a candidate experimental procedure and safeguards intended to make that limitation explicit. The algorithm and results are preliminary; independent implementation and real-network validation are needed before any standards-track recommendation.¶
Different error sources respond to different improvements. Hardware timestamping reduces timestamp-capture uncertainty. Better oscillators reduce drift between measurements. Higher link rates reduce serialization delay. None of these automatically removes directional asymmetry in network delay, and as some error terms shrink, others become the limiting factor. TARE addresses one term: a component of measured offset that depends on packet length.¶
The value of the method is not that packet-length regression solves every source of synchronization error. When the model's assumptions hold, the regression may remove a systematic, length-dependent component of measured offset that averaging at a single length leaves behind. Whether that is useful on a given path depends on the rate asymmetry, the achievable length spread, timestamping quality, and estimator uncertainty; no universal link-rate threshold is claimed. The decisive test is whether TARE reduces the relevant error more reliably than a fair alternative under the same measurement budget (Section 11).¶
Serialization delay scales inversely with link rate, so the effect is larger where forward and reverse rates differ structurally. Access networks with asymmetric rates (for example, some DSL, DOCSIS, and PON deployments) are candidates for evaluation. ADSL2plus, for instance, is specified for minimum net rates of 16 Mbit/s downstream and 800 kbit/s upstream [G992.5]; G-PON specifies an upstream time-division multiple access mechanism with dynamic bandwidth assignment [G984.3]; and DOCSIS upstream uses a request-grant mechanism that is generally reported to add 2-8 ms before any queuing [LLD]. They are not assumed to be suitable: upstream scheduling or grant mechanisms on such links can add delay that is large compared with serialization and may not be linear in packet length, which would violate the model in Section 4.1. Section 11.2 states these conditions as hypotheses to be tested.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals.¶
This document describes an experimental algorithm. The requirements language expresses the intended behavior of implementations of this experiment; it does not imply that TARE is an IETF-approved protocol. The key words are used only for behavior whose compliance can be checked from an implementation's inputs, outputs, or recorded state. Other statements are descriptive.¶
Measurement: An NTP exchange and the offset, delay, timestamps, and packet-length metadata derived from it.¶
Probe length: The packet length varied by the client during calibration.¶
Length layer: The protocol layer at which a length is counted, for example the NTP payload, the UDP datagram, the IP packet, or the link-layer frame. Implementations document which layer defines the probe length.¶
Effective transmitted length: The number of octets relevant to serialization on a particular link. It can differ from an IP or UDP length due to encapsulation, link-layer framing, and other overhead.¶
Timestamp reference point: The point in a frame, for example its start or its end, to which a timestamp refers.¶
Reference length (L0): The probe length to which measurements are normalized. It is normally chosen within the range of lengths actually measured. A value outside that range relies on extrapolation, and the reported uncertainty then includes the extrapolation term (Section 6.3).¶
Output A (length-normalized offset): The offset a probe of length L0 would be expected to measure.¶
Output B (model intercept at zero length): The value at zero length of the fitted linear model, evaluated at the documented length layer. It is an extrapolated quantity: it removes only the length- dependent component represented by the fitted model, and its meaning and uncertainty depend on whether the assumed linear relationship holds between the observed range and zero.¶
Zero length: Zero octets at the documented length layer. It is a property of the length variable, not a physical packet. Overhead that the documented layer does not count is not extrapolated away (Section 4.4).¶
Calibration: The process of collecting measurements and estimating the relationship between measured offset and probe length. In this document the word denotes a defined measurement procedure with specified uncertainty reporting, not a calibration in the sense of ISO/IEC 17025 (Section 6.5).¶
Valid calibration: A calibration that passes the implementation's preconfigured data sufficiency, model-fit, stability, and uncertainty checks.¶
TARE has the following goals:¶
Estimate a packet-length-dependent component of measured offset.¶
Normalize measurements to a reference length using a fitted model.¶
Detect conditions under which the model is not sufficiently supported and disable the correction in those conditions.¶
Operate without new NTP packet fields or mandatory server changes.¶
Make uncertainty and limitations visible to the clock-selection and clock-discipline logic.¶
TARE does not attempt to:¶
Infer absolute clock offset from the regression intercept alone.¶
Remove fixed propagation-delay asymmetry.¶
Correct arbitrary queueing, routing, scheduling, or timestamping errors that are not explained by the model.¶
Replace NTP source selection, authentication, filtering, or clock discipline.¶
Treat a good regression fit as proof that a time source is honest.¶
Estimate oscillator frequency, or specify check intervals or holdover behavior. The time-trend term of Section 4.3 is a nuisance parameter that reduces confounding; it is not an output.¶
Certify accuracy against a primary time reference.¶
TARE is intended initially for controlled experiments and client implementations that can retain per-exchange metadata. It is not a requirement for general NTP interoperability.¶
TARE is a calibration procedure, not a clock discipline algorithm. Its outputs describe measured offset at the time of calibration. How an implementation uses them, for example for immediate slewing, gradual steering, or operator intervention, is outside the scope of this document. Calibration quality is determined by path characteristics, timestamping hardware, and estimator noise, not by the choice of discipline algorithm. This document does not prescribe update frequency, slew limits, or holdover strategies.¶
TARE is one mechanism among several that address different error terms. They are complementary rather than strictly hierarchical:¶
Hardware or kernel timestamping reduces uncertainty about when packets enter or leave the network. Interleaved modes [RFC9769] allow a server to return a more accurate transmit timestamp captured after transmission.¶
TARE estimates a packet-length-dependent component of measured offset, which is most relevant on paths with asymmetric rates and no other correction for that component.¶
Network-device corrections, such as the Network Correction Extension Field of NTP over PTP [RFC10030] and the Correction Extension Field of NTPv5 [NTPv5], account for delay added by forwarding devices. They can overlap with TARE's target; see Section 8.2.¶
An independent external reference, for example a GNSS-disciplined clock, establishes a clock's offset relative to that reference through a separate path, provided the arrangement is sufficiently accurate. It can help distinguish errors that TARE cannot resolve, including fixed propagation asymmetry. It does not remove path asymmetry from any concurrent NTP exchange.¶
An implementation selects mechanisms according to what its deployment supports and avoids applying overlapping corrections twice (Section 6.4).¶
Let theta_i be the offset estimate produced from exchange i using the applicable NTP timestamp equations. Let L_i denote the configured probe length for that exchange. Under the usual two-way measurement model, the observed offset includes the true clock offset and one half of the difference between forward and reverse path delays. With the [RFC5905] definition theta = ((T2 - T1) + (T3 - T4)) / 2, the measured offset equals the true offset plus (d_f - d_r) / 2, where d_f and d_r are the forward and reverse one-way delays; it is positive when the forward path is slower. Implementations MUST use this convention, and units are microseconds for offset and delay, bytes for length, and microseconds per byte for slope.¶
If forward and reverse effective lengths are equal to L_i, and if the only length-dependent contribution is serialization on fixed-rate links, a simplified model is:¶
theta_i = C + b (L_i - L0) + epsilon_i¶
where:¶
theta_i is the measured offset for exchange i; C is the expected measured offset at reference length L0; b is the length-dependent offset slope; L_i is the probe length for exchange i; L0 is the chosen reference length; and epsilon_i represents measurement noise and unmodeled effects.¶
For a simple pair of fixed-rate bottleneck links, with equal packet lengths in each direction, the serialization contribution to the slope can be approximated by:¶
b = (1/2) * 8 * (1/Rf - 1/Rr) [microseconds per byte if the rates are expressed in Mbit/s]¶
where Rf and Rr are the effective forward and reverse rates. For several store-and-forward hops carrying packets of equal length in both directions, the sum over hops of the same term applies. If only the request length is varied and the response length is fixed, the slope is half the forward per-byte serialization time and is not the asymmetry (toy test, 2026-10-23: 0.400 against 0.360 us/B). This equation is an idealized model, not a method for inferring link rates from arbitrary Internet measurements. It also assumes particular timestamp reference points (Section 4.4).¶
In a real path, packet length can affect queueing, scheduling, fragmentation, encapsulation, or route selection. In those cases, a linear slope may not represent serialization alone. TARE therefore treats the slope as an empirical coefficient unless the path and timestamping conditions justify the physical interpretation.¶
TARE normally uses a reference length within the range of lengths measured during calibration. This avoids relying on extrapolation beyond the data. The fitted value C is the expected offset at L0; it still includes true clock offset, fixed path asymmetry, and any other length-independent bias.¶
Output A normalizes to L0. At L0 the length-dependent bias b * L0 is still present, so Output A has the same expected bias as an ordinary sample at L0 and does not reduce it (toy test, 2026-10-23: 107.4 us for both). Output B, the fit extrapolated to zero length, is the only output that removes the length-dependent term. Extrapolation beyond the measured range relies on the linear model, and its uncertainty is larger than that of Output A. Output B is not the true clock offset: a fixed propagation asymmetry remains in both outputs (75 us in the toy model) and cannot be separated from the true offset by this method. Implementations SHOULD NOT label Output B as an absolute offset.¶
If calibration measurements span a period in which the clock offset or path delay changes, a length-only regression can attribute time variation to packet length. Calibration exchanges MUST be sent in randomized length order (toy test, 2026-10-23: with sequential order a 1 ppm drift shifts Output B by about -20 us and the illustrative validity gate rejected only 1.4% of such fits). A time term MAY be fitted, but only when the order is randomized, because in sequential order it is collinear with length. One possible model is:¶
theta_i = C + b (L_i - L0) + c (t_i - t0) + epsilon_i¶
where t_i is the measurement time, t0 is a centered reference time, and c represents a first-order time trend. The term c aggregates all drifting effects in the window, including oscillator frequency error and slowly varying path delay, so it is a nuisance parameter and is not reported as an output. A time term does not repair abrupt path changes or arbitrary correlations between packet length and time. Implementations SHOULD reject calibrations where length and time are too strongly confounded to estimate reliably.¶
Implementations MUST record the layer at which L_i is measured. Depending on the environment, relevant lengths may include the NTP payload, UDP datagram, IP packet, or effective transmitted frame. These quantities are not interchangeable. Encapsulation and link- layer overhead can make effective transmitted length differ by direction or link.¶
If the implementation counts payload only, Output B retains the product of the slope and the omitted overhead (toy test, 2026-10-23: about +10 us for 28 bytes, +24 us for 66 bytes, +36 us for 100 bytes at 0.36 us/B), and the illustrative validity gate did not detect it (Appendix C, Table C-3: the gate rejected 0.9, 1.0, and 1.0 percent of fits for 28, 66, and 100 bytes, against 1.1 percent with no overhead). Output B is therefore the model intercept at zero of the documented layer, not at zero physical bytes.¶
A client usually cannot observe the effective transmitted length on every intermediate link. When it cannot, the length variable is an implementation-defined probe-length proxy. The fitted coefficient MUST NOT be presented as a direct measurement of physical link rates unless the needed assumptions have been independently established.¶
The model in Section 4.1 also depends on where in each frame the four timestamps are taken. Protocols and implementations differ. For example, NTPv5 [NTPv5] defines the server receive timestamp as the end of reception and the server transmit timestamp as the beginning of transmission, and NTP over PTP [RFC10030] recommends a transmit timestamp at the beginning of the frame and a receive timestamp at its end. A different reference point changes which serialization intervals are included in the measured offset and with what sign, so the relation between the fitted slope and the link-rate difference depends on it. Implementations MUST record the timestamp reference point for each of the four timestamps where it is known, and otherwise record that it is unknown.¶
The client selects a set of packet lengths within the path's supported size range. It SHOULD avoid lengths that cause IP fragmentation and SHOULD keep the other relevant packet fields stable where possible. The client MUST obey the selected NTP version's message-format and interoperability requirements. This document does not authorize arbitrary packet padding or changes to NTP message formats.¶
Equal request and response length is required by the model. In NTPv5 (draft-ietf-ntp-ntpv5-09, Section 10) the response must be the same length as the request, and servers must support the Padding extension field (Section 7.2), which provides a conforming way to vary probe length. A Correction Extension Field, when used, must be the last extension field of the message (Section 7.6), so padding precedes it. NTP over PTP [RFC10030] similarly recommends padding a response to the length of its request. For NTPv4 a response is not guaranteed to mirror the request length; a TARE client MUST measure the response length and either fit request and response lengths separately or decline to fit. Deployed NTPv4 server behavior has not been surveyed for this document.¶
NTPv5 also advises clients to use constant-length requests for an association, to avoid adding variation to the measured delay (Section 7.4 of -09, in the context of reference ID requests). TARE varies length deliberately, so a TARE client SHOULD confine length variation to bounded calibration bursts, SHOULD use constant-length requests otherwise, and SHOULD label calibration exchanges so that ordinary filtering does not mix them with steady-state samples.¶
For each accepted exchange, the client records at least:¶
the four timestamps used by the NTP offset and delay calculations; o the measured offset and round-trip delay; o the configured probe length and the layer at which it is measured; o the timestamp reference points (Section 4.4); o the local monotonic measurement time; o the server identity and protocol version; o timestamping mode, if known; o whether the sample was filtered or rejected, and why; and o relevant available correction information from the protocol or implementation, including whether a network correction was applied (Section 8.2).¶
The client SHOULD interleave or randomize lengths rather than send all small packets followed by all large packets. This reduces confounding between length and time. It SHOULD use a bounded number of exchanges and SHOULD respect server polling and rate limits.¶
Implementations MAY use an existing NTP filtering policy, but the policy MUST be documented and applied consistently. Selecting the minimum-delay sample independently at each length can change the statistical properties of the samples and can bias the fitted slope. Therefore, an implementation SHOULD compare calibration results under its selected policy with a suitable sensitivity check.¶
Minimum-delay filtering may reduce some variable-delay effects, but it does not establish that forward and reverse delays are equal and does not eliminate path asymmetry.¶
The client fits the selected model to the collected measurements. Ordinary least squares is a useful baseline. A robust estimator MAY be used when outliers are expected, but robust fitting does not compensate for a wrong model, path changes, or adversarially manipulated samples.¶
The client MUST have enough distinct lengths and accepted samples to estimate the selected model. A fit with insufficient length spread, excessive collinearity between length and time, or numerically unstable coefficients MUST be rejected.¶
The fitted slope is b_hat. The estimated offset normalized to L0 is:¶
theta_hat(L0) = theta(L) - b_hat (L - L0)¶
for an individual measurement at length L. If the implementation uses the fitted line directly, the equivalent prediction at L0 is the fitted intercept C_hat under the reference-length model.¶
For ordinary least squares with n groups, mean length Lbar, Sxx = sum (L_i - Lbar)^2 and residual standard deviation s, the standard error of the slope is s / sqrt(Sxx) and of the zero-length intercept s * sqrt(1/n + Lbar^2 / Sxx). Both MUST be included in the reported uncertainty, within the classification of Section 6.3. A narrow length range inflates them (toy test, 2026-10-23, 48 exchanges: lengths 90-1400 B intercept sd 7.0 us; 90-250 B 11.8 us; Appendix B).¶
Implementations SHOULD retain residuals, slope uncertainty, and goodness-of-fit diagnostics. A single goodness-of-fit statistic is not sufficient to establish calibration validity.¶
A calibration result SHOULD include:¶
the reference length L0; o the estimated slope and its uncertainty; o Output A and Output B with their uncertainty statements (Section 6.3); o the number and range of accepted lengths and samples; o the length layer and the timestamp reference points; o residual and stability diagnostics; o the time window over which it was estimated; o a validity state, a validity timestamp, a validity period, and the reason for any rejection; o the reference conditions: server, path or interface identifier, protocol version, and timestamping mode; and o whether any network correction was applied before fitting.¶
TARE's estimated slope is not itself a clock offset correction. Implementations MUST distinguish slope estimation, normalization to a reference length, and the final clock-offset estimate used by the clock discipline.¶
A TARE calibration produces two named outputs.¶
Output A (length-normalized offset) is the offset normalized to a stated reference length L0. It has the same expected length- dependent bias as an ordinary sample at L0 and offers no bias reduction.¶
Output B (model intercept at zero length) is the fitted linear model extrapolated to zero length at the documented length layer. It removes only the length-dependent component represented by the fitted model. Its meaning and uncertainty depend on whether the assumed length-offset relationship holds between the observed range and zero.¶
Neither output establishes the true absolute clock offset. Fixed path asymmetry and reference-server error remain in both. If the measured length layer omits headers, framing, or encapsulation, Output B retains the product of the fitted slope and the omitted overhead, a term the regression cannot detect (Section 4.4).¶
When a calibration is valid, a client MAY normalize a measurement from length L to reference length L0 by subtracting the estimated length-dependent term:¶
theta_corrected = theta_measured - b_hat (L - L0)¶
The corrected value is an offset estimate normalized to L0. It is not necessarily an unbiased estimate of the true clock offset, because fixed propagation asymmetry and other length-independent biases remain.¶
The standard errors of Section 5.3 are not a complete uncertainty budget. They presuppose the regression assumptions. A calibration SHOULD report an uncertainty statement for each output that classifies the budget into three categories:¶
ESTIMATED from the regression: the residual noise s, the slope standard error, the intercept standard error, the standard error of the fitted value at L0 (including the extrapolation term when L0 is outside the measured range), and, where fitted, the time-trend standard error. These are valid only under the stated regression assumptions. Where samples are correlated or delays vary with time, the least-squares formulas understate the sampling uncertainty, and implementations should qualify or inflate them.¶
ASSUMED by the model: linearity of the length-offset relationship within and below the observed range, the absence of unmodeled length-dependent behavior (queueing thresholds, fragmentation, shapers, scheduling), and the correctness of the length layer and timestamp reference points. These assumptions are documented, not measured, and the validity checks of Section 7 monitor them only partially.¶
UNOBSERVABLE from TARE measurements alone: fixed path propagation asymmetry, the reference server's own time error, and timestamping calibration error. These terms appear in no output of the regression and set a floor on absolute accuracy that no confidence interval from the fit can reduce.¶
An expanded uncertainty with a stated coverage factor may be computed for the ESTIMATED category only. The ASSUMED and UNOBSERVABLE categories are reported qualitatively or with deployment-specific bounds. A narrow regression confidence interval does not demonstrate accuracy of the absolute clock offset.¶
The client SHOULD NOT treat the corrected value as more precise than justified by both the measurement noise and the calibration uncertainty. If the reported uncertainty is too large to support the implementation's configured error budget, the client SHOULD disable the correction (Section 7).¶
If protocol-defined correction fields or implementation-specific corrections already account for part of the same delay, the implementation MUST avoid applying the same correction twice. An implementation MUST NOT apply a TARE correction to a delay or offset component already reported as corrected by a network correction field. Section 8.2 describes the fields known to this document.¶
TARE calibrations are relative to the selected time server. The client inherits the server's time without verifying the server's accuracy or traceability. TARE does not and cannot certify accuracy against a primary reference; a GNSS-disciplined or equivalent primary reference is required for absolute calibration, with that reference's own uncertainty taken into account.¶
Implementations SHOULD model calibration state explicitly. A suggested state machine is:¶
UNCALIBRATED -> CALIBRATING -> VALID | ^ | v | v INVALID <------+¶
Transitions INVALID -> CALIBRATING and VALID -> CALIBRATING (recalibration) are also permitted.¶
The exact state names are implementation-defined. A client SHOULD use ordinary NTP processing when no valid TARE calibration exists.¶
A calibration SHOULD be invalidated when one or more of the following occurs:¶
the fitted slope changes beyond a configured stability threshold; o residuals show significant curvature or systematic structure; o packet-size groups have inconsistent delay or offset behavior; o the route, interface, encapsulation, timestamping mode, network correction usage, or relevant link configuration changes; o there are insufficient fresh samples; o the correction uncertainty exceeds the configured limit; o the correction exceeds its configured bound (Section 9.2); or o a detected discontinuity indicates that the model no longer describes the measurements.¶
Implementations SHOULD bound the magnitude of applied corrections and SHOULD impose a maximum calibration lifetime as a secondary safeguard. A lifetime limit alone is not a substitute for detecting changes. Thresholds should be established through testing and documented; this document does not prescribe universal values.¶
When invalidated, the client MUST stop applying the stale correction and SHOULD fall back to ordinary NTP measurement processing while gathering new calibration data. A TARE client SHOULD fall back to its non-TARE estimate when any validity check fails, and MUST report that it did. The validity checks have limited power: in the 2026-10-23 toy-model tests the illustrative gate missed most size- dependent shaper, curvature, and fragmentation steps (rejection 1.3% to 3.2%) and detected sequential-order drift only at large values.¶
TARE is defined as a client-side measurement algorithm and adds no packet fields. A TARE implementation MUST follow the wire-format, extension-field, padding, and anti-amplification requirements of the NTP version it uses. It MUST NOT assume that a server supports arbitrary packet lengths or that a response will have a desired length unless the protocol and server behavior establish that fact.¶
Implementations SHOULD test with the relevant NTP version and server implementations before deployment. Calibration probes SHOULD be rate-limited, bounded, and disabled when the server or network signals congestion or imposes limits.¶
The initial experiment does not define a new NTP extension, negotiate TARE support, or require the server to participate in calibration. A future protocol extension, if justified by evidence, would require separate design and review.¶
Two different extension fields carry delay corrections from network devices:¶
NTP over PTP [RFC10030] defines a Network Correction Extension Field (type 0x010A). Its value is the sum of the corrections made by PTP transparent clocks and the time taken to receive the packet, computed from packet length and link speed. Per Section 3 of [RFC10030], the extension field carries the correction for the request, while the correction for the response is in the PTP header of the response message itself. A client that applies both therefore removes a length-dependent serialization term even when no transparent clock is on the path.¶
NTPv5 [NTPv5] defines its own Correction Extension Field, added by forwarding devices, whose type code is not yet assigned in draft -09. A forwarding device adds the time from the end of reception to the beginning of retransmission when link speed or packet length changes (Section 7.6 of -09). The client's corrected delay also accounts for packet receive and transmit durations (Section 8 of -09).¶
The overlap with TARE's regression target therefore depends on which field is in use and how the client applies it, not only on whether transparent clocks are present. This reading of the cited specifications has not been confirmed with their authors. A client that applies a network correction before fitting records that fact in the calibration record (Section 5.4); the fitted slope then estimates only the residual length dependence. Outside these mechanisms, TARE and network corrections address different terms.¶
Incorrect time can affect authentication, logging, distributed coordination, and security policy. Security requirements for time protocols are discussed in [RFC7384]. TARE introduces additional measurements and a model whose parameters can be influenced by network behavior.¶
The least-squares fit weights length groups unequally. For the six-length reference design (90, 250, 500, 800, 1100, and 1400 bytes, equal group sizes) the weights of the zero-length intercept are approximately 0.49, 0.40, 0.27, 0.11, -0.06, and -0.22 (computed analytically, 2026-10-23; Appendix B, Table B-2); their absolute values sum to about 1.55. If an attacker changes the measured offset of each group by at most x, Output B can change by up to about 1.55 x. A one-way delay of d changes a measured offset by d/2, so the corresponding bound for one-way delay is about 0.77 d.¶
In the Appendix C toy test, adding 200 us of one-way delay to 1400-byte packets only moved Output B by -21.9 us and left the 90-byte baseline unchanged, while adding the same delay to 90-byte packets only moved Output B by about +49 us and the baseline by +100 us. TARE therefore changes the attack surface relative to the non-TARE baseline rather than uniformly reducing or increasing it: it is less sensitive to delay confined to the length a single-length baseline uses, and it is sensitive to delay confined to other lengths. A toy test of an adversary that knows the length schedule is in Appendix D, Section D.7. Forward delay of s x (L - 90) bytes, which is zero at 90 bytes and linear in length, moved the fitted offset by about -22.5 us at s = 0.5 us/B (the longest packets delayed by about 655 us) without raising the fallback rate of the gate above its nominal level, while the 90-byte baseline did not move. In this model a schedule-aware adversary can bias TARE by an amount it chooses, and no fit-quality gate in this document detects it (Section 11.2).¶
An on-path attacker may delay packets as a function of packet length, manipulate queueing, or induce path changes to bias the estimated slope. A good linear fit is not evidence that the path is trustworthy.¶
Implementations SHOULD define and enforce a bound on the absolute magnitude of applied TARE corrections. The bound is a safeguard, not evidence that in-bound corrections are correct: a systematic error can remain well within any configured limit. The selection of the bound is documented and justified by experimental data appropriate to the deployment environment.¶
Exceeding the bound triggers invalidation and fallback to non-TARE measurement processing (Section 7), reported to the extent the implementation's observability permits.¶
Unacceptable residual structure, goodness-of-fit, or reported uncertainty also triggers invalidation and fallback, even when the prospective correction is small. Bounds constrain magnitude; fit checks constrain model validity. They address different failure modes.¶
No universal numerical bound is specified by this document. Any specific value requires empirical support from the evaluation program (Section 11).¶
Authentication of NTP messages, where available (for example NTS [RFC8915]), can establish message origin and integrity but does not prove that timing behavior is honest or symmetric.¶
Implementations SHOULD:¶
retain existing NTP source authentication and selection policies; o bound the magnitude of TARE corrections (Section 9.2); o monitor residuals, slope stability, and calibration age; o reject samples and calibrations that violate validity checks; o avoid letting TARE override source-selection or clock-discipline safeguards; and o compare independent sources where the deployment permits it.¶
Calibration traffic can impose load on servers and networks. Implementations MUST rate-limit probes and MUST NOT use TARE as a reason to send unbounded traffic. A client SHOULD fall back to ordinary NTP behavior if calibration is invalid or unavailable.¶
TARE does not correct fixed path asymmetry. An attacker or network condition that produces a constant directional delay difference may remain undetected by the length regression, and this limitation should be considered when interpreting the corrected offset.¶
This document has no IANA actions. It defines no new NTP fields, protocol numbers, ports, or registry entries. It refers to extension fields registered or requested by other documents ([RFC10030], [NTPv5]) and does not require changes to those registrations.¶
TARE is experimental. Evaluation SHOULD compare it with ordinary NTP measurement processing using matched measurement budgets and identical underlying network conditions. Results SHOULD report bias, standard deviation, tail error, calibration convergence time, probe overhead, false-valid rate, invalidation latency, and the fraction of time for which calibration is valid.¶
At minimum, evaluation SHOULD include:¶
analytically controlled fixed-rate asymmetry; o independent and correlated queueing in each direction; o different packet-length ranges and sample-selection policies; o clock-frequency error and time-varying offset; o path changes, encapsulation, and packet-size-dependent behavior; o outliers, packet loss, and server load; o adversarial delay manipulation, including an adversary that knows the length schedule; and o real hardware timestamping, where available.¶
Comparisons SHOULD include ordinary NTP filtering, TARE with ordinary least squares, and any robust or validity-checking variant. Experiments MUST compare methods using the same number of candidate exchanges and MUST report error against the true offset, not only the spread of estimators that target different quantities. Results with additional calibration traffic MAY be reported separately.¶
A successful fit in a simulation is necessary but not sufficient evidence of practical accuracy. A pooled-slope variant that was evaluated in the toy model, but is not specified by Sections 5 through 7, is described in Appendix D.¶
The following conditions are hypotheses to be tested by the evaluation program. They are not established deployment criteria.¶
H1: TARE provides measurable benefit when forward and reverse link rates are substantially asymmetric, no network correction already accounts for the length-dependent term, path delay varies linearly with length (no length-dependent scheduling or grant delay), and timestamp resolution is finer than the expected serialization effect.¶
H2: TARE provides little or no benefit when forward and reverse rates are equal, where matched-budget averaging performs at least as well.¶
H3: Under delay manipulation, TARE's error differs from the baseline's in a length-dependent way (Section 9.1). The evaluation tests whether an adversary that knows the length schedule can cause a larger error against TARE than against the baseline for the same delay budget.¶
H4: The achievable bias reduction on asymmetric access links is a function of the rate asymmetry and the effective length range, to be quantified by measurement.¶
The evaluation program tests these hypotheses under matched measurement budgets and identical conditions, reporting error against independently established ground truth.¶
All results in this document derive from a toy Monte Carlo model. A physical testbed is needed to convert this section from a plan into evidence. A suitable design is:¶
Two hosts, back-to-back or through a switch, under experimenter control. o Asymmetric link rates imposed through traffic control (for example tc and netem shaping), with the configured rates as ground truth. o Hardware or driver timestamping, where NIC support permits. o An independent time reference at each end to establish ground truth and decompose one-way delays.¶
The experiment documents a ground-truth uncertainty budget:¶
GNSS-disciplined references at both endpoints are useful but are not automatically ground truth. The experiment documents the references' own offset uncertainty, antenna and receiver delays, clock distribution paths, timestamping calibration, and the method used to compare the two time scales. o A second time server does not establish ground truth merely because it is trusted; its traceability and its path to the client are analyzed. o The experiment shows that the reference measurement is accurate enough to distinguish TARE's improvement from the reference's own measurement error.¶
Measurements include TARE calibration bursts at the six-length reference design, a matched-budget baseline under identical conditions, deliberately induced path variation (encapsulation and MTU changes), and runs of day-scale duration to capture oscillator temperature effects. Success criteria are defined in advance: bias reduction against the baseline under matched budgets, with uncertainty intervals, against independently established ground truth, with the reference uncertainty stated alongside every reported result.¶
Simulation assumptions, random seeds, source code, and all parameter values SHOULD be published so that results can be reproduced. The scripts named in Appendices A through E are reproduced in full in Appendix F, their output data in Appendix G, and SHA-256 checksums, dependency versions, random seeds, and command lines in Appendix H and Section E.2, so that this document is self-contained. Later revisions and independent evaluations SHOULD also place scripts and data in a public repository with a version tag matching the draft revision.¶
The toy-model simulations in this document illustrate the behavior of the estimator under stated assumptions. They are not evidence of benefit on real networks (see Appendix B). Quantitative performance claims require independent validation on production-class testbeds and real-world deployments.¶
This document is submitted with intended status Experimental, subject to the IETF process, to invite review and validation. Organizations with diverse network paths, hardware timestamping, and controlled testbeds are encouraged to conduct the evaluation described in this section and to report results, including negative results, to the NTP working group mailing list. Results from independent implementations and testbeds will inform future revisions or companion documents.¶
The following questions remain open and require further study:¶
Which packet-length definition is most useful and reproducible across common operating systems, timestamping hardware, and encapsulated paths?¶
Which timestamp reference points are used by deployed implementations, and how do they change the relation between the slope and the link-rate difference?¶
Which sample-selection policy provides the most stable slope without introducing selection bias?¶
How should calibration uncertainty be combined with existing NTP dispersion, delay, source-selection, and clock-discipline logic?¶
What minimum length spread and sample count provide reliable estimates under realistic noise?¶
Which validity thresholds generalize across path types, and which must be deployment-specific?¶
How much delay on asymmetric access links depends on packet length through scheduling or grant mechanisms, and does it violate the linear model?¶
How should length-varied calibration bursts coexist with the constant-length request guidance of NTPv5?¶
How much of the length-dependent term do the network correction fields of Section 8.2 already remove in practice?¶
Do the readings of NTPv5 and NTP over PTP in Section 8.2 (what the correction fields carry, where the four timestamps are taken, and how much of the length-dependent term the corrections remove) match the intent of the specification authors? This has not been confirmed with them. Comments from the authors and implementers, or experiments with correction-enabled clients, would settle it.¶
Does the method offer a measurable benefit over existing filtering and correction mechanisms under matched measurement budgets?¶
What prior work addresses packet-size-based estimation of clock offset or serialization asymmetry, and how does TARE differ? Sources read for this version, from abstracts or project pages rather than full texts: Huygens [HUYGENS] filters probe contamination and uses support vector machines to estimate one-way propagation times, and the page reviewed does not discuss packet size; iHorology [IHOROLOGY] bounds the offset error caused by path asymmetry using multiple servers and does not mention packet length; the fault-tolerant time synchronization project of Mills and Monington [MILLS-FT] applies cyclic-consistency checks across hosts to detect asymmetric paths and describes no length variation (that page is undated, and a search of the publications page of Mills found no paper on it); and US patent 7,023,884 (Lucent, found incidentally) corrects the bias of minimum-delay offset estimates without using packet length. NTP over PTP [RFC10030] removes a receive-duration term using known link speed (Section 8.2). The ITU-T G.8275.2 telecom profile [G8275.2] was reviewed only through its table of contents, which lists no section on asymmetry estimation or packet size; the body text of G.8275.2, and the assisted partial timing support work that it relies on, have not been read. Not yet examined: interleaved modes [RFC9769] and packet-size effects in IEEE 1588 simulation studies. No systematic patent or literature search has been performed. None of the items read estimates the length-dependent term by regression across varied packet lengths, but that absence is not established.¶
Until these questions are answered, TARE SHOULD be treated as an experimental estimator rather than a general solution to NTP asymmetry.¶
This appendix reports the preliminary toy Monte Carlo run (test date 2026-10-23). It is illustrative only: it is not an NTP implementation, not a model of the public Internet, and not evidence of benefit on real networks (Section 11.5).¶
Script: tare_monte_carlo_2026-10-23.py. The script is self-contained and does not use the shared core model of Appendices B through D. Seed: 20261022. Trials: 10,000. Command line: python3 -I tare_monte_carlo_2026-10-23.py, which writes tare_monte_carlo_results_2026-10-23.csv to the current directory. Dependencies: numpy and pandas.¶
True clock offset: 0 us.¶
Fixed forward/reverse propagation-delay difference: 150 us, which gives a fixed offset bias of 75 us.¶
One asymmetric access-link pair, forward 10 Mbit/s and reverse 100 Mbit/s, equal packet lengths in each direction: length-dependent slope 0.36 us/B.¶
Independent exponential queueing delays in each direction, mean 50 us.¶
Eight candidate exchanges per packet length; the candidate with the smallest sum of forward and reverse queueing delay is kept.¶
TARE: six lengths (90, 250, 500, 800, 1100, and 1400 B) and an ordinary least-squares line through the six kept samples. Baseline: one group of eight candidates at 90 B.¶
Not modeled: clock drift, packet loss, path changes, nonlinear size effects, and server processing effects.¶
| Metric | Mean | SD | 5th pct | 95th pct | Reference |
|---|---|---|---|---|---|
| Ordinary NTP-style 90-byte sample | 107.3 | 9.0 | 92.5 | 122.3 | 107.4 |
| TARE zero-length extrapolated intercept | 75.0 | 6.7 | 64.1 | 85.8 | 75 |
| TARE estimate normalized to 90 bytes | 107.4 | 6.1 | 97.4 | 117.2 | 107.4 |
| Estimated slope (us/byte) | 0.3600 | 0.0080 | 0.3470 | 0.3731 | 0.36 |
The ordinary 90 B sample averages 107.3 us (standard deviation 9.0 us). The zero-length intercept (Output B) averages 75.0 us (standard deviation 6.7 us), consistent with the 75 us fixed bias. The fitted value normalized to 90 B (Output A) averages 107.4 us (standard deviation 6.1 us), the same expected value as the ordinary sample. The estimated slope averages 0.3600 us/B with standard deviation 0.0080 us/B.¶
The smaller spread of Output A than of the ordinary sample (6.1 us against 9.0 us) is not a like-for-like comparison: TARE was given 48 candidate exchanges and the baseline 8. Appendix B repeats the comparison at equal budget.¶
This appendix reports the matched-budget comparison and the design sweeps (test date 2026-10-23). The question is whether the regression beats an ordinary estimator that is given the same number of candidate exchanges. All figures come from the toy model described in Section B.1 and are not evidence of benefit on real networks.¶
Script: tare_matched_budget_2026-10-23.py. It imports the shared core model tare_core_2026-10-23.py, which MUST be in the same directory. Seed: 20261023. Trials: 10,000 per experiment. Command line: python3 -I tare_matched_budget_2026-10-23.py OUTDIR. Outputs, each with the suffix _2026-10-23.csv: tare_E1_matched_budget, tare_E1_analytic_checks, tare_E2_design_sweep, tare_E2b_budget_sweep, and tare_E4_length_zero_meaning. Dependencies: numpy, scipy, and pandas.¶
Core model. The measured offset error of one candidate exchange is the fixed bias (75 us), plus one half of the forward serialization time minus the reverse serialization time (0.8 us/B forward and 0.08 us/B reverse, which gives a slope of 0.36 us/B), plus one half of the difference of the forward and reverse queueing delays (independent exponentials, mean 50 us), plus any scenario-specific term. The true clock offset is 0, so an estimate is its own error against the truth. For each length group the candidate with the smallest sum of queueing delays is kept. Exchanges are sent in sequential order unless a scenario says otherwise. The reference design is the six lengths 90, 250, 500, 800, 1100, and 1400 B with 8 candidates each (48 candidates).¶
The rows of Table B-1 target different quantities: the baselines and the OLS fitted value at 90 B target a 90 B sample (107.4 us expected value), and the zero-length rows target 75 us. The two expected values differ by the length-dependent bias, so the final column reports root-mean-square error against the true offset (0 us) for every row.¶
| Estimator | Budget | Target | Mean | SD | RMSE vs true |
|---|---|---|---|---|---|
| baseline, 1 group of 8 at 90 B (as in supplied sim) | 8 | 90 B sample (107.4) | 107.4 | 8.79 | 107.8 |
| baseline, mean of 6 groups of 8 at 90 B | 48 | 90 B sample (107.4) | 107.4 | 3.65 | 107.4 |
| baseline, median of 6 groups of 8 at 90 B | 48 | 90 B sample (107.4) | 107.3 | 3.58 | 107.4 |
| baseline, 1 group of 48 at 90 B (min-delay of 48) | 48 | 90 B sample (107.4) | 107.4 | 3.25 | 107.5 |
| TARE OLS, fitted value at 90 B | 48 | 90 B sample (107.4) | 107.4 | 6.00 | 107.6 |
| TARE OLS, zero-length intercept | 48 | zero-length (75) | 75.0 | 6.58 | 75.3 |
| TARE Theil-Sen, zero-length intercept | 48 | zero-length (75) | 75.0 | 6.90 | 75.3 |
At the 48-candidate budget, the minimum-delay sample of 48 candidates at 90 B has a standard deviation of 3.25 us. Output A (the OLS fitted value at 90 B) has 6.00 us, and Output B (the OLS zero-length intercept) has 6.58 us, about 2.0 times the baseline. The Theil-Sen intercept has 6.90 us. In this toy model Output A therefore offers no variance advantage over a well-formed baseline, which agrees with Section 4.2.¶
Output B averages 75.0 us against 107.4 us for the baseline: the regression removes about 32.4 us of length-dependent bias, at roughly twice the spread. Against the true offset, root-mean-square error is 75.3 us for Output B and 107.5 us for the baseline. The remaining 75 us is the fixed propagation asymmetry, which no row of the table removes.¶
| Quantity | Value |
|---|---|
| sd of one selected 90 B sample (from simulation) | 8.7922 |
| analytic sd, mean of 6 groups = s/sqrt(6) | 3.5894 |
| analytic sd, OLS intercept = s*sqrt(1/6+Lbar^2/Sxx) | 6.4631 |
| analytic sd, OLS fitted at 90 B | 5.8930 |
| analytic sd, OLS slope = s/sqrt(Sxx) (us/B) | 0.0078 |
| sum |weight| of OLS prediction at 0 B (worst-case per-group delay amplification) | 1.5465 |
| weight of 90 B group in prediction at 0 B | 0.4916 |
| weight of 250 B group in prediction at 0 B | 0.4050 |
| weight of 500 B group in prediction at 0 B | 0.2696 |
| weight of 800 B group in prediction at 0 B | 0.1071 |
| weight of 1100 B group in prediction at 0 B | -0.0554 |
| weight of 1400 B group in prediction at 0 B | -0.2179 |
| sum |weight| of OLS prediction at 90 B (worst-case per-group delay amplification) | 1.3883 |
| weight of 90 B group in prediction at 90 B | 0.4492 |
| weight of 250 B group in prediction at 90 B | 0.3739 |
| weight of 500 B group in prediction at 90 B | 0.2561 |
| weight of 800 B group in prediction at 90 B | 0.1149 |
| weight of 1100 B group in prediction at 90 B | -0.0264 |
| weight of 1400 B group in prediction at 90 B | -0.1677 |
Weights are for the six-length reference design with equal group sizes. The first row is a simulation result; the standard deviations in rows two to five scale from it.¶
The analytic standard deviations of the mean of six groups, the OLS intercept, and the OLS fitted value at 90 B are within about 2 percent of the simulated values in Table B-1 (for example 6.46 us analytic against 6.58 us simulated for the intercept). The weights of the zero-length intercept are 0.4916, 0.4050, 0.2696, 0.1071, -0.0554, and -0.2179, which round to the two-decimal figures quoted in Section 9.1; their absolute values sum to 1.5465.¶
Each row spreads 48 candidates over g groups of equal size, with lengths evenly spaced from 90 B to the stated maximum. These lengths differ from the reference design, so the six-group row with a 1400 B maximum is not identical to Table B-1. The test fit requires at least four groups, so three groups yield no fit.¶
| Groups | Cand. per group | Max length (B) | Intercept mean (us) | Intercept SD (us) | Slope SD (us/B) | Slope SE <= 0.02 (%) |
|---|---|---|---|---|---|---|
| 3 | 16 | 250 | no fit | - | - | - |
| 3 | 16 | 500 | no fit | - | - | - |
| 3 | 16 | 1400 | no fit | - | - | - |
| 4 | 12 | 250 | 75.0 | 10.5 | 0.0584 | 14.0 |
| 4 | 12 | 500 | 74.9 | 7.7 | 0.0229 | 56.7 |
| 4 | 12 | 1400 | 75.0 | 6.4 | 0.0072 | 99.7 |
| 6 | 8 | 250 | 75.0 | 11.8 | 0.0662 | 2.6 |
| 6 | 8 | 500 | 74.9 | 8.5 | 0.0260 | 39.4 |
| 6 | 8 | 1400 | 75.0 | 7.0 | 0.0081 | 99.9 |
| 8 | 6 | 250 | 75.1 | 12.7 | 0.0717 | 0.4 |
| 8 | 6 | 500 | 74.9 | 9.0 | 0.0278 | 26.9 |
| 8 | 6 | 1400 | 75.0 | 7.4 | 0.0086 | 99.8 |
| 12 | 4 | 250 | 74.9 | 13.9 | 0.0783 | 0.0 |
| 12 | 4 | 500 | 75.0 | 10.0 | 0.0311 | 12.7 |
| 12 | 4 | 1400 | 74.9 | 8.2 | 0.0097 | 99.9 |
The intercept spread falls as the length range widens. With six groups of eight it is 11.8 us for lengths 90 to 250 B, 8.5 us for 90 to 500 B, and 7.0 us for 90 to 1400 B. These are the figures quoted in Section 5.3 (7.0 us and 11.8 us). Over a 90 to 250 B range only 2.6 percent of fits meet the slope standard-error limit of 0.02 us/B used by the illustrative gate of Appendix C, against 99.9 percent over 90 to 1400 B.¶
Six lengths with K candidates per group; the baseline here is the mean of six groups of K candidates at 90 B, not the single 48-candidate minimum of Table B-1.¶
| Cand. per group | Budget | Output B SD | Fitted at 90 B SD | Baseline SD | Output B RMSE vs true | Baseline RMSE vs true |
|---|---|---|---|---|---|---|
| 1 | 6 | 25.8 | 23.6 | 14.4 | 79.5 | 108.2 |
| 2 | 12 | 15.8 | 14.4 | 8.9 | 76.3 | 107.8 |
| 4 | 24 | 10.0 | 9.1 | 5.6 | 75.5 | 107.6 |
| 8 | 48 | 6.5 | 5.9 | 3.6 | 75.4 | 107.4 |
| 16 | 96 | 4.3 | 3.9 | 2.5 | 75.2 | 107.5 |
| 32 | 192 | 3.0 | 2.7 | 1.6 | 75.1 | 107.4 |
The intercept spread stays between 1.77 and 1.81 times the baseline spread at every budget from 6 to 192 candidates; more candidates narrow both without changing the ratio. In every row the intercept has the smaller root-mean-square error against the true offset, because the baseline carries the 32.4 us length-dependent bias.¶
Each row changes the layer at which the length variable is counted, by adding symmetric overhead that the length variable does not include. The prediction is the slope (0.36 us/B) multiplied by the omitted overhead.¶
| Case | Intercept mean | Error vs 75 | Slope x overhead |
|---|---|---|---|
| L is effective length (as simulated) | 75.0 | -0.02 | 0.00 |
| L = NTP payload; +28 B IPv4/UDP both ways | 85.0 | 10.00 | 10.08 |
| L = UDP payload; +66 B IP+Ethernet framing both ways | 98.8 | 23.84 | 23.76 |
| L = NTP payload; +100 B tunnel+framing both ways | 110.9 | 35.93 | 36.00 |
The simulated errors match the prediction to within about 0.1 us, which supports Section 4.4: Output B is the intercept at zero of the documented layer, not at zero physical bytes.¶
This appendix reports the stress and sensitivity tests (test date 2026-10-23). Each scenario perturbs the nominal toy model in one way that Section 11.1 says an evaluation must cover. The results are sensitivities of this toy model, not predictions, and each scenario is a single run with a fixed seed.¶
Script: tare_stress_2026-10-23.py. It imports tare_core_2026-10-23.py from the same directory. Seed: 20261023. Trials: 10,000 per scenario; 25 scenarios. Command line: python3 -I tare_stress_2026-10-23.py OUTDIR. Outputs: tare_stress_estimators_2026-10-23.csv (150 rows, six estimators per scenario) and tare_stress_validity_2026-10-23.csv (25 rows). Table C-1 reproduces four of the six estimators; the baseline of one group of eight and the OLS fitted value at 90 B are in the CSV only.¶
base6: the matched baseline, the mean of six groups of eight candidates at 90 B (48 candidates). Expected value 107.4 us.¶
Output B (OLS): the zero-length intercept of the OLS line through six length groups of eight candidates (48 candidates). Expected value 75 us.¶
Theil-Sen: the zero-length intercept of a Theil-Sen line through the same samples. Expected value 75 us.¶
OLS plus time term: the zero-length intercept of the model of Section 4.3 with a first-order time term. Expected value 75 us.¶
Illustrative validity gate (test settings, not recommendations): at least five accepted groups, slope standard error at most 0.02 us/B, and a quadratic-term p-value of at least 0.01.¶
A fit is bad when Output B is more than 25 us from 75 us, about 3.8 nominal standard deviations. The false-valid rate is the fraction of all trials in which the gate accepted a bad fit.¶
Exchanges are in sequential order unless the scenario says randomized.¶
| Scenario | base6 | Output B (OLS) | Theil-Sen | OLS + time term |
|---|---|---|---|---|
| nominal | 107.4 (3.6) | 75.0 (6.6) | 75.0 (6.9) | 75.0 (45.4) |
| drift 0.1 ppm, sequential order | 107.4 (3.7) | 73.0 (6.5) | 72.9 (6.8) | 74.3 (45.3) |
| drift 1 ppm, sequential order | 107.4 (3.8) | 54.7 (6.8) | 54.5 (7.3) | 75.5 (45.1) |
| drift 5 ppm, sequential order | 107.4 (5.9) | -27.0 (10.7) | -27.7 (12.7) | 75.2 (43.3) |
| drift 1 ppm, randomized order | 107.4 (6.4) | 75.1 (12.0) | 75.1 (13.8) | 75.0 (8.3) |
| drift 5 ppm, randomized order | 107.3 (26.9) | 75.4 (51.0) | 75.3 (60.1) | 75.1 (8.2) |
| path step +50 us mid-window, sequential | 132.9 (15.3) | 79.0 (20.6) | 82.3 (22.4) | 98.3 (92.7) |
| path step +50 us mid-window, randomized | 133.1 (17.0) | 100.5 (21.7) | 100.8 (24.2) | 100.6 (21.7) |
| shaper: +40 us forward for L>=1100 B | 107.5 (3.6) | 69.6 (6.6) | 70.5 (7.4) | 56.1 (52.0) |
| quadratic forward term, +30 us at 1400 B | 107.4 (3.7) | 72.4 (6.6) | 72.6 (6.9) | 66.5 (44.6) |
| fragmentation at >=1300 B (+30 us, +20 B hdr) | 107.4 (3.7) | 70.3 (6.5) | 71.4 (6.9) | 55.6 (56.6) |
| iid packet loss 20% | 107.4 (4.3) | 75.0 (7.7) | 75.0 (7.9) | 74.7 (51.1) |
| size-dependent loss 2%..32% | 107.3 (3.8) | 74.9 (7.1) | 74.9 (7.4) | 75.0 (50.4) |
| length-label noise 10% | 107.4 (3.7) | 96.1 (52.5) | 79.7 (28.2) | 174.0 (119.9) |
| queue asymmetry fwd 150 us / rev 20 us | 112.6 (4.8) | 80.2 (8.8) | 79.4 (8.9) | 80.2 (57.3) |
| length-dependent forward queue (x2 at 700 B) | 107.6 (3.9) | 74.9 (8.1) | 74.9 (8.2) | 74.3 (62.1) |
| outliers 5% (mean +2 ms, one direction) | 107.4 (3.8) | 75.0 (6.8) | 75.0 (7.1) | 75.7 (46.3) |
| outliers 30% | 107.4 (4.8) | 75.0 (8.7) | 75.0 (8.9) | 74.7 (57.4) |
| symmetric encapsulation +66 B (L = payload) | 131.2 (3.6) | 98.8 (6.5) | 98.8 (6.9) | 98.8 (45.0) |
| forward-only tunnel +50 B | 127.4 (3.6) | 95.0 (6.6) | 95.0 (6.9) | 94.7 (42.8) |
| NTPv4-style fixed 90 B response | 107.4 (3.6) | 71.3 (6.6) | 71.4 (6.9) | 71.0 (46.6) |
| server rx timestamp lag 0.01 us/B | 107.8 (3.7) | 75.1 (6.6) | 75.1 (6.9) | 75.2 (44.3) |
| adversary: fwd delay 0.05 us/B on every packet | 109.7 (3.6) | 75.0 (6.5) | 75.0 (6.9) | 74.7 (45.4) |
| adversary: +200 us fwd on 90 B packets only | 207.4 (3.6) | 124.1 (6.5) | 88.8 (12.4) | -24.3 (153.5) |
| adversary: +200 us fwd on 1400 B packets only | 107.4 (3.7) | 53.1 (6.6) | 68.5 (8.4) | -8.8 (156.6) |
| Scenario | Rejected (%) | Bad fits (%) | False valid (%) | Accepted mean error vs 75 (us) | Mean slope (us/B) |
|---|---|---|---|---|---|
| nominal | 1.1 | 0.1 | 0.1 | -0.0 | 0.360 |
| drift 0.1 ppm, sequential order | 0.9 | 0.1 | 0.1 | -2.0 | 0.363 |
| drift 1 ppm, sequential order | 1.4 | 22.9 | 22.5 | -20.3 | 0.389 |
| drift 5 ppm, sequential order | 12.3 | 100.0 | 87.6 | -101.9 | 0.508 |
| drift 1 ppm, randomized order | 11.1 | 3.4 | 3.1 | 0.1 | 0.360 |
| drift 5 ppm, randomized order | 99.0 | 63.6 | 0.8 | -2.1 | 0.359 |
| path step +50 us mid-window, sequential | 14.4 | 19.2 | 16.2 | 3.8 | 0.391 |
| path step +50 us mid-window, randomized | 48.6 | 51.7 | 27.2 | 26.2 | 0.360 |
| shaper: +40 us forward for L>=1100 B | 1.6 | 0.3 | 0.3 | -5.5 | 0.378 |
| quadratic forward term, +30 us at 1400 B | 1.3 | 0.2 | 0.2 | -2.6 | 0.371 |
| fragmentation at >=1300 B (+30 us, +20 B hdr) | 3.2 | 0.2 | 0.2 | -4.7 | 0.372 |
| iid packet loss 20% | 1.8 | 0.4 | 0.3 | 0.0 | 0.360 |
| size-dependent loss 2%..32% | 1.7 | 0.1 | 0.1 | -0.1 | 0.360 |
| length-label noise 10% | 45.5 | 31.4 | 0.6 | 0.1 | 0.330 |
| queue asymmetry fwd 150 us / rev 20 us | 3.6 | 2.2 | 1.7 | 5.0 | 0.360 |
| length-dependent forward queue (x2 at 700 B) | 4.6 | 0.4 | 0.4 | -0.1 | 0.362 |
| outliers 5% (mean +2 ms, one direction) | 1.1 | 0.1 | 0.1 | 0.0 | 0.360 |
| outliers 30% | 3.0 | 0.9 | 0.7 | -0.0 | 0.360 |
| symmetric encapsulation +66 B (L = payload) | 0.9 | 42.0 | 41.7 | 23.8 | 0.360 |
| forward-only tunnel +50 B | 1.2 | 21.4 | 21.1 | 20.0 | 0.360 |
| NTPv4-style fixed 90 B response | 0.9 | 0.2 | 0.2 | -3.7 | 0.400 |
| server rx timestamp lag 0.01 us/B | 1.1 | 0.1 | 0.1 | 0.1 | 0.365 |
| adversary: fwd delay 0.05 us/B on every packet | 1.1 | 0.1 | 0.1 | 0.0 | 0.385 |
| adversary: +200 us fwd on 90 B packets only | 99.96 | 99.98 | 0.0 | 41.8 | 0.313 |
| adversary: +200 us fwd on 1400 B packets only | 99.4 | 30.9 | 0.1 | -20.5 | 0.416 |
Sequential-order drift. A drift of 1 ppm moves Output B by -20.3 us and the gate accepts a bad fit in 22.5 percent of trials; the gate rejects only 1.4 percent of fits (Sections 4.3 and 7). At 5 ppm the shift is -102.0 us. The mean slope rises from 0.360 to 0.389 us/B at 1 ppm.¶
Randomized order removes that bias (Output B mean 75.1 us at 1 ppm) but raises the spread from 6.6 us to 12.0 us. At 5 ppm randomized the spread is 51.0 us and the gate rejects 99.0 percent of fits.¶
The time-term model is unbiased under drift in both orders (means 75.5 and 75.0 us at 1 ppm). In sequential order the time term is nearly collinear with length and the spread is 45.4 us at nominal; in randomized order at 1 ppm it is 8.3 us.¶
Path step. A 50 us step in the middle of the window shifts every estimator by about 25 us in randomized order (Output B mean 100.5 us, base6 133.1 us). The gate rejects 48.6 percent of fits and the false-valid rate is 27.2 percent.¶
Size-dependent behaviour. A 40 us shaper step for lengths of 1100 B and above, a 30 us quadratic term at 1400 B, and fragmentation at 1300 B and above move Output B by -5.4, -2.6, and -4.7 us. The gate rejects 1.6, 1.3, and 3.2 percent of fits, so these steps are mostly undetected (Section 7). The shifts are below the nominal spread of 6.6 us.¶
Packet loss. Independent loss of 20 percent and size-dependent loss from 2 to 32 percent add no bias; Output B spread rises to 7.7 and 7.1 us.¶
Length-label noise. With 10 percent of length labels wrong, Output B averages 96.1 us with spread 52.5 us. Theil-Sen is less affected (79.7 us, spread 28.2 us). The gate rejects 45.5 percent of fits.¶
Queueing asymmetry and outliers. Forward and reverse queue means of 150 and 20 us shift every estimator by about +5 us (Output B 80.2 us). Outliers at 5 and 30 percent add no bias (Output B spread 6.8 and 8.7 us). A forward queue that grows with length (twice the mean at 700 B) leaves Output B at 74.9 us.¶
Encapsulation. A symmetric 66 B overhead outside the counted length shifts Output B, the baseline, and the fitted value alike by about 23.8 us, and a forward-only 50 B tunnel by about 20.0 us. The gate rejects about 0.9 and 1.2 percent, and the false-valid rates are 41.7 and 21.1 percent.¶
Server behaviour. When the response length is fixed at 90 B while the request length varies, the fitted slope is 0.400 us/B instead of 0.360 and Output B is 71.3 us (Section 4.1). A receive-timestamp lag of 0.01 us/B moves the mean slope to 0.365 us/B and Output B to 75.1 us, against 107.8 us for base6.¶
Adversarial delay. Forward delay of 0.05 us/B on every packet leaves Output B at 75.0 us and moves base6 to 109.7 us. Adding 200 us of forward delay to 90 B packets only moves Output B by +49.1 us and base6 by +100.0 us. Adding it to 1400 B packets only moves Output B by -21.9 us and leaves base6 at 107.4 us. The gate rejects 99.96 and 99.4 percent of fits in those two cases (Section 9.1). An adversary that knows the length schedule is evaluated in Section D.7.¶
Section 4.4 states that the illustrative gate does not detect a length variable that omits overhead. Tables C-1 and C-2 cover one case (66 B). This section repeats the test for 28 B and 100 B and adds a control with no overhead. Script: tare_supplement_2026-10-24.py (Section E.2). Seed: 20261024. Trials: 10,000 per row. The gate and the 25 us threshold for a bad fit are those of Section C.1. The overhead is symmetric and lies outside the counted length.¶
| Overhead (B) | Predicted shift (us) | Output B error vs 75 (us) | Spread (us) | Gate rejected (%) | More than 25 us off (%) | False valid (%) |
|---|---|---|---|---|---|---|
| 0 | 0.0 | 0.0 | 6.5 | 1.1 | 0.1 | 0.1 |
| 28 | 10.1 | 10.1 | 6.6 | 0.9 | 1.6 | 1.6 |
| 66 | 23.8 | 23.7 | 6.6 | 1.0 | 41.8 | 41.4 |
| 100 | 36.0 | 35.9 | 6.5 | 1.0 | 95.3 | 94.4 |
Predicted shift is the slope (0.36 us/B) times the overhead. At 28 B the shift is below the 25 us threshold, so the false-valid rate says little there; the gate rejection rate is the informative column.¶
The gate rejects 0.9, 1.0, and 1.0 percent of fits at 28, 66, and 100 B, against 1.1 percent with no overhead. The rejection rate does not respond to the overhead, because the added delay is linear in the counted length and so enters the intercept without changing the fit quality.¶
The mean errors (10.1, 23.7, and 35.9 us) match the predicted shifts (10.1, 23.8, and 36.0 us), and the fitted slope is unchanged at 0.360 us/B.¶
This appendix reports a variant that the body of this document does not specify: the slope is estimated from many pooled calibration windows, and the offset is a single minimum-delay sample at 90 B corrected by that slope. It is reported as an evaluated alternative to the single-window intercept of Section 5, so that its behaviour can be compared under the same toy model and the same impairments. Sections 5 through 7 do not require it.¶
Calibration: M = 20 windows, pooled. Each window has six lengths, two replicate groups per length, and four candidates per group (48 candidates); the minimum-delay candidate of each group is kept. Order within a window is randomized unless a scenario says otherwise.¶
Slope: the pooled OLS slope b_hat over all 12 x M selected points.¶
Offset (hybrid): one minimum-delay sample of 48 candidates at 90 B, minus b_hat x 90. No intercept is extrapolated: slope error is multiplied by 90 B, not by the leverage of the fit.¶
Gate: a pooled lack-of-fit F-test against the pure error of the replicates (reject when p < 0.01) AND slope significance, |b_hat| >= 3 standard errors. When the gate fails the estimator falls back to the plain 90 B minimum-delay sample of 48 candidates.¶
Budget accounting: the calibration costs 20 x 48 = 960 candidates, amortized over R = 96 offset estimates, which adds 10 candidates per estimate. The fully loaded baseline is therefore a minimum-delay sample of 58 candidates (base58).¶
Comparators: base58, and the single-window OLS intercept of Section 5 (48 candidates, with and without the illustrative gate of Appendix C).¶
False valid: the gate passed and the estimate is more than 25 us from 75 us. For the single-window comparator, the original gate accepted a fit that is more than 25 us from 75 us.¶
Packet-loss, delay-confined-to-90 B, and schedule-aware adversary scenarios, which were not run on 2026-10-23, are reported in Section D.7.¶
Script: tare_hybrid_2026-10-23.py. It imports tare_core_2026-10-23.py from the same directory. Seed: 20261023. Trials: 5,000 per scenario (2,500 for the pooling-depth experiment). Command line: python3 -I tare_hybrid_2026-10-23.py OUTDIR. Outputs, each with the suffix _2026-10-23.csv: tare_hybrid_estimators (per-estimator distribution summaries, not reproduced here), tare_hybrid_validity, tare_hybrid_slope_sweep, tare_hybrid_power, tare_hybrid_pooling_depth, and tare_hybrid_leverage. Dependencies: numpy, scipy, and pandas.¶
Error columns. The base58 error is measured against 107.4 us, the expected value of a 90 B sample. The hybrid and single-window OLS errors are measured against 75 us. Against the true offset (0 us) the nominal values are 107.4 us for the baseline and 75 us for the other two; the fixed 75 us propagation asymmetry is not removed by any of them.¶
| Scenario | base58 | Hybrid | Hybrid fallback | Hybrid false valid |
|---|---|---|---|---|
| nominal | -0.0 (3.0) | 0.1 (3.2) | 0.9 | 0.0 |
| drift 1 ppm, sequential (neg. control) | -0.1 (16.9) | -1.4 (14.2) | 0.1 | 3.8 |
| drift 1 ppm, randomized | 0.1 (16.8) | -0.0 (14.3) | 1.1 | 3.1 |
| drift 5 ppm, randomized | -0.8 (83.3) | -0.4 (69.1) | 1.4 | 77.8 |
| path step +50 us, randomized | 25.4 (25.2) | 25.2 (25.2) | 0.1 | 50.3 |
| path step +50 us, sequential (neg. control) | 25.0 (25.2) | 24.3 (25.2) | 0.0 | 51.4 |
| shaper +10 us fwd for L>=1100 | 0.0 (3.0) | -0.4 (3.2) | 5.1 | 0.0 |
| shaper +40 us fwd for L>=1100 | 0.0 (2.9) | -1.5 (3.2) | 97.9 | 0.0 |
| quadratic fwd term +5 us at 1400 B | 0.0 (2.9) | -0.2 (3.2) | 1.0 | 0.0 |
| quadratic fwd term +30 us at 1400 B | 0.0 (2.9) | -1.0 (3.2) | 6.7 | 0.0 |
| fragmentation at >=1300 B | -0.0 (2.9) | -1.1 (3.2) | 99.96 | 0.0 |
| length-label noise 10% | 0.0 (2.9) | 3.5 (3.4) | 0.5 | 0.0 |
| symmetric +66 B overhead (L=payload) | 23.8 (2.9) | 23.8 (3.3) | 0.9 | 31.9 |
| forward-only tunnel +50 B | 20.0 (3.0) | 19.9 (3.2) | 1.0 | 5.7 |
| NTPv4-style fixed 90 B response | 0.0 (2.9) | -3.6 (3.2) | 1.1 | 0.0 |
| queue asymmetry fwd150/rev20 | 0.4 (3.3) | 0.6 (3.8) | 1.0 | 0.0 |
| length-dependent fwd queue (x2 at 700 B) | 0.1 (3.1) | -0.5 (3.4) | 1.4 | 0.0 |
| outliers 5% (mean +2 ms) | -0.0 (3.0) | 0.0 (3.3) | 0.8 | 0.0 |
| adversary: fwd delay 0.05 us/B, every packet | 2.4 (2.9) | 0.0 (3.2) | 1.2 | 0.0 |
| adversary: +20 us fwd on 1400 B only | 0.0 (2.9) | -0.5 (3.2) | 43.3 | 0.0 |
| adversary: +200 us fwd on 1400 B only | 0.0 (2.9) | -5.1 (3.2) | 100.0 | 0.0 |
Hybrid fallback is the share of trials in which the lack-of-fit or slope test failed.¶
| Scenario | OLS single window | OLS false valid |
|---|---|---|
| nominal | 0.0 (6.6) | 0.1 |
| drift 1 ppm, sequential (neg. control) | -20.4 (6.8) | 23.7 |
| drift 1 ppm, randomized | 0.0 (12.2) | 3.6 |
| drift 5 ppm, randomized | -0.4 (50.0) | 0.6 |
| path step +50 us, randomized | 25.6 (21.9) | 27.8 |
| path step +50 us, sequential (neg. control) | 4.2 (20.6) | 16.3 |
| shaper +10 us fwd for L>=1100 | -1.4 (6.5) | 0.1 |
| shaper +40 us fwd for L>=1100 | -5.4 (6.5) | 0.2 |
| quadratic fwd term +5 us at 1400 B | -0.4 (6.6) | 0.1 |
| quadratic fwd term +30 us at 1400 B | -2.6 (6.5) | 0.1 |
| fragmentation at >=1300 B | -4.8 (6.3) | 0.1 |
| length-label noise 10% | 22.4 (53.9) | 0.5 |
| symmetric +66 B overhead (L=payload) | 23.8 (6.5) | 40.8 |
| forward-only tunnel +50 B | 20.0 (6.7) | 21.2 |
| NTPv4-style fixed 90 B response | -3.7 (6.7) | 0.2 |
| queue asymmetry fwd150/rev20 | 5.1 (8.6) | 1.6 |
| length-dependent fwd queue (x2 at 700 B) | -0.0 (8.1) | 0.3 |
| outliers 5% (mean +2 ms) | -0.2 (6.7) | 0.0 |
| adversary: fwd delay 0.05 us/B, every packet | -0.0 (6.5) | 0.1 |
| adversary: +20 us fwd on 1400 B only | -2.2 (6.6) | 0.1 |
| adversary: +200 us fwd on 1400 B only | -21.8 (6.7) | 0.2 |
Nominal. The hybrid error is +0.07 us with spread 3.21 us, against 2.99 us for the fully loaded baseline and 6.57 us for the single-window OLS intercept. Relative to base58 the hybrid adds about 8 percent to the spread while removing the 32.4 us length-dependent bias.¶
Drift. In randomized order at 1 ppm the hybrid spread is 14.3 us, against 16.8 us for base58 and 12.2 us for the single-window OLS. The sequential-order scenario is not a like-for-like control for the hybrid: its 12-group layout repeats the six lengths twice per window, whereas the single-window comparator uses six groups in sequence, so the hybrid error there (-1.4 us), much smaller than the single-window error (-20.4 us), is not evidence that pooling removes the drift confound; the layout effect was not isolated.¶
Path step. A 50 us step is not removed: the hybrid error is +25.2 us, the same as the baseline, and the false-valid rate is 50.3 percent.¶
Size-dependent behaviour. The lack-of-fit test rejects 97.9 percent of calibrations for a 40 us shaper step and 99.96 percent for fragmentation, where the single-window gate rejects 1.6 and 2.9 percent. A 30 us quadratic term is detected in only 6.7 percent.¶
Encapsulation. Overhead outside the counted length is not detected by either gate: a symmetric 66 B overhead shifts the hybrid by +23.8 us (false-valid 31.9 percent, single window 40.8 percent). The shift is just below the 25 us threshold, so the false-valid rate reflects the spread of each estimator more than the size of its bias.¶
Length-label noise. The hybrid error is +3.5 us with spread 3.4 us, against +22.4 us and 53.9 us for the single-window OLS.¶
Adversarial delay. A forward delay of 0.05 us/B on every packet leaves the hybrid at +0.002 us and moves base58 by +2.35 us. Delay of 200 us confined to 1400 B packets is rejected by the lack-of-fit test in 100.0 percent of calibrations.¶
The true slope is varied by changing the reverse-link serialization time; the forward link is unchanged. The expected value of a 90 B sample is 75 us plus 90 B times the slope, which is the target of the baseline. The hybrid targets 75 us at every slope.¶
| True slope (us/B) | 90 B sample target | base58 | Hybrid | Hybrid fallback | OLS single window |
|---|---|---|---|---|---|
| 0.00 | 75.0 | 0.1 (2.9) | -0.0 (3.2) | 99.8 | -0.1 (6.7) |
| 0.02 | 76.8 | -0.0 (2.9) | -0.0 (3.2) | 0.8 | -0.0 (6.6) |
| 0.05 | 79.5 | -0.0 (2.9) | 0.1 (3.2) | 1.0 | -0.1 (6.5) |
| 0.10 | 84.0 | 0.0 (2.9) | 0.0 (3.3) | 1.1 | 0.0 (6.5) |
| 0.20 | 93.0 | -0.0 (2.9) | -0.0 (3.2) | 1.0 | 0.0 (6.4) |
| 0.36 | 107.4 | -0.0 (3.0) | -0.0 (3.2) | 0.9 | 0.0 (6.5) |
At a true slope of zero the slope test fails in 99.8 percent of calibrations and the hybrid falls back to the plain baseline, which is the intended behaviour when there is nothing to correct. At the smallest non-zero slope tested (0.02 us/B, a 1.8 us difference at 90 B) the fallback rate is 0.8 percent, so the slope is detected. As the slope grows the baseline target moves from 75 to 107.4 us while the hybrid stays at 75 us.¶
| Impairment | Lack-of-fit rejection | Hybrid error | OLS error | OLS gate rejection |
|---|---|---|---|---|
| shaper us at >=1100 B = 2 | 1.0 | -0.12 | -0.38 | 1.1 |
| shaper us at >=1100 B = 5 | 1.3 | -0.15 | -0.54 | 1.1 |
| shaper us at >=1100 B = 10 | 5.2 | -0.49 | -1.42 | 0.9 |
| shaper us at >=1100 B = 20 | 32.3 | -0.74 | -2.72 | 1.0 |
| shaper us at >=1100 B = 40 | 98.0 | -1.58 | -5.35 | 1.9 |
| quadratic us at 1400 B = 2 | 0.8 | -0.03 | -0.15 | 1.2 |
| quadratic us at 1400 B = 5 | 1.0 | -0.17 | -0.34 | 0.9 |
| quadratic us at 1400 B = 10 | 1.2 | -0.31 | -0.67 | 1.1 |
| quadratic us at 1400 B = 30 | 5.7 | -0.91 | -2.62 | 1.2 |
| adv us on 1400 B only = 2 | 1.2 | -0.05 | -0.22 | 1.1 |
| adv us on 1400 B only = 5 | 1.8 | -0.14 | -0.49 | 1.3 |
| adv us on 1400 B only = 10 | 6.6 | -0.33 | -1.00 | 1.2 |
| adv us on 1400 B only = 20 | 42.8 | -0.57 | -2.32 | 1.3 |
| adv us on 1400 B only = 50 | 100.0 | -1.25 | -5.56 | 3.4 |
| adv us on 1400 B only = 200 | 100.0 | -5.03 | -21.90 | 99.3 |
The rejection rate with a 2 us impairment is 1.0 percent, close to the 1 percent test level. Rejection reaches 32.3 percent for a 20 us shaper step and 98.0 percent for 40 us. For delay confined to 1400 B it is 42.8 percent at 20 us and 100.0 percent at 50 us. The quadratic term is the weakest case, at 5.7 percent for 30 us. Where rejection is below roughly one half, the hybrid error is under one microsecond in magnitude and smaller than the single-window error in every row.¶
| M | Cand. | Slope mean (us/B) | Slope SD (us/B) | Hybrid mean (us) | Hybrid SD (us) | base48 SD (us) | False reject (%) |
|---|---|---|---|---|---|---|---|
| 5 | 240 | 0.3600 | 0.0039 | 75.0 | 3.21 | 3.19 | 0.8 |
| 10 | 480 | 0.3600 | 0.0027 | 75.0 | 3.23 | 3.22 | 0.9 |
| 20 | 960 | 0.3600 | 0.0020 | 75.1 | 3.26 | 3.26 | 0.7 |
| 40 | 1920 | 0.3600 | 0.0014 | 75.0 | 3.30 | 3.29 | 1.0 |
Cand. is the number of calibration candidates, 48 x M.¶
The slope spread falls with the square root of M. At M = 20 it is 0.0020 us/B, which multiplied by 90 B adds about 0.18 us in quadrature; the hybrid spread (3.26 us) is therefore almost the spread of the 48-candidate baseline (3.26 us). The lack-of-fit test falsely rejects 0.7 to 1.0 percent of nominal calibrations at the 1 percent level.¶
| Length (B) | Single-window intercept | Hybrid correction |
|---|---|---|
| 90 | 0.4916 | -0.0424 |
| 250 | 0.4050 | -0.0311 |
| 500 | 0.2696 | -0.0134 |
| 800 | 0.1071 | 0.0078 |
| 1100 | -0.0554 | 0.0290 |
| 1400 | -0.2179 | 0.0502 |
| sum of |weights| | 1.5465 | 0.1738 |
If an attacker shifts the measured offset of one length class, the single-window intercept moves by up to 1.55 times the largest shift (Section 9.1). The correction applied by the hybrid moves by up to 0.17 times, because the slope error is multiplied by 90 B rather than by the leverage of the fit. The hybrid output also carries a weight of one on its 90 B offset sample, so delay confined to 90 B packets affects it as it affects the baseline; that case is reported in Section D.7.¶
This section reports three cases that were not run on 2026-10-23: packet loss, delay confined to 90 B packets, and an adversary that knows the length schedule. Script: tare_supplement_2026-10-24.py (Section E.2). Seed: 20261024. Trials: 5,000 per scenario. The design is that of Section D.1, except that the pooled fit gives lost candidates zero weight, so loss can be modelled. Errors are measured as in Table D-1.¶
The schedule-aware adversary adds forward delay s x (L - 90) to every packet of length L bytes, with s of 0.2, 0.5, and 1 us/B. The added delay is zero at 90 B and exactly linear in length. It changes a measured offset by half the one-way delay, so an estimator that takes its slope from the fit and its offset from the 90 B sample, or from the zero-length intercept, is predicted to shift by -45 x s us. The predicted shift for the 90 B-only cases is half the added delay.¶
| Scenario | base58 | Hybrid | Hybrid fallback | Hybrid false valid | Predicted shift |
|---|---|---|---|---|---|
| nominal (control) | -0.0 (2.9) | -0.0 (3.2) | 0.8 | 0.0 | - |
| iid packet loss 20% | -0.0 (3.3) | 0.1 (3.6) | 1.0 | 0.0 | - |
| size-dependent loss 2%..32% | 0.0 (3.0) | 0.0 (3.3) | 1.1 | 0.0 | - |
| +5 us fwd on 90 B packets only | 2.5 (2.9) | 2.6 (3.2) | 2.2 | 0.0 | 2.5 |
| +20 us fwd on 90 B packets only | 10.0 (2.9) | 10.4 (3.2) | 56.8 | 0.0 | 10.0 |
| +200 us fwd on 90 B packets only | 100.0 (2.9) | 104.2 (3.2) | 100.0 | 0.0 | 100.0 |
| schedule-aware: fwd delay 0.2 us/B x (L-90) | -0.1 (3.0) | -9.0 (3.3) | 0.5 | 0.0 | -9.0 |
| schedule-aware: fwd delay 0.5 us/B x (L-90) | -0.0 (3.0) | -22.5 (3.2) | 0.8 | 19.5 | -22.5 |
| schedule-aware: fwd delay 1 us/B x (L-90) | 0.0 (2.9) | -45.0 (3.2) | 1.0 | 99.0 | -45.0 |
Predicted shift applies to the hybrid and to the single-window OLS intercept for the schedule-aware rows, and to the baseline and the hybrid before fallback for the 90 B-only rows.¶
| Scenario | OLS single window | OLS false valid |
|---|---|---|
| nominal (control) | 0.1 (6.7) | 0.1 |
| iid packet loss 20% | 0.1 (7.6) | 0.3 |
| size-dependent loss 2%..32% | -0.1 (7.1) | 0.1 |
| +5 us fwd on 90 B packets only | 1.3 (6.5) | 0.1 |
| +20 us fwd on 90 B packets only | 5.1 (6.7) | 0.3 |
| +200 us fwd on 90 B packets only | 49.2 (6.6) | 0.1 |
| schedule-aware: fwd delay 0.2 us/B x (L-90) | -8.9 (6.5) | 0.9 |
| schedule-aware: fwd delay 0.5 us/B x (L-90) | -22.5 (6.6) | 34.3 |
| schedule-aware: fwd delay 1 us/B x (L-90) | -44.9 (6.5) | 98.7 |
Packet loss. With the loss-aware fit, 20 percent independent loss and size-dependent loss from 2 to 32 percent leave the hybrid error at +0.06 and +0.04 us, with spread 3.6 and 3.3 us against 3.2 us in the nominal control. The fallback rate is 1.0 and 1.1 percent, against 0.8 percent.¶
Delay confined to 90 B packets. The hybrid takes its offset from a 90 B sample, so it inherits this delay as the baseline does. Forward delay of 5, 20, and 200 us on 90 B packets only moves base58 by +2.5, +10.0, and +100.0 us, and the hybrid before any fallback by +2.6, +10.4, and +104.2 us. The lack-of-fit test rejects 2.2, 56.8, and 100.0 percent of calibrations. When it rejects, the hybrid falls back to the plain 90 B sample, which carries the same shift as base58, so the gate flags the condition but does not remove the error. The single-window OLS intercept moves by +1.3, +5.1, and +49.2 us.¶
Schedule-aware adversary. The hybrid moves by -9.0, -22.5, and -45.0 us for s of 0.2, 0.5, and 1 us/B (predicted -9.0, -22.5, and -45.0 us), and the single-window OLS intercept by -8.9, -22.5, and -44.9 us. The 90 B baseline moves by at most 0.05 us, which is within sampling noise. The hybrid fallback rate is 0.5, 0.8, and 1.0 percent, against 0.8 percent at nominal, so the gate does not respond. The hybrid false-valid rate (more than 25 us from 75 us) is 0.0, 19.5, and 99.0 percent.¶
Cost to the adversary. For s = 0.5 us/B the longest packets (1400 B) are delayed by about 655 us and the 90 B packets are not delayed. A test for departure from linearity cannot separate delay of this form from a real length-dependent serialization effect, because the delay enters the fitted slope. The hybrid and the single-window intercept share this weakness; the plain 90 B baseline does not have it, since it never uses the slope. Detecting it would need information outside the fit, such as a bound on a physically plausible slope for the path.¶
This appendix lists every numerical result quoted in the body of this document and the table in this document that supports it, so that a reader can check each figure against the data. Every row was checked against the CSV outputs when this revision was prepared.¶
| Section | Figure quoted in the text | Supporting table | Value in the data |
|---|---|---|---|
| 4.1 | request-only slope 0.400 against 0.360 us/B | Table C-2, NTPv4-style fixed 90 B response | 0.400 |
| 4.1 | nominal slope 0.360 us/B | Table C-2, nominal | 0.360 |
| 4.2 | Output A and ordinary sample 107.4 us | Table B-1 (48 candidates) | 107.4 and 107.4 |
| 4.2 | (second value of the pair) | Table B-1 (48 candidates) | 107.4 |
| 4.2 | fixed propagation asymmetry 75 us | Table B-1, Output B | 75.0 |
| 4.3 | 1 ppm sequential drift shifts Output B by about -20 us | Table C-1 / C-2, drift 1 ppm sequential | -20.3 |
| 4.3 | gate rejected 1.4% of such fits | Table C-2, drift 1 ppm sequential | 1.4% |
| 4.4 | overhead 28 B retained as about +10 us | Table B-5 | 10.0 |
| 4.4 | overhead 66 B retained as about +24 us | Table B-5 | 23.8 |
| 4.4 | overhead 100 B retained as about +36 us | Table B-5 | 35.9 |
| 4.4 | gate did not detect the 66 B case | Table C-2, symmetric encapsulation +66 B (rejected) | 0.9% |
| 4.4 | gate did not detect 28 B overhead (rejection near the no-overhead rate) | Table C-3 | 0.9% vs 1.1% |
| 4.4 | gate did not detect 66 B overhead (rejection near the no-overhead rate) | Table C-3 | 1.0% vs 1.1% |
| 4.4 | gate did not detect 100 B overhead (rejection near the no-overhead rate) | Table C-3 | 1.0% vs 1.1% |
| 9.1 | schedule-aware delay s = 0.5 us/B moves the hybrid by about -22.5 us | Table D-6 | -22.5 |
| 9.1 | ...and the 90 B baseline does not move | Table D-6, base58 | -0.02 |
| 9.1 | ...without the fallback rate rising above nominal | Table D-6 | 0.8% vs 0.8% |
| 9.1 | longest packets delayed by about 655 us at s = 0.5 | arithmetic: 0.5 x (1400 - 90) | 655 |
| 5.3 | intercept SD 7.0 us, 90-1400 B, 48 exchanges | Table B-3, 6 groups, max 1400 B | 7.0 |
| 5.3 | intercept SD 11.8 us, 90-250 B | Table B-3, 6 groups, max 250 B | 11.8 |
| 7 | gate rejection for shaper within 1.3% to 3.2% | Table C-2 | 1.6% |
| 7 | gate rejection for curvature within 1.3% to 3.2% | Table C-2 | 1.3% |
| 7 | gate rejection for fragmentation within 1.3% to 3.2% | Table C-2 | 3.2% |
| 7 | sequential-order drift detected only at large values | Table C-2, drift 0.1, 1, 5 ppm sequential | 0.9% / 1.4% / 12.3% |
| 9.1 | intercept weight of the 90 B group +0.49 | Table B-2 | +0.4916 |
| 9.1 | intercept weight of the 250 B group +0.40 | Table B-2 | +0.4050 |
| 9.1 | intercept weight of the 500 B group +0.27 | Table B-2 | +0.2696 |
| 9.1 | intercept weight of the 800 B group +0.11 | Table B-2 | +0.1071 |
| 9.1 | intercept weight of the 1100 B group -0.06 | Table B-2 | -0.0554 |
| 9.1 | intercept weight of the 1400 B group -0.22 | Table B-2 | -0.2179 |
| 9.1 | sum of absolute weights about 1.55 | Table B-2 | 1.5465 |
| 9.1 | one-way delay bound about 0.77 d | Table B-2 (1.5465 / 2) | 0.773 |
| 9.1 | 200 us on 1400 B only moves Output B by -21.9 us | Table C-1 | -21.9 |
| 9.1 | ...and leaves the 90 B baseline unchanged | Table C-1, base6 | -0.0 |
| 9.1 | 200 us on 90 B only moves Output B by about +49 us | Table C-1 | +49.1 |
| 9.1 | ...and the baseline by +100 us | Table C-1, base6 | +100.0 |
Scripts, seeds, and outputs. Every output file name carries the test date of its script as a suffix (_2026-10-23.csv, or _2026-10-24.csv for the supplementary script), which is omitted below.¶
tare_monte_carlo_2026-10-23.py: seed 20261022; 10,000 trials; output tare_monte_carlo_results.¶
tare_matched_budget_2026-10-23.py: seed 20261023; 10,000 trials; outputs tare_E1_matched_budget, tare_E1_analytic_checks, tare_E2_design_sweep, tare_E2b_budget_sweep, and tare_E4_length_zero_meaning.¶
tare_stress_2026-10-23.py: seed 20261023; 10,000 trials per scenario; outputs tare_stress_estimators and tare_stress_validity.¶
tare_hybrid_2026-10-23.py: seed 20261023; 5,000 trials per scenario; outputs tare_hybrid_estimators, tare_hybrid_validity, tare_hybrid_slope_sweep, tare_hybrid_power, tare_hybrid_pooling_depth, and tare_hybrid_leverage.¶
tare_supplement_2026-10-24.py: seed 20261024; 10,000 trials per gate row and 5,000 per hybrid scenario; outputs tare_supplement_gate and tare_supplement_hybrid.¶
tare_core_2026-10-23.py: the shared model imported by the matched-budget, stress, hybrid, and supplementary scripts; it has no seed and no output file.¶
The tables in this document were produced from these CSV files. When this revision was prepared, the Monte Carlo, matched-budget (E1), stress, and hybrid validity and power scripts were rerun with Python 3.13.17, numpy 2.5.3, pandas 3.0.5, and SciPy 1.18.1, and reproduced the previously saved CSV files byte for byte. The remaining output files (the E1 analytic checks, E2, E2b, E4, and the hybrid estimators, slope sweep, pooling depth, and leverage files) were generated in that rerun.¶
The supplementary script of 2026-10-24 was run twice with the same seed and produced identical CSV files, using the same Python and package versions.¶
The scripts are reproduced in Appendix F, the output files in Appendix G, and the SHA-256 checksum of every file, with the reproduction procedure, in Appendix H.¶
This appendix reproduces, without change, the scripts that produced every result in Appendices A through E, so that this document is self-contained. The matched-budget, stress, hybrid, and supplementary scripts import tare_core_2026-10-23.py, which MUST be in the same directory as the script that imports it. Lines longer than 69 characters are folded as described in RFC 8792 (the double-backslash form), and each block that was folded begins with the header line that RFC requires. Appendix H gives the unfolding procedure and the SHA-256 checksum of each file. Extract the files from the XML or HTML form of this document, not from paginated text, because page breaks in the text form interrupt the blocks.¶
Shared toy model and estimators; imported by the matched-budget, stress, hybrid, and supplementary scripts (Appendices B through D).¶
========== NOTE: '\\' line wrapping per RFC 8792 ==========
#!/usr/bin/env python3
# TARE review core model (toy) -- test date: 2026-10-23
"""TARE review core model (toy). Test date: 2026-10-23.
Shared simulation and estimator code for the 2026-10-23 review tests\
\ of
draft-tare-offset-regression-00. This is a TOY model: it is not an N\
\TP
implementation and it is not real-network evidence.
Model (same physics as the supplied tare_monte_carlo.py):
measured offset error = BIAS0 + 0.5*(SER_F*Lf - SER_R*Lr) + 0.5*(q\
\f - qr) + extras
true clock offset = 0 (so an estimate IS its own error against\
\ the truth)
forward link 10 Mbps, reverse link 100 Mbps -> slope 0.36 us/byte
BIAS0 = 75 us (fixed propagation asymmetry of 150 us)
qf, qr: exponential queueing delays, mean 50 us unless a scenario \
\overrides
per length group: K candidate exchanges, keep the one with minimum\
\ qf+qr
"""
import warnings
import numpy as np
from scipy import stats
TEST_DATE = "2026-10-23"
RF, RR = 10e6, 100e6 # forward / reverse bottleneck \
\rates (bit/s)
SER_F = 8.0 / RF * 1e6 # us per byte, forward (0.8)
SER_R = 8.0 / RR * 1e6 # us per byte, reverse (0.08)
SLOPE = 0.5 * (SER_F - SER_R) # 0.36 us/byte
BIAS0 = 75.0 # us, fixed propagation-asymmet\
\ry offset
LENGTHS = np.array([90., 250., 500., 800., 1100., 1400.])
BASE_LEN = 90.0
DEFAULT = dict(
order="sequential", dt=1.0, drift_ppm=0.0, step_us=0.0,
shaper_us=0.0, shaper_from=1100.0, quad_us=0.0,
loss=0.0, loss_size=0.0, label_swap=0.0,
qf_mean=50.0, qr_mean=50.0, q_len_scale=0.0,
outlier_p=0.0, outlier_mean=2000.0,
frag_from=None, frag_delay=30.0,
overhead_sym=0.0, overhead_f=0.0, overhead_r=0.0, resp_fixed=Non\
\e,
ts_lag=0.0, adv_slope=0.0, adv_len=None, adv_us=0.0,
)
def simulate(p, rng, lengths, k, trials):
"""One calibration window per trial: len(lengths) groups of k ca\
\ndidate exchanges."""
q = {**DEFAULT, **p}
lengths = np.asarray(lengths, float)
g = len(lengths)
shape = (trials, g, k)
Lx = lengths.reshape(1, g, 1)
slots = np.arange(g * k) * q["dt"]
if q["order"] == "sequential":
t = np.broadcast_to(slots.reshape(1, g, k), shape)
else: # randomized interleaving of all exchanges
perm = np.argsort(rng.random((trials, g * k)), axis=1)
t = slots[perm].reshape(shape)
tc = slots.mean()
qf = rng.exponential(1.0, shape) * q["qf_mean"] * (1.0 + q["q_le\
\n_scale"] * Lx / 700.0)
qr = rng.exponential(1.0, shape) * q["qr_mean"]
if q["outlier_p"] > 0:
hit = rng.random(shape) < q["outlier_p"]
side = rng.random(shape) < 0.5
extra = rng.exponential(1.0, shape) * q["outlier_mean"] * hit
qf = qf + extra * side
qr = qr + extra * (~side)
Lf = Lx + q["overhead_sym"] + q["overhead_f"]
Lr = Lx + q["overhead_sym"] + q["overhead_r"]
if q["resp_fixed"] is not None: # NTPv4-style: respons\
\e length does not mirror request
Lr = np.zeros_like(Lx) + q["resp_fixed"] + q["overhead_sym"]\
\ + q["overhead_r"]
extra_f = np.zeros_like(Lx)
if q["shaper_us"]:
extra_f = extra_f + q["shaper_us"] * (Lx >= q["shaper_from"])
if q["quad_us"]:
extra_f = extra_f + q["quad_us"] * (Lx / 1400.0) ** 2
if q["frag_from"] is not None:
fr = (Lx >= q["frag_from"]).astype(float)
extra_f = extra_f + q["frag_delay"] * fr
Lf = Lf + 20.0 * fr
Lr = Lr + 20.0 * fr
extra_f = extra_f + q["ts_lag"] * Lx + q["adv_slope"] * Lx
if q["adv_len"] is not None:
extra_f = extra_f + q["adv_us"] * (Lx == q["adv_len"])
off = BIAS0 + 0.5 * (SER_F * Lf - SER_R * Lr) + 0.5 * (qf - qr) \
\+ 0.5 * extra_f
off = off + q["drift_ppm"] * (t - tc) # 1 ppm == 1 us/s\
\ of offset drift
if q["step_us"]:
tstep = slots[rng.integers(0, g * k, size=trials)].reshape(t\
\rials, 1, 1)
off = off + q["step_us"] * (t >= tstep)
key = qf + qr # what a min-dela\
\y filter can observe
p_lost = q["loss"] + q["loss_size"] * Lx / 1400.0
if np.any(p_lost > 0):
key = np.where(rng.random(shape) < p_lost, np.inf, key)
idx = np.argmin(key, axis=2)[..., None]
valid = np.isfinite(np.take_along_axis(key, idx, axis=2)[..., 0])
y = np.take_along_axis(off, idx, axis=2)[..., 0]
tsel = np.take_along_axis(np.broadcast_to(t, shape), idx, axis=2\
\)[..., 0] - tc
L = np.broadcast_to(lengths[None, :], (trials, g)).copy()
if q["label_swap"] > 0: # recorded length\
\ label wrong (errors-in-variables)
swap = rng.random((trials, g)) < q["label_swap"]
other = (np.arange(g)[None, :] + rng.integers(1, g, size=(tr\
\ials, g))) % g
L = np.where(swap, np.take_along_axis(L, other, axis=1), L)
return dict(y=y, t=tsel, L=L, valid=valid)
def wls(X, y, w):
"""Batched 0/1-weighted least squares. X (T,g,m), y (T,g), w (T,\
\g)."""
m = X.shape[2]
Xw = X * w[..., None]
A = np.einsum("tgi,tgj->tij", Xw, X) + 1e-9 * np.eye(m)[None]
b = np.einsum("tgi,tg->ti", Xw, y)
n = w.sum(1)
ok = n >= m + 1
A = np.where(ok[:, None, None], A, np.eye(m)[None])
coef = np.linalg.solve(A, b[..., None])[..., 0]
res = (y - np.einsum("tgi,ti->tg", X, coef)) * w
s2 = (res ** 2).sum(1) / np.maximum(n - m, 1)
return coef, s2, np.linalg.inv(A), n, ok
def theil_sen(L, y, v):
g = L.shape[1]
sl = []
for i in range(g):
for j in range(i + 1, g):
ok = v[:, i] & v[:, j] & (L[:, i] != L[:, j])
d = np.where(L[:, j] != L[:, i], L[:, j] - L[:, i], 1.0)
sl.append(np.where(ok, (y[:, j] - y[:, i]) / d, np.nan))
S = np.stack(sl, 1)
with warnings.catch_warnings():
warnings.simplefilter("ignore", RuntimeWarning)
b1 = np.nanmedian(S, axis=1)
b0 = np.nanmedian(np.where(v, y - b1[:, None] * L, np.nan), \
\axis=1)
return b1, b0
def run_estimators(p, rng, lengths=LENGTHS, k=8, trials=10000):
lengths = np.asarray(lengths, float)
g = len(lengths)
s = simulate(p, rng, lengths, k, trials)
b = simulate(p, rng, np.full(g, BASE_LEN), k, trials) # bas\
\eline: every group at 90 B
y, L, v, t = s["y"], s["L"], s["valid"], s["t"]
w = v.astype(float)
one = np.ones_like(L)
c2, s2, A2, n, ok2 = wls(np.stack([one, L], 2), y, w)
ok2 = ok2 & (n >= 4)
out = dict(n_groups=n)
out["tare0"] = np.where(ok2, c2[:, 0], np.nan)
out["tare90"] = np.where(ok2, c2[:, 0] + BASE_LEN * c2[:, 1], np\
\.nan)
out["slope"] = np.where(ok2, c2[:, 1], np.nan)
out["slope_se"] = np.where(ok2, np.sqrt(s2 * A2[:, 1, 1]), np.na\
\n)
c3, _, _, n3, ok3 = wls(np.stack([one, L, t], 2), y, w)
out["tare_t0"] = np.where(ok3 & (n3 >= 5), c3[:, 0], np.nan)
Lk = L / 1000.0
cq, s2q, Aq, nq, okq = wls(np.stack([one, Lk, Lk ** 2], 2), y, w)
tq = cq[:, 2] / np.sqrt(np.maximum(s2q * Aq[:, 2, 2], 1e-30))
dfq = nq - 3
out["p_curv"] = np.where(okq & (dfq >= 1), 2 * stats.t.sf(np.abs\
\(tq), np.maximum(dfq, 1)), np.nan)
_, b0 = theil_sen(L, y, v)
out["ts0"] = np.where(n >= 4, b0, np.nan)
yb, vb = b["y"], b["valid"]
out["base1"] = np.where(vb[:, 0], yb[:, 0], np.nan)
with warnings.catch_warnings():
warnings.simplefilter("ignore", RuntimeWarning)
out["base6"] = np.nanmean(np.where(vb, yb, np.nan), axis=1)
return out
def accept(out, se_max=0.02, p_min=0.01, n_min=5):
"""Illustrative validity gate used ONLY for these tests (thresho\
\lds are not recommendations)."""
with np.errstate(invalid="ignore"):
return (out["n_groups"] >= n_min) & (out["slope_se"] <= se_m\
\ax) & (out["p_curv"] >= p_min)
def summarize(scenario, estimator, est, target):
e = est[np.isfinite(est)]
if len(e) < 2:
return dict(test_date=TEST_DATE, scenario=scenario, estimato\
\r=estimator, n=len(e))
return dict(test_date=TEST_DATE, scenario=scenario, estimator=es\
\timator, n=len(e),
mean=e.mean(), sd=e.std(ddof=1), bias_vs_nominal_tar\
\get=e.mean() - target,
rmse_vs_true_offset=float(np.sqrt(np.mean(e ** 2))),
p95_abs_err_vs_true=float(np.quantile(np.abs(e), 0.9\
\5)))
Self-contained preliminary Monte Carlo run (Appendix A).¶
========== NOTE: '\\' line wrapping per RFC 8792 ==========
#!/usr/bin/env python3
# TARE toy Monte Carlo -- test date: 2026-10-23
"""Reproducible toy Monte Carlo simulation for TARE. Test date: 2026\
\-10-23.
This is an illustrative model, not a complete NTP implementation or a
validated model of the public Internet. It assumes:
- true clock offset = 0 us
- fixed forward/reverse propagation-delay difference = 150 us
- one asymmetric access-link pair: 10 Mbps vs 100 Mbps
- packet-length-dependent offset slope = 360 ns/byte = 0.36 us/byte
- independent exponential queueing delays in both directions, mean 5\
\0 us
- 8 candidate exchanges per packet length, retaining the candidate w\
\ith
minimum sum of queueing delays
- six packet lengths for TARE, ordinary baseline uses 90 bytes
- 10,000 Monte Carlo trials
Symmetric core serialization cancels from the offset equation. No dr\
\ift,
packet loss, path changes, nonlinear size effects, or server process\
\ing
effects are modeled.
"""
import numpy as np
import pandas as pd
TEST_DATE = "2026-10-23" # date of this test run; stamped into the \
\CSV and the printed output
SEED = 20261022
N_TRIALS = 10_000
N_CANDIDATES = 8
QUEUE_MEAN_US = 50.0
LENGTHS_BYTES = np.array([90, 250, 500, 800, 1100, 1400], dtype=floa\
\t)
TRUE_OFFSET_US = 0.0
PROPAGATION_DIFFERENCE_US = 150.0
FIXED_OFFSET_BIAS_US = PROPAGATION_DIFFERENCE_US / 2.0
SLOPE_US_PER_BYTE = 0.36 # half of 8*(1/10 Mbps - 1/100 Mbps)
BASELINE_LENGTH_BYTES = 90.0
def selected_offset(length_bytes, rng):
q_forward = rng.exponential(QUEUE_MEAN_US, N_CANDIDATES)
q_reverse = rng.exponential(QUEUE_MEAN_US, N_CANDIDATES)
selected = np.argmin(q_forward + q_reverse)
return (
TRUE_OFFSET_US
+ FIXED_OFFSET_BIAS_US
+ SLOPE_US_PER_BYTE * length_bytes
+ 0.5 * (q_forward[selected] - q_reverse[selected])
)
def main():
rng = np.random.default_rng(SEED)
baseline = np.empty(N_TRIALS)
tare_zero_intercept = np.empty(N_TRIALS)
tare_at_90_bytes = np.empty(N_TRIALS)
estimated_slope = np.empty(N_TRIALS)
for trial in range(N_TRIALS):
baseline[trial] = selected_offset(BASELINE_LENGTH_BYTES, rng)
y = np.array([selected_offset(L, rng) for L in LENGTHS_BYTES\
\])
slope, intercept = np.polyfit(LENGTHS_BYTES, y, 1)
estimated_slope[trial] = slope
tare_zero_intercept[trial] = intercept
tare_at_90_bytes[trial] = intercept + slope * BASELINE_LENGT\
\H_BYTES
records = []
for name, values, expected in [
("Ordinary NTP-style 90-byte sample", baseline, 107.4),
("TARE zero-length extrapolated intercept", tare_zero_interc\
\ept, 75.0),
("TARE estimate normalized to 90 bytes", tare_at_90_bytes, 1\
\07.4),
("Estimated slope (us/byte)", estimated_slope, 0.36),
]:
records.append({
"metric": name,
"mean": values.mean(),
"standard_deviation": values.std(ddof=1),
"5th_percentile": np.quantile(values, 0.05),
"95th_percentile": np.quantile(values, 0.95),
"theoretical_reference": expected,
})
df = pd.DataFrame(records)
df.insert(0, "test_date", TEST_DATE)
df.to_csv(f"tare_monte_carlo_results_{TEST_DATE}.csv", index=Fal\
\se)
print(f"TARE toy Monte Carlo -- test date: {TEST_DATE} seed={SE\
\ED} trials={N_TRIALS}")
print(df.to_string(index=False))
if __name__ == "__main__":
main()
Matched-budget comparison, analytic checks, design sweeps, and the zero-length experiment (Appendix B).¶
========== NOTE: '\\' line wrapping per RFC 8792 ==========
#!/usr/bin/env python3
# TARE matched-budget and design-sweep tests -- test date: 2026-10-23
"""TARE matched-budget comparison and design sweeps (toy model). Tes\
\t date: 2026-10-23.
Usage: python3 -I tare_matched_budget_2026-10-23.py OUTDIR
Question: does the regression beat an ordinary estimator given the S\
\AME number of
candidate exchanges? The supplied simulation gives TARE 48 candidate\
\s (6 groups x 8)
and the baseline 8. This script gives every estimator a 48-candidate\
\ budget.
Toy model only; not an NTP implementation; not real-network evidence.
"""
import importlib.util
import os
import sys
import numpy as np
import pandas as pd
_here = os.path.dirname(os.path.abspath(__file__))
_spec = importlib.util.spec_from_file_location("tare_core", os.path.\
\join(_here, "tare_core_2026-10-23.py"))
core = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(core)
OUT = sys.argv[1] if len(sys.argv) > 1 else "."
SEED = 20261023
TRIALS = 10_000
T1 = core.BASE_LEN * core.SLOPE + core.BIAS0 # 107.4 us: nomina\
\l value of a 90 B sample
T0 = core.BIAS0 # 75 us: nominal z\
\ero-length intercept
print(f"TARE matched-budget tests -- test date: {core.TEST_DATE} se\
\ed={SEED} trials={TRIALS}")
rng = np.random.default_rng(SEED)
L = core.LENGTHS
Lb = L.mean()
Sxx = ((L - Lb) ** 2).sum()
def row(exp, name, budget, target_label, est, target):
e = est[np.isfinite(est)]
return dict(test_date=core.TEST_DATE, experiment=exp, estimator=\
\name, budget_candidates=budget,
target=target_label, n=len(e), mean=e.mean(), sd=e.s\
\td(ddof=1),
bias_vs_own_target=e.mean() - target,
rmse_vs_true_offset=float(np.sqrt(np.mean(e ** 2))))
# ---------------- E1: matched budget, nominal model ----------------
rows = []
r = core.run_estimators({}, rng, trials=TRIALS) #\
\ TARE: 6 groups x 8 = 48 candidates
rows.append(row("E1", "baseline, 1 group of 8 at 90 B (as in supplie\
\d sim)", 8, "90 B sample (107.4)", r["base1"], T1))
b6 = core.simulate({}, rng, np.full(6, 90.0), 8, TRIALS)
rows.append(row("E1", "baseline, mean of 6 groups of 8 at 90 B", 48,\
\ "90 B sample (107.4)", np.mean(b6["y"], 1), T1))
rows.append(row("E1", "baseline, median of 6 groups of 8 at 90 B", 4\
\8, "90 B sample (107.4)", np.median(b6["y"], 1), T1))
b48 = core.simulate({}, rng, np.array([90.0]), 48, TRIALS)
rows.append(row("E1", "baseline, 1 group of 48 at 90 B (min-delay of\
\ 48)", 48, "90 B sample (107.4)", b48["y"][:, 0], T1))
rows.append(row("E1", "TARE OLS, fitted value at 90 B", 48, "90 B sa\
\mple (107.4)", r["tare90"], T1))
rows.append(row("E1", "TARE OLS, zero-length intercept", 48, "zero-l\
\ength (75)", r["tare0"], T0))
rows.append(row("E1", "TARE Theil-Sen, zero-length intercept", 48, "\
\zero-length (75)", r["ts0"], T0))
e1 = pd.DataFrame(rows)
s = e1.loc[0, "sd"]
analytic = pd.DataFrame([
dict(test_date=core.TEST_DATE, quantity="sd of one selected 90 B\
\ sample (from simulation)", value=s),
dict(test_date=core.TEST_DATE, quantity="analytic sd, mean of 6 \
\groups = s/sqrt(6)", value=s / np.sqrt(6)),
dict(test_date=core.TEST_DATE, quantity="analytic sd, OLS interc\
\ept = s*sqrt(1/6+Lbar^2/Sxx)", value=s * np.sqrt(1 / 6 + Lb ** 2 / \
\Sxx)),
dict(test_date=core.TEST_DATE, quantity="analytic sd, OLS fitted\
\ at 90 B", value=s * np.sqrt(1 / 6 + (90 - Lb) ** 2 / Sxx)),
dict(test_date=core.TEST_DATE, quantity="analytic sd, OLS slope \
\= s/sqrt(Sxx) (us/B)", value=s / np.sqrt(Sxx)),
])
# attack amplification: weights of each length group in the OLS pred\
\iction at x0
for x0 in (0.0, 90.0):
w = 1 / len(L) + (x0 - Lb) * (L - Lb) / Sxx
analytic.loc[len(analytic)] = dict(test_date=core.TEST_DATE,
quantity=f"sum |weight| of OLS prediction at {x0:.0f} B (wor\
\st-case per-group delay amplification)", value=np.abs(w).sum())
for Li, wi in zip(L, w):
analytic.loc[len(analytic)] = dict(test_date=core.TEST_DATE,\
\ quantity=f" weight of {Li:.0f} B group in prediction at {x0:.0f} \
\B", value=wi)
# ---------------- E2: design sweeps at budget 48 ----------------
rows = []
for (g, k) in [(3, 16), (4, 12), (6, 8), (8, 6), (12, 4)]:
for lmax in (250, 500, 1400):
lens = np.linspace(90, lmax, g)
o = core.run_estimators({}, rng, lengths=lens, k=k, trials=T\
\RIALS)
e0 = o["tare0"][np.isfinite(o["tare0"])]
if e0.size < 2: # the test fit gate requires >= 4 groups, \
\so 3 groups yields no fit
rows.append(dict(test_date=core.TEST_DATE, groups=g, can\
\didates_per_group=k, max_length_B=lmax,
note="no fit: gate requires >= 4 accept\
\ed groups"))
continue
rows.append(dict(test_date=core.TEST_DATE, groups=g, candida\
\tes_per_group=k, max_length_B=lmax,
intercept_mean=e0.mean(), intercept_sd=e0.s\
\td(ddof=1),
slope_mean=np.nanmean(o["slope"]), slope_sd\
\=np.nanstd(o["slope"], ddof=1),
frac_slope_se_le_0p02=float(np.mean(o["slop\
\e_se"][np.isfinite(o["slope_se"])] <= 0.02))))
e2 = pd.DataFrame(rows)
# ---------------- E2b: budget sweep, 6 lengths, K per group; baseli\
\ne matched at 6K ----------------
rows = []
for k in (1, 2, 4, 8, 16, 32):
o = core.run_estimators({}, rng, k=k, trials=TRIALS)
rows.append(dict(test_date=core.TEST_DATE, candidates_per_group=\
\k, budget_candidates=6 * k,
tare_intercept_sd=np.nanstd(o["tare0"], ddof=1)\
\, tare_at_90_sd=np.nanstd(o["tare90"], ddof=1),
baseline_mean_of_6_groups_sd=np.nanstd(o["base6\
\"], ddof=1),
tare_intercept_rmse_vs_true=float(np.sqrt(np.na\
\nmean(o["tare0"] ** 2))),
baseline_rmse_vs_true=float(np.sqrt(np.nanmean(\
\o["base6"] ** 2)))))
e2b = pd.DataFrame(rows)
# ---------------- E4: what "length zero" means (encapsulation / lay\
\er of L) ----------------
rows = []
for name, p, pred in [("L is effective length (as simulated)", {}, 0\
\.0),
("L = NTP payload; +28 B IPv4/UDP both ways", \
\dict(overhead_sym=28.0), core.SLOPE * 28),
("L = UDP payload; +66 B IP+Ethernet framing b\
\oth ways", dict(overhead_sym=66.0), core.SLOPE * 66),
("L = NTP payload; +100 B tunnel+framing both \
\ways", dict(overhead_sym=100.0), core.SLOPE * 100)]:
o = core.run_estimators(p, rng, trials=TRIALS)
rows.append(dict(test_date=core.TEST_DATE, case=name, intercept_\
\mean=np.nanmean(o["tare0"]),
intercept_error_vs_75=np.nanmean(o["tare0"]) - \
\T0, predicted_error_slope_x_overhead=pred))
e4 = pd.DataFrame(rows)
for nm, df in [("E1_matched_budget", e1), ("E1_analytic_checks", ana\
\lytic), ("E2_design_sweep", e2),
("E2b_budget_sweep", e2b), ("E4_length_zero_meaning",\
\ e4)]:
df.to_csv(os.path.join(OUT, f"tare_{nm}_{core.TEST_DATE}.csv"), \
\index=False)
print(f"\n== {nm} (test date {core.TEST_DATE}) ==")
print(df.drop(columns=["test_date"]).to_string(index=False, floa\
\t_format=lambda x: f"{x:.4f}"))
Stress and sensitivity scenarios and the illustrative validity gate (Appendix C). A comment near its false-valid column still says more than 10 us; the threshold actually used is 25 us (BAD_US).¶
========== NOTE: '\\' line wrapping per RFC 8792 ==========
#!/usr/bin/env python3
# TARE stress and sensitivity tests -- test date: 2026-10-23
"""TARE stress and sensitivity tests (toy model). Test date: 2026-10\
\-23.
Usage: python3 -I tare_stress_2026-10-23.py OUTDIR
Each scenario perturbs the nominal toy model (see tare_core_2026-10-\
\23.py) in one way the
draft says must be tested: clock drift, path change, nonlinear size \
\effects, packet loss,
label noise, queueing asymmetry, outliers, MTU/fragmentation, encaps\
\ulation, server
behaviour, adversarial delay. For each scenario we report matched-bu\
\dget baselines
(48 candidates) and TARE variants, plus an illustrative validity gat\
\e.
Toy model only. Not an NTP implementation. Not real-network evidence\
\. The validity-gate
thresholds are test settings, not recommendations. Results for scena\
\rios are one run per
scenario with a fixed seed; they are sensitivities of this toy, not \
\predictions.
"""
import importlib.util
import os
import sys
import numpy as np
import pandas as pd
_here = os.path.dirname(os.path.abspath(__file__))
_spec = importlib.util.spec_from_file_location("tare_core", os.path.\
\join(_here, "tare_core_2026-10-23.py"))
core = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(core)
OUT = sys.argv[1] if len(sys.argv) > 1 else "."
SEED = 20261023
TRIALS = 10_000
T1 = core.BASE_LEN * core.SLOPE + core.BIAS0
T0 = core.BIAS0
BAD_US = 25.0 # "bad" = intercept more than 25 us (~3.8 nominal sd\
\) from 75 us; 10 us was inside the noise
print(f"TARE stress tests -- test date: {core.TEST_DATE} seed={SEED\
\} trials={TRIALS}")
SCENARIOS = [
("nominal", {}),
("drift 0.1 ppm, sequential order", dict(drift_ppm=0.1)),
("drift 1 ppm, sequential order", dict(drift_ppm=1.0)),
("drift 5 ppm, sequential order", dict(drift_ppm=5.0)),
("drift 1 ppm, randomized order", dict(drift_ppm=1.0, order="ran\
\dom")),
("drift 5 ppm, randomized order", dict(drift_ppm=5.0, order="ran\
\dom")),
("path step +50 us mid-window, sequential", dict(step_us=50.0)),
("path step +50 us mid-window, randomized", dict(step_us=50.0, o\
\rder="random")),
("shaper: +40 us forward for L>=1100 B", dict(shaper_us=40.0, sh\
\aper_from=1100.0)),
("quadratic forward term, +30 us at 1400 B", dict(quad_us=30.0)),
("fragmentation at >=1300 B (+30 us, +20 B hdr)", dict(frag_from\
\=1300.0)),
("iid packet loss 20%", dict(loss=0.2)),
("size-dependent loss 2%..32%", dict(loss=0.02, loss_size=0.30)),
("length-label noise 10%", dict(label_swap=0.1)),
("queue asymmetry fwd 150 us / rev 20 us", dict(qf_mean=150.0, q\
\r_mean=20.0)),
("length-dependent forward queue (x2 at 700 B)", dict(q_len_scal\
\e=1.0)),
("outliers 5% (mean +2 ms, one direction)", dict(outlier_p=0.05)\
\),
("outliers 30%", dict(outlier_p=0.30)),
("symmetric encapsulation +66 B (L = payload)", dict(overhead_sy\
\m=66.0)),
("forward-only tunnel +50 B", dict(overhead_f=50.0)),
("NTPv4-style fixed 90 B response", dict(resp_fixed=90.0)),
("server rx timestamp lag 0.01 us/B", dict(ts_lag=0.01)),
("adversary: fwd delay 0.05 us/B on every packet", dict(adv_slop\
\e=0.05)),
("adversary: +200 us fwd on 90 B packets only", dict(adv_len=90.\
\0, adv_us=200.0)),
("adversary: +200 us fwd on 1400 B packets only", dict(adv_len=1\
\400.0, adv_us=200.0)),
]
rng = np.random.default_rng(SEED)
est_rows, val_rows = [], []
for name, p in SCENARIOS:
o = core.run_estimators(p, rng, trials=TRIALS)
for en, target in [("base1", T1), ("base6", T1), ("tare90", T1),\
\ ("tare0", T0), ("ts0", T0), ("tare_t0", T0)]:
est_rows.append(core.summarize(name, en, o[en], target))
acc = core.accept(o)
t0 = o["tare0"]
with np.errstate(invalid="ignore"):
bad = np.abs(t0 - T0) > BAD_US # interce\
\pt more than BAD_US off the nominal 75 us
fin = np.isfinite(t0)
a = acc & fin
val_rows.append(dict(test_date=core.TEST_DATE, scenario=name,
frac_rejected_by_gate=1.0 - a.mean(),
frac_fit_available=fin.mean(),
frac_bad_among_all=float(np.mean(bad & fin)\
\),
false_valid_rate=float(np.mean(a & bad)), \
\ # accepted AND >10 us off
accepted_mean_err_vs_75=float(np.mean(t0[a]\
\ - T0)) if a.any() else np.nan,
accepted_sd=float(np.std(t0[a], ddof=1)) if\
\ a.sum() > 1 else np.nan,
mean_slope=float(np.nanmean(o["slope"])), n\
\ominal_slope=core.SLOPE,
median_p_curv=float(np.nanmedian(o["p_curv"\
\])) if np.isfinite(o["p_curv"]).any() else np.nan))
est = pd.DataFrame(est_rows)
val = pd.DataFrame(val_rows)
est.to_csv(os.path.join(OUT, f"tare_stress_estimators_{core.TEST_DAT\
\E}.csv"), index=False)
val.to_csv(os.path.join(OUT, f"tare_stress_validity_{core.TEST_DATE}\
\.csv"), index=False)
pd.set_option("display.width", 250)
print(f"\n== intercept (tare0) and matched baseline (base6) per scen\
\ario, test date {core.TEST_DATE} ==")
pivot = est[est.estimator.isin(["base6", "tare0", "ts0", "tare_t0"])\
\].pivot(index="scenario", columns="estimator",
\
\ values="rmse_vs_true_offset")
print(pivot.reindex([s for s, _ in SCENARIOS]).to_string(float_forma\
\t=lambda x: f"{x:.1f}"))
print(f"\n== validity gate (illustrative), test date {core.TEST_DATE\
\} ==")
print(val.drop(columns=["test_date"]).to_string(index=False, float_f\
\ormat=lambda x: f"{x:.3f}"))
Pooled-slope hybrid estimator and lack-of-fit gate (Appendix D).¶
========== NOTE: '\\' line wrapping per RFC 8792 ==========
#!/usr/bin/env python3
# TARE hybrid estimator and lack-of-fit gate tests -- test date: 202\
\6-10-23
"""TARE hybrid estimator + replicate lack-of-fit gate (toy model). T\
\est date: 2026-10-23.
Usage: python3 -I tare_hybrid_2026-10-23.py OUTDIR
Proposal under test (fixes 1 and 3 from the review):
* Calibration = M windows pooled. Each window: 6 lengths x 2 repli\
\cate groups x 4 candidates
= 48 candidates (min-delay kept per group). Randomized order.
* Slope b_hat = pooled OLS slope over all M*12 selected points.
* Offset = one min-delay sample of 48 candidates at 90 B, minus b_\
\hat * 90 ("hybrid").
No extrapolation of an intercept: slope error is multiplied by 9\
\0 B, not by the fit leverage.
* Gate: pooled lack-of-fit F-test against pure error from the repl\
\icates (reject if p < 0.01)
AND slope significance |b_hat| >= 3 se(b_hat). If the gate fails\
\, fall back to the plain
90 B min-delay sample.
Budget accounting: calibration costs M*48 = 960 candidates, amortize\
\d over R = 96 offset
estimates = +10 per estimate, so the fully loaded baseline is a 58-c\
\andidate min-delay sample.
Comparators: plain baselines (48 and 58 candidates), the original si\
\ngle-window OLS intercept
with the original illustrative gate (core.accept).
Toy model only. Not an NTP implementation. Not real-network evidence\
\. Gate thresholds are
test settings. Packet loss scenarios are not run here (loss handling\
\ is not implemented in
the pooled fit). One run per scenario, fixed seed; sd of a reported \
\mean is about sd/sqrt(n).
"""
import importlib.util
import os
import sys
import numpy as np
import pandas as pd
from scipy import stats
_here = os.path.dirname(os.path.abspath(__file__))
_spec = importlib.util.spec_from_file_location("tare_core", os.path.\
\join(_here, "tare_core_2026-10-23.py"))
core = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(core)
TEST_DATE = "2026-10-23"
OUT = sys.argv[1] if len(sys.argv) > 1 else "."
SEED = 20261023
TRIALS = 5000
M = 20
R = 96
BAD_US = 25.0
LENS12 = np.tile(core.LENGTHS, 2)
SER_R_NOMINAL = core.SER_R
print(f"TARE hybrid tests -- test date: {TEST_DATE} seed={SEED} tri\
\als={TRIALS} M={M} R={R}")
def true_slope():
return 0.5 * (core.SER_F - core.SER_R)
def calibrate(p, rng, m, trials):
s = core.simulate(p, rng, LENS12, 4, trials * m)
n = 12 * m
y = s["y"].reshape(trials, n)
L = s["L"].reshape(trials, n)
Lb = L.mean(1, keepdims=True)
sxx = ((L - Lb) ** 2).sum(1)
b = ((L - Lb) * (y - y.mean(1, keepdims=True))).sum(1) / sxx
a = y.mean(1) - b * Lb[:, 0]
sse = ((y - a[:, None] - b[:, None] * L) ** 2).sum(1)
pe = np.zeros(trials)
for Lj in core.LENGTHS:
mk = (L == Lj)
cnt = np.maximum(mk.sum(1), 1)
mu = (y * mk).sum(1) / cnt
pe += (((y - mu[:, None]) ** 2) * mk).sum(1)
df_pe = n - len(core.LENGTHS)
lof = np.maximum(sse - pe, 0.0)
f = (lof / 4.0) / (pe / df_pe)
return dict(b=b, p_lof=stats.f.sf(f, 4, df_pe), se_b=np.sqrt((pe\
\ / df_pe) / sxx))
def offs(p, rng, k, trials):
q = {**p, "label_swap": 0.0} # single known-length group: labe\
\l noise cannot apply
return core.simulate(q, rng, np.array([core.BASE_LEN]), k, trial\
\s)["y"][:, 0]
def summ(scen, name, est):
e = est[np.isfinite(est)]
return dict(test_date=TEST_DATE, scenario=scen, estimator=name, \
\n=len(e), mean=e.mean(),
sd=e.std(ddof=1), mean_err_vs_75=e.mean() - core.BIA\
\S0,
rmse_vs_75=float(np.sqrt(np.mean((e - core.BIAS0) **\
\ 2))),
p95_abs_err_vs_75=float(np.quantile(np.abs(e - core.\
\BIAS0), 0.95)),
rmse_vs_true_offset=float(np.sqrt(np.mean(e ** 2))))
def run(scen, p, rng):
p = {"order": "random", **p}
cal = calibrate(p, rng, M, TRIALS)
y48 = offs(p, rng, 48, TRIALS)
y58 = offs(p, rng, 58, TRIALS)
o = core.run_estimators(p, rng, trials=TRIALS)
b = cal["b"]
hyb_raw = y48 - b * core.BASE_LEN
sig = np.abs(b) >= 3.0 * cal["se_b"]
lof_ok = cal["p_lof"] >= 0.01
ok = lof_ok & sig
hyb = np.where(ok, hyb_raw, y48)
acc = core.accept(o) & np.isfinite(o["tare0"])
ols = np.where(acc, o["tare0"], y48)
t1 = core.BIAS0 + true_slope() * core.BASE_LEN
hyb_bad = ok & (np.abs(hyb - core.BIAS0) > BAD_US)
ols_bad = acc & (np.abs(ols - core.BIAS0) > BAD_US)
est = [summ(scen, "base48", y48), summ(scen, "base58 (fully load\
\ed)", y58),
summ(scen, "ols_intercept_raw (orig, 1 window)", o["tare0\
\"]), summ(scen, "ols_gated (orig gate)", ols),
summ(scen, "hybrid_raw", hyb_raw), summ(scen, "hybrid_gat\
\ed", hyb)]
e_h = hyb_raw[np.isfinite(hyb_raw)]
e_o = o["tare0"][np.isfinite(o["tare0"])]
val = dict(test_date=TEST_DATE, scenario=scen, nominal_baseline_\
\us=t1,
base58_err=y58.mean() - t1, base58_sd=y58.std(ddof=1),
hyb_raw_err=e_h.mean() - core.BIAS0, hyb_raw_sd=e_h.s\
\td(ddof=1),
hyb_lof_reject=1.0 - lof_ok.mean(), hyb_slope_not_sig\
\=1.0 - sig.mean(),
hyb_fallback=1.0 - ok.mean(), hyb_false_valid=float(h\
\yb_bad.mean()),
hyb_applied_err=(hyb_raw[ok].mean() - core.BIAS0) if \
\ok.any() else np.nan,
ols_raw_err=e_o.mean() - core.BIAS0, ols_raw_sd=e_o.s\
\td(ddof=1),
ols_fallback=1.0 - acc.mean(), ols_false_valid=float(\
\ols_bad.mean()))
return est, val
# ---------------- E1/E3: impairment suite at nominal slope --------\
\--------
SCEN = [
("nominal", {}),
("drift 1 ppm, sequential (neg. control)", dict(order="sequentia\
\l", drift_ppm=1.0)),
("drift 1 ppm, randomized", dict(drift_ppm=1.0)),
("drift 5 ppm, randomized", dict(drift_ppm=5.0)),
("path step +50 us, randomized", dict(step_us=50.0)),
("path step +50 us, sequential (neg. control)", dict(order="sequ\
\ential", step_us=50.0)),
("shaper +10 us fwd for L>=1100", dict(shaper_us=10.0)),
("shaper +40 us fwd for L>=1100", dict(shaper_us=40.0)),
("quadratic fwd term +5 us at 1400 B", dict(quad_us=5.0)),
("quadratic fwd term +30 us at 1400 B", dict(quad_us=30.0)),
("fragmentation at >=1300 B", dict(frag_from=1300.0)),
("length-label noise 10%", dict(label_swap=0.1)),
("symmetric +66 B overhead (L=payload)", dict(overhead_sym=66.0)\
\),
("forward-only tunnel +50 B", dict(overhead_f=50.0)),
("NTPv4-style fixed 90 B response", dict(resp_fixed=90.0)),
("queue asymmetry fwd150/rev20", dict(qf_mean=150.0, qr_mean=20.\
\0)),
("length-dependent fwd queue (x2 at 700 B)", dict(q_len_scale=1.\
\0)),
("outliers 5% (mean +2 ms)", dict(outlier_p=0.05)),
("adversary: fwd delay 0.05 us/B, every packet", dict(adv_slope=\
\0.05)),
("adversary: +20 us fwd on 1400 B only", dict(adv_len=1400.0, ad\
\v_us=20.0)),
("adversary: +200 us fwd on 1400 B only", dict(adv_len=1400.0, a\
\dv_us=200.0)),
]
rng = np.random.default_rng(SEED)
est_rows, val_rows = [], []
for name, p in SCEN:
e, v = run(name, p, rng)
est_rows += e
val_rows.append(v)
val = pd.DataFrame(val_rows)
# ---------------- E2: true-slope sweep (applicability) ------------\
\----
sweep_rows = []
for s in (0.0, 0.02, 0.05, 0.1, 0.2, 0.36):
core.SER_R = core.SER_F - 2.0 * s
e, v = run(f"true slope {s:.2f} us/B", {}, rng)
est_rows += e
sweep_rows.append(v)
core.SER_R = SER_R_NOMINAL
sweep = pd.DataFrame(sweep_rows)
# ---------------- E4: detection power vs size of impairment -------\
\---------
pw_rows = []
for label, key, vals_, extra in [("shaper us at >=1100 B", "shaper_u\
\s", (2, 5, 10, 20, 40), {}),
("quadratic us at 1400 B", "quad_us\
\", (2, 5, 10, 30), {}),
("adv us on 1400 B only", "adv_us",\
\ (2, 5, 10, 20, 50, 200), dict(adv_len=1400.0))]:
for v_ in vals_:
_, v = run(f"{label} = {v_}", {key: float(v_), **extra}, rng)
pw_rows.append(v)
power = pd.DataFrame(pw_rows)
# ---------------- E5: pooling depth (nominal) ----------------
m_rows = []
T5 = 2500
for m in (5, 10, 20, 40):
p = {"order": "random"}
cal = calibrate(p, rng, m, T5)
y48 = offs(p, rng, 48, T5)
hy = y48 - cal["b"] * core.BASE_LEN
m_rows.append(dict(test_date=TEST_DATE, M=m, calibration_candida\
\tes=48 * m,
slope_mean=cal["b"].mean(), slope_sd=cal["b"]\
\.std(ddof=1),
hybrid_mean=hy.mean(), hybrid_sd=hy.std(ddof=\
\1), base48_sd=y48.std(ddof=1),
lof_false_reject_at_p01=float(np.mean(cal["p_\
\lof"] < 0.01)),
mean_se_b=cal["se_b"].mean()))
mdf = pd.DataFrame(m_rows)
# ---------------- E6: analytic leverage of one length group on the \
\output ----------------
L = core.LENGTHS
sxx = ((L - L.mean()) ** 2).sum()
w_ols0 = 1.0 / len(L) + (0.0 - L.mean()) * (L - L.mean()) / sxx
w_hyb = core.BASE_LEN * (L - L.mean()) / sxx
lev = pd.DataFrame(dict(test_date=TEST_DATE, length_B=L, weight_ols_\
\intercept=w_ols0,
weight_hybrid_output=w_hyb))
lev.loc[len(lev)] = dict(test_date=TEST_DATE, length_B=np.nan, weigh\
\t_ols_intercept=np.abs(w_ols0).sum(),
weight_hybrid_output=np.abs(w_hyb).sum())
est = pd.DataFrame(est_rows)
for nm, df in [("estimators", est), ("validity", val), ("slope_sweep\
\", sweep), ("power", power),
("pooling_depth", mdf), ("leverage", lev)]:
df.to_csv(os.path.join(OUT, f"tare_hybrid_{nm}_{TEST_DATE}.csv")\
\, index=False)
pd.set_option("display.width", 250)
pd.set_option("display.max_columns", 30)
fmt = lambda x: f"{x:.3f}"
cols = ["scenario", "base58_err", "base58_sd", "hyb_raw_err", "hyb_r\
\aw_sd", "hyb_lof_reject",
"hyb_fallback", "hyb_false_valid", "ols_raw_err", "ols_raw_s\
\d", "ols_fallback", "ols_false_valid"]
print(f"\n== E1/E3 impairment suite, errors vs the nominal target, t\
\est date {TEST_DATE} ==")
print(val[cols].to_string(index=False, float_format=fmt))
print(f"\n== E2 true-slope sweep (hybrid should track the compensate\
\d target; base58_err ~ slope*90), test date {TEST_DATE} ==")
print(sweep[cols].to_string(index=False, float_format=fmt))
print(f"\n== E4 detection power vs impairment size, test date {TEST_\
\DATE} ==")
print(power[["scenario", "hyb_raw_err", "hyb_lof_reject", "hyb_fallb\
\ack", "hyb_applied_err", "hyb_false_valid",
"ols_raw_err", "ols_fallback"]].to_string(index=False, \
\float_format=fmt))
print(f"\n== E5 pooling depth, nominal, test date {TEST_DATE} ==")
print(mdf.drop(columns=["test_date"]).to_string(index=False, float_f\
\ormat=lambda x: f"{x:.4f}"))
print(f"\n== E6 analytic leverage per length group (last row = sum o\
\f |weights|), test date {TEST_DATE} ==")
print(lev.drop(columns=["test_date"]).to_string(index=False, float_f\
\ormat=lambda x: f"{x:.4f}"))
Gate against payload-only length counting, and hybrid with loss, delay at 90 B, and a schedule-aware adversary (Table C-3 and Section D.7).¶
========== NOTE: '\\' line wrapping per RFC 8792 ==========
#!/usr/bin/env python3
# TARE supplementary tests (gate vs payload-only overhead; hybrid wi\
\th loss, 90 B-only delay, schedule-aware adversary) -- test date: 2\
\026-10-24
"""TARE supplementary tests (toy model). Test date: 2026-10-24.
Usage: python3 -I tare_supplement_2026-10-24.py OUTDIR
Closes gaps listed after the 2026-10-23 runs. Uses the unmodified co\
\re model
(tare_core_2026-10-23.py) and the same hybrid design as tare_hybrid_\
\2026-10-23.py
(M = 20 pooled windows, 12 groups x 4 candidates, lack-of-fit F-test\
\ p < 0.01 and
|slope| >= 3 se gate, fallback to the plain 90 B sample), with one c\
\hange: the pooled
fit here is loss-aware (lost candidates get zero weight), so packet-\
\loss scenarios can run.
S1 Illustrative gate (core.accept) against payload-only length co\
\unting: symmetric
overhead of 28, 66 and 100 B (Section 4.4 of the draft), plus \
\a no-overhead control.
S2 Hybrid with packet loss (iid 20 percent; size-dependent 2..32 \
\percent).
S3 Hybrid with forward delay confined to 90 B packets (5, 20, 200\
\ us).
S4 Hybrid and original OLS against a schedule-aware adversary tha\
\t adds forward delay
d(L) = s (L - 90) to every packet (zero at 90 B). The delay is\
\ exactly linear in L, so
it passes any lack-of-fit gate. Predicted hybrid shift: -45 s \
\us (s in us/B of forward delay).
Toy model only. Not an NTP implementation. Not real-network evidence\
\. Thresholds are test
settings, not recommendations. One run per scenario, fixed seed.
"""
import importlib.util
import os
import sys
import numpy as np
import pandas as pd
from scipy import stats
_here = os.path.dirname(os.path.abspath(__file__))
_spec = importlib.util.spec_from_file_location("tare_core", os.path.\
\join(_here, "tare_core_2026-10-23.py"))
core = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(core)
TEST_DATE = "2026-10-24"
OUT = sys.argv[1] if len(sys.argv) > 1 else "."
SEED = 20261024
TRIALS_GATE = 10_000
TRIALS_HYB = 5_000
M = 20
BAD_US = 25.0
LENS12 = np.tile(core.LENGTHS, 2)
T0, T1 = core.BIAS0, core.BIAS0 + core.SLOPE * core.BASE_LEN
print(f"TARE supplementary tests -- test date: {TEST_DATE} seed={SE\
\ED} trials gate={TRIALS_GATE} hybrid={TRIALS_HYB} M={M}")
def calibrate(p, rng, m, trials):
"""Pooled OLS slope with lack-of-fit F-test; lost candidates (va\
\lid == False) get zero weight."""
s = core.simulate(p, rng, LENS12, 4, trials * m)
n = 12 * m
v = s["valid"].reshape(trials, n).astype(float)
y = np.where(v > 0, s["y"].reshape(trials, n), 0.0)
L = s["L"].reshape(trials, n)
nv = v.sum(1)
Lb = (v * L).sum(1, keepdims=True) / nv[:, None]
yb = (v * y).sum(1, keepdims=True) / nv[:, None]
sxx = (v * (L - Lb) ** 2).sum(1)
b = (v * (L - Lb) * (y - yb)).sum(1) / sxx
a = yb[:, 0] - b * Lb[:, 0]
sse = (v * (y - a[:, None] - b[:, None] * L) ** 2).sum(1)
pe = np.zeros(trials)
nlen = np.zeros(trials)
for Lj in core.LENGTHS:
mk = (L == Lj) * v
cnt = mk.sum(1)
mu = (y * mk).sum(1) / np.maximum(cnt, 1)
pe += (mk * (y - mu[:, None]) ** 2).sum(1)
nlen += cnt > 0
df_pe = nv - nlen
lof = np.maximum(sse - pe, 0.0)
f = (lof / (nlen - 2)) / (pe / df_pe)
return dict(b=b, p_lof=stats.f.sf(f, nlen - 2, df_pe), se_b=np.s\
\qrt((pe / df_pe) / sxx))
def offs(p, rng, k, trials):
q = {**p, "label_swap": 0.0}
s = core.simulate(q, rng, np.array([core.BASE_LEN]), k, trials)
return np.where(s["valid"][:, 0], s["y"][:, 0], np.nan)
def run_hybrid(scen, p, rng, predicted_shift=np.nan):
p = {"order": "random", **p}
cal = calibrate(p, rng, M, TRIALS_HYB)
y48, y58 = offs(p, rng, 48, TRIALS_HYB), offs(p, rng, 58, TRIALS\
\_HYB)
o = core.run_estimators(p, rng, trials=TRIALS_HYB)
hyb_raw = y48 - cal["b"] * core.BASE_LEN
ok = (cal["p_lof"] >= 0.01) & (np.abs(cal["b"]) >= 3.0 * cal["se\
\_b"])
hyb = np.where(ok, hyb_raw, y48)
acc = core.accept(o) & np.isfinite(o["tare0"])
ols = np.where(acc, o["tare0"], y48)
fin = lambda x: x[np.isfinite(x)]
return dict(test_date=TEST_DATE, scenario=scen,
base58_err=np.nanmean(y58) - T1, base58_sd=np.nanstd\
\(y58, ddof=1),
hyb_raw_err=np.nanmean(hyb_raw) - T0, hyb_raw_sd=np.\
\nanstd(hyb_raw, ddof=1),
hyb_lof_reject=float(np.mean(cal["p_lof"] < 0.01)), \
\hyb_fallback=1.0 - ok.mean(),
hyb_false_valid=float(np.mean(ok & (np.abs(hyb - T0)\
\ > BAD_US))),
hyb_applied_err=(np.nanmean(hyb_raw[ok]) - T0) if ok\
\.any() else np.nan,
ols_raw_err=fin(o["tare0"]).mean() - T0, ols_raw_sd=\
\fin(o["tare0"]).std(ddof=1),
ols_fallback=1.0 - acc.mean(),
ols_false_valid=float(np.mean(acc & (np.abs(ols - T0\
\) > BAD_US))),
predicted_hybrid_shift=predicted_shift)
rng = np.random.default_rng(SEED)
# ---- S1: gate against payload-only length counting ---------------\
\----------------------------
g_rows = []
for name, p, oh in [("no overhead (control)", {}, 0.0),
("payload-only, symmetric overhead 28 B", dict(o\
\verhead_sym=28.0), 28.0),
("payload-only, symmetric overhead 66 B", dict(o\
\verhead_sym=66.0), 66.0),
("payload-only, symmetric overhead 100 B", dict(\
\overhead_sym=100.0), 100.0)]:
o = core.run_estimators(p, rng, trials=TRIALS_GATE)
t0 = o["tare0"]
fin = np.isfinite(t0)
acc = core.accept(o) & fin
g_rows.append(dict(test_date=TEST_DATE, scenario=name, overhead_\
\B=oh,
predicted_shift_us=core.SLOPE * oh,
mean_err_vs_75=float(np.nanmean(t0) - T0), sd\
\=float(np.nanstd(t0, ddof=1)),
frac_rejected_by_gate=1.0 - acc.mean(),
frac_beyond_25us=float(np.mean(fin & (np.abs(\
\t0 - T0) > BAD_US))),
false_valid_rate=float(np.mean(acc & (np.abs(\
\t0 - T0) > BAD_US))),
accepted_mean_err_vs_75=float(np.mean(t0[acc]\
\ - T0)) if acc.any() else np.nan,
mean_slope=float(np.nanmean(o["slope"])), med\
\ian_p_curv=float(np.nanmedian(o["p_curv"]))))
gate = pd.DataFrame(g_rows)
# ---- S2-S4: hybrid supplements -----------------------------------\
\------------------------------
h_rows = []
for name, p in [("nominal (control)", {}),
("iid packet loss 20%", dict(loss=0.2)),
("size-dependent loss 2%..32%", dict(loss=0.02, loss\
\_size=0.30))]:
h_rows.append(dict(group="S2 loss", **run_hybrid(name, p, rng)))
for us in (5.0, 20.0, 200.0):
h_rows.append(dict(group="S3 90 B-only delay", **run_hybrid(f"+{\
\us:g} us fwd on 90 B packets only", dict(adv_len=90.0, adv_us=us), \
\rng,
pre\
\dicted_shift=0.5 * us)))
for s_ in (0.2, 0.5, 1.0):
# d(L) = s (L - 90): adv_slope * L plus a constant -90 s on ever\
\y packet (shaper_from = 0)
h_rows.append(dict(group="S4 schedule-aware", **run_hybrid(f"sch\
\edule-aware: fwd delay {s_:g} us/B x (L-90)",
dict(\
\adv_slope=s_, shaper_us=-90.0 * s_, shaper_from=0.0), rng,
predi\
\cted_shift=-45.0 * s_)))
hyb = pd.DataFrame(h_rows)
gate.to_csv(os.path.join(OUT, f"tare_supplement_gate_{TEST_DATE}.csv\
\"), index=False)
hyb.to_csv(os.path.join(OUT, f"tare_supplement_hybrid_{TEST_DATE}.cs\
\v"), index=False)
pd.set_option("display.width", 250)
pd.set_option("display.max_columns", 30)
print(f"\n== S1 gate vs payload-only overhead, test date {TEST_DATE}\
\ ==")
print(gate.drop(columns=["test_date"]).to_string(index=False, float_\
\format=lambda x: f"{x:.3f}"))
print(f"\n== S2-S4 hybrid supplements (errors vs 75 us; base58 vs 10\
\7.4 us), test date {TEST_DATE} ==")
print(hyb.drop(columns=["test_date"]).to_string(index=False, float_f\
\ormat=lambda x: f"{x:.3f}"))
This appendix reproduces the output file of every script run, as written by the scripts. Each file is comma-separated text with a header row. Appendix H gives the SHA-256 checksum of each. The scripts are deterministic for a given seed and package versions (Section E.2), so each file can also be regenerated from Appendix F.¶
Produced by the script of Section F.2. Reproduced in: Table A-1.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,metric,mean,standard_deviation,5th_percentile,95th_percent\ \ile,theoretical_reference 2026-10-23,Ordinary NTP-style 90-byte sample,107.33962195974443,8.99\ \2870289528778,92.51076525023129,122.28756229399,107.4 2026-10-23,TARE zero-length extrapolated intercept,74.98589817579087\ \,6.656938652636782,64.07429573071184,85.79669972725456,75.0 2026-10-23,TARE estimate normalized to 90 bytes,107.38319240765254,6\ \.0688879676666785,97.42630101598706,117.22316034134255,107.4 2026-10-23,Estimated slope (us/byte),0.35996993590957443,0.007976981\ \620170328,0.3470351606821014,0.3731109467649705,0.36
Produced by the script of Section F.3. Reproduced in: Table B-1.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,experiment,estimator,budget_candidates,target,n,mean,sd,bi\ \as_vs_own_target,rmse_vs_true_offset 2026-10-23,E1,"baseline, 1 group of 8 at 90 B (as in supplied sim)",\ \8,90 B sample (107.4),10000,107.39128437358303,8.792161830826513,-0\ \.0087156264169721,107.75055609534577 2026-10-23,E1,"baseline, mean of 6 groups of 8 at 90 B",48,90 B samp\ \le (107.4),10000,107.37393339629611,3.646228067620041,-0.0260666037\ \03895908,107.43581908570074 2026-10-23,E1,"baseline, median of 6 groups of 8 at 90 B",48,90 B sa\ \mple (107.4),10000,107.34277640312114,3.5806229978181734,-0.0572235\ \9687887035,107.40247308557124 2026-10-23,E1,"baseline, 1 group of 48 at 90 B (min-delay of 48)",48\ \,90 B sample (107.4),10000,107.40936023588553,3.253133928596892,0.0\ \09360235885523593,107.45860825616337 2026-10-23,E1,"TARE OLS, fitted value at 90 B",48,90 B sample (107.4\ \),10000,107.39876628147222,5.999187038315719,-0.0012337185277857543\ \,107.56617333008772 2026-10-23,E1,"TARE OLS, zero-length intercept",48,zero-length (75),\ \10000,74.99523487274244,6.575559924569044,-0.004765127257556401,75.\ \28292580752007 2026-10-23,E1,"TARE Theil-Sen, zero-length intercept",48,zero-length\ \ (75),10000,74.97565867258736,6.898471026325922,-0.0243413274126425\ \,75.29232057121848
Produced by the script of Section F.3. Reproduced in: Table B-2.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,quantity,value 2026-10-23,sd of one selected 90 B sample (from simulation),8.792161\ \830826513 2026-10-23,"analytic sd, mean of 6 groups = s/sqrt(6)",3.58938503691\ \65525 2026-10-23,"analytic sd, OLS intercept = s*sqrt(1/6+Lbar^2/Sxx)",6.4\ \63115310628789 2026-10-23,"analytic sd, OLS fitted at 90 B",5.892986951290075 2026-10-23,"analytic sd, OLS slope = s/sqrt(Sxx) (us/B)",0.007789524\ \7082281115 2026-10-23,sum |weight| of OLS prediction at 0 B (worst-case per-gro\ \up delay amplification),1.5465201465201466 2026-10-23, weight of 90 B group in prediction at 0 B,0.49162742019\ \884875 2026-10-23, weight of 250 B group in prediction at 0 B,0.4049712192\ \569335 2026-10-23, weight of 500 B group in prediction at 0 B,0.2695709052\ \85191 2026-10-23, weight of 800 B group in prediction at 0 B,0.1070905285\ \1909995 2026-10-23, weight of 1100 B group in prediction at 0 B,-0.05538984\ \8246991114 2026-10-23, weight of 1400 B group in prediction at 0 B,-0.21787022\ \501308215 2026-10-23,sum |weight| of OLS prediction at 90 B (worst-case per-gr\ \oup delay amplification),1.3882783882783882 2026-10-23, weight of 90 B group in prediction at 90 B,0.4492412349\ \555207 2026-10-23, weight of 250 B group in prediction at 90 B,0.373888016\ \7451596 2026-10-23, weight of 500 B group in prediction at 90 B,0.256148613\ \29147043 2026-10-23, weight of 800 B group in prediction at 90 B,0.114861329\ \14704342 2026-10-23, weight of 1100 B group in prediction at 90 B,-0.0264259\ \54997383566 2026-10-23, weight of 1400 B group in prediction at 90 B,-0.1677132\ \391418106
Produced by the script of Section F.3. Reproduced in: Table B-3.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,groups,candidates_per_group,max_length_B,note,intercept_me\ \an,intercept_sd,slope_mean,slope_sd,frac_slope_se_le_0p02 2026-10-23,3,16,250,no fit: gate requires >= 4 accepted groups,,,,, 2026-10-23,3,16,500,no fit: gate requires >= 4 accepted groups,,,,, 2026-10-23,3,16,1400,no fit: gate requires >= 4 accepted groups,,,,, 2026-10-23,4,12,250,,74.99682648142885,10.527299962249701,0.35960405\ \95060146,0.05839893557667127,0.1404 2026-10-23,4,12,500,,74.86772863316033,7.655861311813244,0.360373423\ \96762223,0.022922038302779602,0.5674 2026-10-23,4,12,1400,,75.0083468581195,6.406832697549918,0.359921686\ \34312705,0.007215731655096678,0.9972 2026-10-23,6,8,250,,74.98160583747881,11.846584240185212,0.360021133\ \43939773,0.06622693142029053,0.0261 2026-10-23,6,8,500,,74.93567450867461,8.472317767419304,0.3600962159\ \8340247,0.02597714276914016,0.3942 2026-10-23,6,8,1400,,75.01594463078585,7.0187421058006185,0.35997940\ \64925287,0.008092866445680235,0.9991 2026-10-23,8,6,250,,75.14552899026265,12.720874448073335,0.358840680\ \01300595,0.07170224062297169,0.0044 2026-10-23,8,6,500,,74.93414744749957,9.045437649982128,0.3604027433\ \442678,0.027803049407872094,0.2689 2026-10-23,8,6,1400,,75.00268047346935,7.384565765231218,0.360060838\ \9739125,0.008616879296525728,0.9984 2026-10-23,12,4,250,,74.94581927725058,13.858516599434923,0.36052689\ \740666993,0.07829710184760974,0.0002 2026-10-23,12,4,500,,75.0427012340892,9.99006723454537,0.35985273854\ \30255,0.031078115831584686,0.1271 2026-10-23,12,4,1400,,74.91274003411462,8.246192009815982,0.36006834\ \91298452,0.009660763597394657,0.9988
Produced by the script of Section F.3. Reproduced in: Table B-4.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,candidates_per_group,budget_candidates,tare_intercept_sd,t\ \are_at_90_sd,baseline_mean_of_6_groups_sd,tare_intercept_rmse_vs_tr\ \ue,baseline_rmse_vs_true 2026-10-23,1,6,25.848462162958874,23.554891707197932,14.419150704205\ \602,79.47183910783815,108.2280098695189 2026-10-23,2,12,15.828486446387288,14.4378434874567,8.92515654745364\ \3,76.26615253747143,107.78384634866255 2026-10-23,4,24,9.985193918496869,9.107497166266445,5.63817239840396\ \6,75.48944815075222,107.55699375502572 2026-10-23,8,48,6.523620378888386,5.948086672265669,3.61713972293805\ \9,75.36311143159789,107.44501200049835 2026-10-23,16,96,4.32944578589779,3.9485435854293054,2.4519741700715\ \096,75.16661470056732,107.47132391430411 2026-10-23,32,192,2.979860247095177,2.718459483886751,1.646694297663\ \7653,75.07802847238908,107.40821684645637
Produced by the script of Section F.3. Reproduced in: Table B-5.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,case,intercept_mean,intercept_error_vs_75,predicted_error_\ \slope_x_overhead 2026-10-23,L is effective length (as simulated),74.98135657960727,-0\ \.01864342039273481,0.0 2026-10-23,L = NTP payload; +28 B IPv4/UDP both ways,84.998256529396\ \43,9.998256529396429,10.08 2026-10-23,L = UDP payload; +66 B IP+Ethernet framing both ways,98.8\ \356185996677,23.835618599667697,23.759999999999998 2026-10-23,L = NTP payload; +100 B tunnel+framing both ways,110.9257\ \0919129197,35.92570919129197,36.0
Produced by the script of Section F.4. Reproduced in: Table C-1 reproduces four of the six estimators; the other two are only here.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,scenario,estimator,n,mean,sd,bias_vs_nominal_target,rmse_v\ \s_true_offset,p95_abs_err_vs_true 2026-10-23,nominal,base1,10000,107.39128437358303,8.792161830826513,\ \-0.0087156264169721,107.75055609534577,121.83238788894438 2026-10-23,nominal,base6,10000,107.35793066737342,3.6301301116303843\ \,-0.04206933262658197,107.41928041102983,113.36994553024049 2026-10-23,nominal,tare90,10000,107.39876628147222,5.999187038315719\ \,-0.0012337185277857543,107.56617333008772,117.14816871875605 2026-10-23,nominal,tare0,10000,74.99523487274244,6.575559924569044,-\ \0.004765127257556401,75.28292580752007,85.6377620445779 2026-10-23,nominal,ts0,10000,74.97565867258736,6.898471026325922,-0.\ \0243413274126425,75.29232057121848,86.22422952918939 2026-10-23,nominal,tare_t0,10000,75.02992585143228,45.40383458046601\ \,0.029925851432281547,87.69715968640197,142.58260032336293 2026-10-23,"drift 0.1 ppm, sequential order",base1,10000,105.4680810\ \3422643,8.97255427428841,-1.9319189657735762,105.84901887393279,120\ \.38978429821964 2026-10-23,"drift 0.1 ppm, sequential order",base6,10000,107.4343174\ \3600657,3.6625919902208146,0.03431743600656034,107.49672460856398,1\ \13.51734179047979 2026-10-23,"drift 0.1 ppm, sequential order",tare90,10000,105.642030\ \85590282,5.961811984409265,-1.7579691440971885,105.81010505229051,1\ \15.44734976659208 2026-10-23,"drift 0.1 ppm, sequential order",tare0,10000,72.98204347\ \666837,6.536114195569005,-2.017956523331634,73.27410993474403,83.75\ \072138781687 2026-10-23,"drift 0.1 ppm, sequential order",ts0,10000,72.9213736904\ \8497,6.848207386938218,-2.0786263095150304,73.24220091946601,84.082\ \588469154 2026-10-23,"drift 0.1 ppm, sequential order",tare_t0,10000,74.289887\ \22330892,45.301274239484314,-0.7101127766910764,87.01142207106004,1\ \44.5111059527595 2026-10-23,"drift 1 ppm, sequential order",base1,10000,87.3495154450\ \0777,9.146555301312995,-20.050484554992238,87.82704000710851,102.15\ \736299465063 2026-10-23,"drift 1 ppm, sequential order",base6,10000,107.368729234\ \72151,3.751380393745859,-0.03127076527849226,107.43423786229435,113\ \.49582394671278 2026-10-23,"drift 1 ppm, sequential order",tare90,10000,89.737357230\ \2883,6.1669359615080825,-17.66264276971171,89.94898875873925,99.802\ \34356959727 2026-10-23,"drift 1 ppm, sequential order",tare0,10000,54.6914371407\ \6866,6.7671178227071564,-20.308562859231337,55.10846215202061,65.66\ \835426376657 2026-10-23,"drift 1 ppm, sequential order",ts0,10000,54.471301697128\ \2,7.313529461292046,-20.528698302871803,54.96003159560073,66.430209\ \25358651 2026-10-23,"drift 1 ppm, sequential order",tare_t0,10000,75.52196418\ \391782,45.07188865598309,0.5219641839178166,87.94793387965177,140.3\ \120832397408 2026-10-23,"drift 5 ppm, sequential order",base1,10000,7.45505877613\ \2406,14.681597397417752,-99.9449412238676,16.465286167122592,31.018\ \07828368379 2026-10-23,"drift 5 ppm, sequential order",base6,10000,107.404445391\ \62694,5.8581625070897845,0.004445391626930473,107.5640717248824,116\ \.94195627988077 2026-10-23,"drift 5 ppm, sequential order",tare90,10000,18.740493307\ \672335,9.729470172394374,-88.65950669232767,21.11537858982026,34.87\ \186430682102 2026-10-23,"drift 5 ppm, sequential order",tare0,10000,-26.950841664\ \256714,10.679243634033284,-101.95084166425671,28.989355052888236,44\ \.43949211627997 2026-10-23,"drift 5 ppm, sequential order",ts0,10000,-27.65696845135\ \158,12.70984479877511,-102.65696845135159,30.437343916848704,48.084\ \641498642426 2026-10-23,"drift 5 ppm, sequential order",tare_t0,10000,75.16217359\ \27848,43.25346171032368,0.16217359278479648,86.71809040173427,140.5\ \7543685826874 2026-10-23,"drift 1 ppm, randomized order",base1,10000,107.320449975\ \00644,16.59942808843529,-0.07955002499356567,108.596466064047,133.5\ \687638495818 2026-10-23,"drift 1 ppm, randomized order",base6,10000,107.357257894\ \2108,6.396691104917148,-0.0427421057892019,107.54763776062262,117.9\ \3535254617031 2026-10-23,"drift 1 ppm, randomized order",tare90,10000,107.52210419\ \833507,10.892922530451527,0.12210419833506592,108.07241455115138,12\ \5.26415732437714 2026-10-23,"drift 1 ppm, randomized order",tare0,10000,75.1310441661\ \4286,11.9793620246121,0.13104416614285697,76.07998791732406,94.7053\ \1864072693 2026-10-23,"drift 1 ppm, randomized order",ts0,10000,75.126903949336\ \45,13.777652798630424,0.12690394933645166,76.37968598574341,97.5076\ \1281212831 2026-10-23,"drift 1 ppm, randomized order",tare_t0,10000,75.04449677\ \796254,8.293904124043067,0.044496777962535816,75.50138053964237,87.\ \5757067610097 2026-10-23,"drift 5 ppm, randomized order",base1,10000,107.560287710\ \69867,69.1134211513356,0.1602877106986682,127.84914082289264,214.93\ \26475137432 2026-10-23,"drift 5 ppm, randomized order",base6,10000,107.346992658\ \56673,26.936514779197243,-0.053007341433271904,110.67465881449759,1\ \51.7216114539863 2026-10-23,"drift 5 ppm, randomized order",tare90,10000,107.79001040\ \985175,46.29650385997894,0.3900104098517403,117.31086171870882,184.\ \69266740323977 2026-10-23,"drift 5 ppm, randomized order",tare0,10000,75.4433995435\ \3828,50.979331271905366,0.44339954353827693,91.0512979720494,159.89\ \228795771217 2026-10-23,"drift 5 ppm, randomized order",ts0,10000,75.341087038689\ \55,60.12757254283643,0.34108703868955104,96.3910931754976,173.87065\ \616241603 2026-10-23,"drift 5 ppm, randomized order",tare_t0,10000,75.14384178\ \876436,8.161874190828872,0.14384178876436238,75.58575585031043,88.0\ \0195251906217 2026-10-23,"path step +50 us mid-window, sequential",base1,10000,111\ \.9720203353208,17.085397018430676,4.572020335320801,113.26789014620\ \059,156.79138812874024 2026-10-23,"path step +50 us mid-window, sequential",base6,10000,132\ \.8951632417654,15.265528677198335,25.495163241765397,133.7689705246\ \0728,157.2568577512812 2026-10-23,"path step +50 us mid-window, sequential",tare90,10000,11\ \4.21577200762813,19.57114043451596,6.8157720076281265,115.880256343\ \57322,156.3442540948604 2026-10-23,"path step +50 us mid-window, sequential",tare0,10000,79.\ \02001723237532,20.64439482598379,4.020017232375324,81.6719752548707\ \9,123.71063703833104 2026-10-23,"path step +50 us mid-window, sequential",ts0,10000,82.30\ \064867299824,22.3645386874593,7.300648672998236,85.28493035372708,1\ \26.08493426323285 2026-10-23,"path step +50 us mid-window, sequential",tare_t0,10000,9\ \8.29561392187853,92.7282151574516,23.295613921878527,135.1284194770\ \9228,239.7521271165904 2026-10-23,"path step +50 us mid-window, randomized",base1,10000,133\ \.13834233678398,26.4759357218637,25.738342336783973,135.74506722167\ \737,168.12294170914777 2026-10-23,"path step +50 us mid-window, randomized",base6,10000,133\ \.12855273628202,16.96328217679465,25.728552736282012,134.2048274860\ \9442,159.0876012236855 2026-10-23,"path step +50 us mid-window, randomized",tare90,10000,13\ \2.9150174867677,20.59952429843814,25.515017486767704,134.5016722601\ \9747,164.21406031644014 2026-10-23,"path step +50 us mid-window, randomized",tare0,10000,100\ \.50024256820386,21.682980562506874,25.50024256820386,102.8124670804\ \9203,133.83239344337724 2026-10-23,"path step +50 us mid-window, randomized",ts0,10000,100.7\ \5247537076034,24.178567157838007,25.752475370760337,103.61276920742\ \331,134.25224308668473 2026-10-23,"path step +50 us mid-window, randomized",tare_t0,10000,1\ \00.61605494437771,21.69900577539814,25.61605494437771,102.929054593\ \56766,133.5704870526017 2026-10-23,shaper: +40 us forward for L>=1100 B,base1,10000,107.4902\ \0288714878,8.857422779982945,0.09020288714877722,107.85448442058374\ \,122.54629482991535 2026-10-23,shaper: +40 us forward for L>=1100 B,base6,10000,107.4593\ \4323654548,3.629870496051695,0.05934323654547313,107.5206263516532,\ \113.4170631557675 2026-10-23,shaper: +40 us forward for L>=1100 B,tare90,10000,103.530\ \87090040853,5.974282758599966,-3.8691290995914756,103.7030844028822\ \3,113.3734152534337 2026-10-23,shaper: +40 us forward for L>=1100 B,tare0,10000,69.55496\ \532493109,6.554883475443652,-5.445034675068911,69.86311904058729,80\ \.44481766948037 2026-10-23,shaper: +40 us forward for L>=1100 B,ts0,10000,70.4741011\ \5339623,7.3502520957216095,-4.525898846603766,70.8563316622389,82.1\ \2058878956057 2026-10-23,shaper: +40 us forward for L>=1100 B,tare_t0,10000,56.122\ \07859017205,52.000192616861185,-18.877921409827948,76.5077599689658\ \4,135.6155180364307 2026-10-23,"quadratic forward term, +30 us at 1400 B",base1,10000,10\ \7.40184304166394,8.825717921536546,0.0018430416639318992,107.763822\ \29787075,122.03270328171797 2026-10-23,"quadratic forward term, +30 us at 1400 B",base6,10000,10\ \7.42745327379541,3.6796215253837077,0.027453273795401856,107.490445\ \98243186,113.39601414470326 2026-10-23,"quadratic forward term, +30 us at 1400 B",tare90,10000,1\ \05.81169373061252,5.983265064578664,-1.5883062693874876,105.9807077\ \3035944,115.75294391153614 2026-10-23,"quadratic forward term, +30 us at 1400 B",tare0,10000,72\ \.38924707235698,6.5655719540845645,-2.61075292764302,72.68635027371\ \714,83.31516380291136 2026-10-23,"quadratic forward term, +30 us at 1400 B",ts0,10000,72.5\ \5320857917452,6.938946130257995,-2.446791420825477,72.8842385817021\ \9,83.74432482616882 2026-10-23,"quadratic forward term, +30 us at 1400 B",tare_t0,10000,\ \66.53219421378982,44.60768989297689,-8.467805786210178,80.101060416\ \76154,135.48511543836398 2026-10-23,"fragmentation at >=1300 B (+30 us, +20 B hdr)",base1,100\ \00,107.3231077617425,9.002564109762847,-0.07689223825749991,107.699\ \98846598325,122.00100552219531 2026-10-23,"fragmentation at >=1300 B (+30 us, +20 B hdr)",base6,100\ \00,107.42118778477548,3.687246769300956,0.02118778477547778,107.484\ \44545259022,113.42568809770917 2026-10-23,"fragmentation at >=1300 B (+30 us, +20 B hdr)",tare90,10\ \000,103.83859082770982,5.89197094841486,-3.5614091722901833,104.005\ \59982620813,113.36960115711936 2026-10-23,"fragmentation at >=1300 B (+30 us, +20 B hdr)",tare0,100\ \00,70.34551460505813,6.460757062370396,-4.654485394941872,70.641550\ \32791419,80.7224288133247 2026-10-23,"fragmentation at >=1300 B (+30 us, +20 B hdr)",ts0,10000\ \,71.3951850854967,6.935086163395787,-3.6048149145032937,71.73118613\ \228172,82.35480991415153 2026-10-23,"fragmentation at >=1300 B (+30 us, +20 B hdr)",tare_t0,1\ \0000,55.64693746414525,56.58192423318647,-19.353062535854747,79.358\ \52599219288,141.31658182231175 2026-10-23,iid packet loss 20%,base1,10000,107.31046367224008,10.711\ \809772411806,-0.08953632775993015,107.84371566236315,124.3852629470\ \7921 2026-10-23,iid packet loss 20%,base6,10000,107.38837995374973,4.3124\ \66228054635,-0.011620046250271798,107.47492570047457,114.4646165886\ \3291 2026-10-23,iid packet loss 20%,tare90,10000,107.37877989530251,7.054\ \966157438488,-0.021220104697491138,107.61026875736198,118.893852823\ \00368 2026-10-23,iid packet loss 20%,tare0,10000,74.97422083654746,7.73717\ \6582370022,-0.025779163452540388,75.37235371888035,87.59472042471418 2026-10-23,iid packet loss 20%,ts0,10000,74.97895679423895,7.9320796\ \45735273,-0.021043205761046124,75.39731797398294,87.90996670143198 2026-10-23,iid packet loss 20%,tare_t0,10000,74.70072059459562,51.12\ \934085901623,-0.29927940540437703,90.52152082836238,154.09287107398\ \765 2026-10-23,size-dependent loss 2%..32%,base1,10000,107.4514949590377\ \,9.203191967716991,0.051494959037697186,107.84486098768228,122.6839\ \6227274638 2026-10-23,size-dependent loss 2%..32%,base6,10000,107.3414258539636\ \6,3.7708137423037873,-0.05857414603634936,107.40763156655815,113.62\ \819150751318 2026-10-23,size-dependent loss 2%..32%,tare90,10000,107.348493296101\ \6,6.439574396063519,-0.05150670389841139,107.54144775170998,118.041\ \42339445714 2026-10-23,size-dependent loss 2%..32%,tare0,10000,74.93178057012753\ \,7.1137833644263475,-0.06821942987247098,75.26866939553506,86.82353\ \611143745 2026-10-23,size-dependent loss 2%..32%,ts0,10000,74.92054590047516,7\ \.420326866207989,-0.07945409952483828,75.28707686383828,87.12159662\ \228184 2026-10-23,size-dependent loss 2%..32%,tare_t0,10000,74.985032582182\ \58,50.38782366703389,-0.014967417817416617,90.34065525539259,150.90\ \398740898357 2026-10-23,length-label noise 10%,base1,10000,107.47719983393307,8.8\ \4107021109682,0.07719983393306507,107.84018355960119,121.7199546663\ \1036 2026-10-23,length-label noise 10%,base6,10000,107.3643310979557,3.67\ \9514717760834,-0.03566890204430706,107.42735716188321,113.409509965\ \06885 2026-10-23,length-label noise 10%,tare90,10000,125.84086998037,46.90\ \122420443474,18.440869980369996,134.2960513820412,230.21552526613982 2026-10-23,length-label noise 10%,tare0,10000,96.12156851268313,52.4\ \8361233625839,21.121568512683126,109.5153415930604,210.932609580902\ \44 2026-10-23,length-label noise 10%,ts0,10000,79.70242930422776,28.201\ \44676026799,4.702429304227763,84.54418551389396,96.06698894351213 2026-10-23,length-label noise 10%,tare_t0,10000,174.01200975239024,1\ \19.92051276305703,99.01200975239024,211.32834837399915,355.77123500\ \683837 2026-10-23,queue asymmetry fwd 150 us / rev 20 us,base1,10000,112.46\ \511894783866,11.62407011018761,5.065118947838656,113.06417856234336\ \,133.39391284634692 2026-10-23,queue asymmetry fwd 150 us / rev 20 us,base6,10000,112.62\ \577876410928,4.811047685257853,5.225778764109279,112.72847868854585\ \,120.88104590675934 2026-10-23,queue asymmetry fwd 150 us / rev 20 us,tare90,10000,112.6\ \3812378776628,8.000662225849123,5.23812378776627,112.92188063179204\ \,126.62717511901069 2026-10-23,queue asymmetry fwd 150 us / rev 20 us,tare0,10000,80.242\ \14889546032,8.782827297606028,5.242148895460318,80.72132804219255,9\ \5.49808215173785 2026-10-23,queue asymmetry fwd 150 us / rev 20 us,ts0,10000,79.43947\ \979062125,8.936554003644119,4.439479790621249,79.94050888419979,95.\ \59559062227903 2026-10-23,queue asymmetry fwd 150 us / rev 20 us,tare_t0,10000,80.1\ \7184429065529,57.26711426306298,5.171844290655287,98.52268287428122\ \,169.5517144528911 2026-10-23,length-dependent forward queue (x2 at 700 B),base1,10000,\ \107.48002751507508,9.535572673710542,0.08002751507507355,107.902151\ \82350299,123.01495917850325 2026-10-23,length-dependent forward queue (x2 at 700 B),base6,10000,\ \107.59909378511901,3.871877246298984,0.199093785119004,107.66872766\ \799979,113.9590944218608 2026-10-23,length-dependent forward queue (x2 at 700 B),tare90,10000\ \,107.56649141139663,7.296997094301871,0.1664914113966205,107.813686\ \12813334,119.37769045621634 2026-10-23,length-dependent forward queue (x2 at 700 B),tare0,10000,\ \74.94995470326515,8.112828979684785,-0.05004529673485081,75.3877120\ \1114747,87.97545788654323 2026-10-23,length-dependent forward queue (x2 at 700 B),ts0,10000,74\ \.87587656234865,8.24060734082144,-0.12412343765134892,75.3279344570\ \4414,88.1958022650552 2026-10-23,length-dependent forward queue (x2 at 700 B),tare_t0,1000\ \0,74.33465333603843,62.10462494688878,-0.6653466639615715,96.861960\ \68601312,169.80150520776283 2026-10-23,"outliers 5% (mean +2 ms, one direction)",base1,10000,107\ \.27037182645822,9.22474431023683,-0.12962817354178924,107.666243873\ \30081,122.649011819113 2026-10-23,"outliers 5% (mean +2 ms, one direction)",base6,10000,107\ \.36662740976976,3.797355600071082,-0.033372590230243304,107.4337523\ \7284955,113.55877757342698 2026-10-23,"outliers 5% (mean +2 ms, one direction)",tare90,10000,10\ \7.42628950014912,6.217776656591957,0.026289500149118794,107.6060618\ \935869,117.39500839838122 2026-10-23,"outliers 5% (mean +2 ms, one direction)",tare0,10000,75.\ \02666411754016,6.818532091685181,0.02666411754016451,75.33583515999\ \236,85.95173985201274 2026-10-23,"outliers 5% (mean +2 ms, one direction)",ts0,10000,75.00\ \162263615142,7.102856320125174,0.0016226361514242171,75.33716825646\ \697,86.49228679381335 2026-10-23,"outliers 5% (mean +2 ms, one direction)",tare_t0,10000,7\ \5.71687117584304,46.264862991669865,0.716871175843039,88.7314379717\ \9458,146.9324472720637 2026-10-23,outliers 30%,base1,10000,107.31667626788199,12.1924617488\ \68384,-0.0833237321180178,108.00699173234415,126.45097456622874 2026-10-23,outliers 30%,base6,10000,107.42999805819153,4.81941381912\ \4463,0.02999805819152357,107.53803471176161,115.15462906621364 2026-10-23,outliers 30%,tare90,10000,107.3711799843587,7.90211686293\ \0065,-0.02882001564130121,107.66154140547991,120.25151629029783 2026-10-23,outliers 30%,tare0,10000,74.97935815589001,8.656009061826\ \511,-0.020641844109988483,75.47730221529095,89.11395300903834 2026-10-23,outliers 30%,ts0,10000,74.9520692382415,8.872631289561616\ \,-0.047930761758493645,75.47534959664684,89.34811448088035 2026-10-23,outliers 30%,tare_t0,10000,74.73777634571724,57.373874765\ \283425,-0.2622236542827636,94.21872182604855,162.32493564945338 2026-10-23,symmetric encapsulation +66 B (L = payload),base1,10000,1\ \31.07763821916816,8.819470977744194,23.67763821916816,131.373979657\ \82864,145.4613901157737 2026-10-23,symmetric encapsulation +66 B (L = payload),base6,10000,1\ \31.16699840350915,3.6229785578651894,23.76699840350915,131.21701921\ \328483,137.0985726707178 2026-10-23,symmetric encapsulation +66 B (L = payload),tare90,10000,\ \131.18801557216105,5.967838936867949,23.788015572161044,131.3236725\ \416549,140.9750831270424 2026-10-23,symmetric encapsulation +66 B (L = payload),tare0,10000,9\ \8.79576905740502,6.539617528856273,23.795769057405025,99.0119503111\ \0178,109.53581314728673 2026-10-23,symmetric encapsulation +66 B (L = payload),ts0,10000,98.\ \81624184733644,6.864496643113834,23.816241847336443,99.054360100215\ \65,110.06054668849127 2026-10-23,symmetric encapsulation +66 B (L = payload),tare_t0,10000\ \,98.77486536084808,44.950101354518075,23.774865360848082,108.520890\ \0980541,168.27988033466278 2026-10-23,forward-only tunnel +50 B,base1,10000,127.40480482190563,\ \8.831265817028074,20.004804821905623,127.71048409787382,142.2010736\ \3436603 2026-10-23,forward-only tunnel +50 B,base6,10000,127.42973085805647,\ \3.643375886258205,20.029730858056467,127.48179935577664,133.3745876\ \489423 2026-10-23,forward-only tunnel +50 B,tare90,10000,127.39086721741164\ \,5.9787960684828665,19.990867217411633,127.53107651953881,137.11130\ \70719768 2026-10-23,forward-only tunnel +50 B,tare0,10000,94.98851911424349,6\ \.555588944630524,19.988519114243488,95.21444329697738,105.625153279\ \67158 2026-10-23,forward-only tunnel +50 B,ts0,10000,94.95486319394824,6.8\ \93207453832256,19.954863193948242,95.20471417714616,106.31364921605\ \554 2026-10-23,forward-only tunnel +50 B,tare_t0,10000,94.65300425217072\ \,42.80917514995776,19.653004252170717,103.88278696893681,160.624361\ \69756756 2026-10-23,NTPv4-style fixed 90 B response,base1,10000,107.379592248\ \41617,9.0167222352235,-0.020407751583832123,107.75745905121977,122.\ \40318606250635 2026-10-23,NTPv4-style fixed 90 B response,base6,10000,107.366253097\ \60794,3.6295612494835403,-0.03374690239206757,107.4275788692637,113\ \.30013671944906 2026-10-23,NTPv4-style fixed 90 B response,tare90,10000,107.33969952\ \785196,5.986218828851729,-0.06030047214804313,107.50647574502128,11\ \7.24110043464331 2026-10-23,NTPv4-style fixed 90 B response,tare0,10000,71.3367893129\ \4679,6.572237676419196,-3.6632106870532084,71.63886862677478,82.218\ \62831794897 2026-10-23,NTPv4-style fixed 90 B response,ts0,10000,71.379108468134\ \33,6.866160163691823,-3.6208915318656665,71.70855295349095,82.67879\ \913749093 2026-10-23,NTPv4-style fixed 90 B response,tare_t0,10000,70.96159627\ \207027,46.5985959476657,-4.038403727929733,84.8926389439018,137.106\ \3910737971 2026-10-23,server rx timestamp lag 0.01 us/B,base1,10000,107.8361781\ \7313242,8.903715077409084,0.4361781731324186,108.20309393706367,122\ \.54445730132485 2026-10-23,server rx timestamp lag 0.01 us/B,base6,10000,107.8371219\ \6352323,3.6995906502705433,0.4371219635232251,107.9005582731538,113\ \.83131296343885 2026-10-23,server rx timestamp lag 0.01 us/B,tare90,10000,107.965805\ \77342289,5.975346469871526,0.5658057734228805,108.13101502928258,11\ \7.82428641898096 2026-10-23,server rx timestamp lag 0.01 us/B,tare0,10000,75.12254341\ \76746,6.550382721609414,0.1225434176746063,75.40755766227007,85.834\ \13358241897 2026-10-23,server rx timestamp lag 0.01 us/B,ts0,10000,75.1135577315\ \117,6.853316034232664,0.11355773151170467,75.42552485038567,86.2468\ \6213713227 2026-10-23,server rx timestamp lag 0.01 us/B,tare_t0,10000,75.219426\ \49527253,44.26531637750409,0.2194264952725291,87.27648259671581,143\ \.1533638104711 2026-10-23,adversary: fwd delay 0.05 us/B on every packet,base1,1000\ \0,109.66156034312232,8.948480118863568,2.261560343122312,110.026020\ \13067776,124.40975079343846 2026-10-23,adversary: fwd delay 0.05 us/B on every packet,base6,1000\ \0,109.66777952048622,3.638691606305587,2.267779520486215,109.728121\ \36162777,115.64813381723187 2026-10-23,adversary: fwd delay 0.05 us/B on every packet,tare90,100\ \00,109.65543400181271,5.9575197254644126,2.255434001812702,109.8171\ \3299026285,119.43074900980193 2026-10-23,adversary: fwd delay 0.05 us/B on every packet,tare0,1000\ \0,75.00432084946102,6.531628170745785,0.004320849461024068,75.28815\ \342690454,85.68727865662245 2026-10-23,adversary: fwd delay 0.05 us/B on every packet,ts0,10000,\ \75.00029809370533,6.864354766908759,0.0002980937053251864,75.313739\ \57369269,86.15298598177802 2026-10-23,adversary: fwd delay 0.05 us/B on every packet,tare_t0,10\ \000,74.74297869951941,45.37561822031554,-0.2570213004805879,87.4371\ \4141644703,143.57338203030673 2026-10-23,adversary: +200 us fwd on 90 B packets only,base1,10000,2\ \07.3447011223797,8.79096893274928,99.94470112237968,207.53095790795\ \177,221.6672421611448 2026-10-23,adversary: +200 us fwd on 90 B packets only,base6,10000,2\ \07.35614981264933,3.590969033645961,99.95614981264933,207.387238359\ \11557,213.33903173287882 2026-10-23,adversary: +200 us fwd on 90 B packets only,tare90,10000,\ \152.29873266030657,5.961055214796842,44.898732660306564,152.4153358\ \287527,162.0888125759671 2026-10-23,adversary: +200 us fwd on 90 B packets only,tare0,10000,1\ \24.13859082246859,6.533307910337464,49.138590822468586,124.31037597\ \573396,134.82856369340442 2026-10-23,adversary: +200 us fwd on 90 B packets only,ts0,10000,88.\ \80578906058017,12.385939920232648,13.805789060580167,89.66529059356\ \861,111.70181485667615 2026-10-23,adversary: +200 us fwd on 90 B packets only,tare_t0,10000\ \,-24.265944807723937,153.46629538686963,-99.26594480772394,155.3653\ \2659122963,316.73899500522253 2026-10-23,adversary: +200 us fwd on 1400 B packets only,base1,10000\ \,107.2013665038702,8.919436632836964,-0.1986334961298013,107.571749\ \89052338,121.85137641283792 2026-10-23,adversary: +200 us fwd on 1400 B packets only,base6,10000\ \,107.35571442664015,3.6564793386018137,-0.04428557335985772,107.417\ \9590395564,113.28485985030635 2026-10-23,adversary: +200 us fwd on 1400 B packets only,tare90,1000\ \0,90.53843305071119,5.977383855085858,-16.861566949288814,90.735513\ \4669848,100.35759235509434 2026-10-23,adversary: +200 us fwd on 1400 B packets only,tare0,10000\ \,53.10725852711643,6.557632184288793,-21.89274147288357,53.51055174\ \333763,63.8115471030983 2026-10-23,adversary: +200 us fwd on 1400 B packets only,ts0,10000,6\ \8.54501364580511,8.382708841892214,-6.454986354194887,69.0556418857\ \3439,80.9780266043166 2026-10-23,adversary: +200 us fwd on 1400 B packets only,tare_t0,100\ \00,-8.76228531104771,156.6200642910472,-83.7622853110477,156.857161\ \76811982,308.57555873428083
Produced by the script of Section F.4. Reproduced in: Table C-2.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,scenario,frac_rejected_by_gate,frac_fit_available,frac_bad\ \_among_all,false_valid_rate,accepted_mean_err_vs_75,accepted_sd,mea\ \n_slope,nominal_slope,median_p_curv 2026-10-23,nominal,0.011199999999999988,1.0,0.0007,0.0007,-0.0069040\ \0147930916,6.5689845824742665,0.36003923787477515,0.36,0.4905423392\ \0969736 2026-10-23,"drift 0.1 ppm, sequential order",0.009000000000000008,1.\ \0,0.0011,0.0011,-2.0253242414116657,6.535189316613825,0.36288874865\ \81604,0.36,0.49260972032053496 2026-10-23,"drift 1 ppm, sequential order",0.01419999999999999,1.0,0\ \.2287,0.2251,-20.3043423317903,6.768408056107253,0.3893991121057736\ \,0.36,0.4824083889575322 2026-10-23,"drift 5 ppm, sequential order",0.12350000000000005,1.0,1\ \.0,0.8765,-101.88742781875878,10.801204319803015,0.5076814996881006\ \,0.36,0.3791380216182796 2026-10-23,"drift 1 ppm, randomized order",0.11050000000000004,1.0,0\ \.034,0.0311,0.14447866597171263,12.098786869429427,0.35990066702435\ \797,0.36,0.5061246466612312 2026-10-23,"drift 5 ppm, randomized order",0.9904,1.0,0.6363,0.0075,\ \-2.1202396697999077,75.63849341222092,0.35940678740348303,0.36,0.50\ \90241318780732 2026-10-23,"path step +50 us mid-window, sequential",0.1435999999999\ \9995,1.0,0.1917,0.1623,3.814778825031893,21.06727457320795,0.391063\ \94194725347,0.36,0.2872586565694124 2026-10-23,"path step +50 us mid-window, randomized",0.486,1.0,0.516\ \8,0.272,26.172401849090793,25.360841864591308,0.36016416576182053,0\ \.36,0.4892236600363379 2026-10-23,shaper: +40 us forward for L>=1100 B,0.015599999999999947\ \,1.0,0.0026,0.0026,-5.452873526481344,6.546933716794406,0.377510061\ \94974934,0.36,0.4400188313560851 2026-10-23,"quadratic forward term, +30 us at 1400 B",0.013499999999\ \999956,1.0,0.0016,0.0016,-2.610548702367001,6.565459334575394,0.371\ \36051842506146,0.36,0.46368594532465085 2026-10-23,"fragmentation at >=1300 B (+30 us, +20 B hdr)",0.0322000\ \00000000006,1.0,0.002,0.0018,-4.676623201731776,6.431286887352099,0\ \.3721452913627967,0.36,0.2559573178795847 2026-10-23,iid packet loss 20%,0.018299999999999983,1.0,0.0035,0.003\ \,0.008968904728534103,7.669945088189061,0.3600506562083894,0.36,0.4\ \946962284512907 2026-10-23,size-dependent loss 2%..32%,0.016700000000000048,1.0,0.00\ \12,0.0011,-0.075744543029013,7.091580139085991,0.36018569695526736,\ \0.36,0.4833686182777541 2026-10-23,length-label noise 10%,0.4548,1.0,0.3145,0.0057,0.0985442\ \0153770511,7.40469527138702,0.3302144607520764,0.36,0.5348010766339\ \137 2026-10-23,queue asymmetry fwd 150 us / rev 20 us,0.0362000000000000\ \1,1.0,0.0223,0.0167,5.029838268141658,8.539051113297777,0.359955276\ \5811776,0.36,0.5009255093568354 2026-10-23,length-dependent forward queue (x2 at 700 B),0.0456999999\ \9999996,1.0,0.0045,0.0036,-0.08854436925912554,7.981382975559291,0.\ \3624059634236828,0.36,0.45973949701964856 2026-10-23,"outliers 5% (mean +2 ms, one direction)",0.0113999999999\ \99966,1.0,0.0009,0.0009,0.028442752806790986,6.80995066185115,0.359\ \995837584544,0.36,0.4911255331655068 2026-10-23,outliers 30%,0.030299999999999994,1.0,0.0088,0.0067,-0.01\ \578147641986134,8.48273894050102,0.3599091314274301,0.36,0.48756980\ \918753123 2026-10-23,symmetric encapsulation +66 B (L = payload),0.00919999999\ \9999986,1.0,0.42,0.4166,23.789875730076844,6.534443603694672,0.3599\ \138501639558,0.36,0.49292535852856334 2026-10-23,forward-only tunnel +50 B,0.012299999999999978,1.0,0.2136\ \,0.2111,19.987264529983847,6.551517150254236,0.36002609003520164,0.\ \36,0.491344368407889 2026-10-23,NTPv4-style fixed 90 B response,0.008600000000000052,1.0,\ \0.0017,0.0016,-3.6528035552276963,6.563182262640934,0.4000323357211\ \6825,0.36,0.4920555156894102 2026-10-23,server rx timestamp lag 0.01 us/B,0.010800000000000032,1.\ \0,0.0008,0.0008,0.13173175727891126,6.545196828746784,0.36492513728\ \6092,0.36,0.4943305202449827 2026-10-23,adversary: fwd delay 0.05 us/B on every packet,0.01090000\ \000000002,1.0,0.0009,0.0008,0.00643319229954513,6.511101731326142,0\ \.3850123683594632,0.36,0.5013585720542335 2026-10-23,adversary: +200 us fwd on 90 B packets only,0.9996,1.0,0.\ \9998,0.0004,41.81128985217287,9.66202657761693,0.31289046486486666,\ \0.36,0.2236482382373992 2026-10-23,adversary: +200 us fwd on 1400 B packets only,0.9936,1.0,\ \0.3087,0.0015,-20.509410888943346,6.215262218852488,0.4159019391510\ \5284,0.36,0.09331799367643742
Produced by the script of Section F.6. Reproduced in: Table C-3.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,scenario,overhead_B,predicted_shift_us,mean_err_vs_75,sd,f\ \rac_rejected_by_gate,frac_beyond_25us,false_valid_rate,accepted_mea\ \n_err_vs_75,mean_slope,median_p_curv 2026-10-24,no overhead (control),0.0,0.0,0.035394557258442205,6.5413\ \14462072287,0.011299999999999977,0.0006,0.0006,0.045617406490953354\ \,0.3599022131509252,0.49249343407002355 2026-10-24,"payload-only, symmetric overhead 28 B",28.0,10.08,10.133\ \604177197014,6.6093632568998695,0.009099999999999997,0.0157,0.0155,\ \10.129214658375998,0.35992265832363174,0.49433484795555127 2026-10-24,"payload-only, symmetric overhead 66 B",66.0,23.759999999\ \999998,23.744592399535847,6.584711978727442,0.010000000000000009,0.\ \4178,0.4139,23.744810109956845,0.36001195531160946,0.493352113673002 2026-10-24,"payload-only, symmetric overhead 100 B",100.0,36.0,35.90\ \016708754753,6.515753553377028,0.010299999999999976,0.9532,0.9436,3\ \5.90491283338781,0.360052851087162,0.5046912354071931
Produced by the script of Section F.5. Reproduced in: Per-estimator distribution summaries for the hybrid scenarios; not tabulated elsewhere.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,scenario,estimator,n,mean,sd,mean_err_vs_75,rmse_vs_75,p95\ \_abs_err_vs_75,rmse_vs_true_offset 2026-10-23,nominal,base48,5000,107.47207388438466,3.2106415810739732\ \,32.472073884384656,32.630380630191645,37.823443665098985,107.52001\ \126640978 2026-10-23,nominal,base58 (fully loaded),5000,107.39418718194175,2.9\ \88052019572123,32.394187181941746,32.53167736774995,37.354385647512\ \984,107.43573944293695 2026-10-23,nominal,"ols_intercept_raw (orig, 1 window)",5000,75.0464\ \0163682264,6.567761044491434,0.04640163682263676,6.567268165105756,\ \13.004402726773607,75.33318828163192 2026-10-23,nominal,ols_gated (orig gate),5000,75.49600667119374,7.50\ \4786984342197,0.4960066711937401,7.520411287468571,14.0636934395952\ \16,75.86802743324586 2026-10-23,nominal,hybrid_raw,5000,75.07170217557301,3.2129513526577\ \376,0.07170217557300873,3.213430096524301,6.727123498134083,75.1404\ \116259766 2026-10-23,nominal,hybrid_gated,5000,75.37597789912806,4.47982559604\ \8762,0.3759778991280598,4.495128806182554,7.06308282918277,75.50895\ \885822675 2026-10-23,"drift 1 ppm, sequential (neg. control)",base48,5000,107.\ \33106199933968,14.228450081145045,32.33106199933968,35.322880289671\ \19,54.487571174794134,108.26987194903019 2026-10-23,"drift 1 ppm, sequential (neg. control)",base58 (fully lo\ \aded),5000,107.3411828825811,16.887862979454802,32.341182882581094,\ \36.484174463377855,58.979829716440605,108.6612737761773 2026-10-23,"drift 1 ppm, sequential (neg. control)","ols_intercept_r\ \aw (orig, 1 window)",5000,54.596806309899385,6.792692355773483,-20.\ \403193690100615,21.50399390955217,31.425557352718112,55.01765807944\ \723 2026-10-23,"drift 1 ppm, sequential (neg. control)",ols_gated (orig \ \gate),5000,55.26037174392515,9.104710204848413,-19.73962825607485,2\ \1.737803303294395,31.93291352566301,56.00524845085047 2026-10-23,"drift 1 ppm, sequential (neg. control)",hybrid_raw,5000,\ \73.6012817455373,14.228153160352974,-1.3987182544626933,14.29532325\ \767272,24.27190683535942,74.96364804938428 2026-10-23,"drift 1 ppm, sequential (neg. control)",hybrid_gated,500\ \0,73.62148727120959,14.241113217933378,-1.3785127287904118,14.30625\ \8811034308,24.27190683535942,74.98594622894169 2026-10-23,"drift 1 ppm, randomized",base48,5000,107.36962065873519,\ \14.267477045983545,32.36962065873519,35.3738961759633,54.5758264634\ \6167,108.31322924499163 2026-10-23,"drift 1 ppm, randomized",base58 (fully loaded),5000,107.\ \51782691249173,16.782879285318757,32.51782691249173,36.592591753098\ \48,58.66770675581011,108.81953780494884 2026-10-23,"drift 1 ppm, randomized","ols_intercept_raw (orig, 1 win\ \dow)",5000,75.03711642656788,12.150431465773751,0.03711642656787717\ \,12.14927305794981,23.827664637152715,76.01429010272875 2026-10-23,"drift 1 ppm, randomized",ols_gated (orig gate),5000,78.4\ \8940610068713,16.06522134851812,3.489406100687134,16.43823815513693\ \,35.29538224309208,80.11633159817086 2026-10-23,"drift 1 ppm, randomized",hybrid_raw,5000,74.968398896143\ \82,14.27580109775702,-0.03160110385617543,14.27440842602904,23.9774\ \4388647323,76.31525778201016 2026-10-23,"drift 1 ppm, randomized",hybrid_gated,5000,75.3245359335\ \3078,14.709977665188344,0.32453593353078247,14.71208652074581,24.36\ \3938662119637,76.74715551617226 2026-10-23,"drift 5 ppm, randomized",base48,5000,107.0361119208365,6\ \9.06513245619675,32.036111920836504,76.12720269189015,139.849351536\ \85413,127.38040578447534 2026-10-23,"drift 5 ppm, randomized",base58 (fully loaded),5000,106.\ \5656539164254,83.31660550877665,31.565653916425404,89.0879280785334\ \7,161.75820491918205,135.2645815311228 2026-10-23,"drift 5 ppm, randomized","ols_intercept_raw (orig, 1 win\ \dow)",5000,74.62979207231322,49.96974582083732,-0.3702079276867778,\ \49.966120083605965,96.67832922386974,89.81136880738605 2026-10-23,"drift 5 ppm, randomized",ols_gated (orig gate),5000,106.\ \81193675331096,69.10256841498607,31.81193675331096,76.0671364555823\ \,139.80453138249118,127.21241984000156 2026-10-23,"drift 5 ppm, randomized",hybrid_raw,5000,74.629478886093\ \2,69.0616929892043,-0.3705211139068041,69.05578050346875,113.875084\ \81612728,101.67655901857239 2026-10-23,"drift 5 ppm, randomized",hybrid_gated,5000,75.0692428405\ \1455,69.18685436298135,0.06924284051454777,69.17996998446895,114.05\ \203285035869,102.08454669110898 2026-10-23,"path step +50 us, randomized",base48,5000,132.6056286847\ \6282,25.2392054571124,57.60562868476282,62.891164282231884,86.41860\ \373436914,134.98571349401794 2026-10-23,"path step +50 us, randomized",base58 (fully loaded),5000\ \,132.81670363923598,25.22427384970892,57.81670363923598,63.07858557\ \509122,86.18526198871061,135.1902862784139 2026-10-23,"path step +50 us, randomized","ols_intercept_raw (orig, \ \1 window)",5000,100.64425545312488,21.85364980690612,25.64425545312\ \4885,33.69145783764836,58.85991049094266,102.98908995226034 2026-10-23,"path step +50 us, randomized",ols_gated (orig gate),5000\ \,115.58854589935306,29.61601166537837,40.588545899353065,50.2430371\ \649478,84.5787237812969,119.32160185172374 2026-10-23,"path step +50 us, randomized",hybrid_raw,5000,100.209032\ \14940755,25.238941162113363,25.209032149407548,35.670324529842546,5\ \4.00040712156317,103.33792563466436 2026-10-23,"path step +50 us, randomized",hybrid_gated,5000,100.2412\ \4704797,25.254941043414444,25.241247047970006,35.704412013553345,54\ \.01851809166925,103.37307238555442 2026-10-23,"path step +50 us, sequential (neg. control)",base48,5000\ \,133.04636607169522,25.195713151085386,58.04636607169522,63.2777813\ \3380458,86.21758279770889,135.4106071224964 2026-10-23,"path step +50 us, sequential (neg. control)",base58 (ful\ \ly loaded),5000,132.3511401830933,25.239319980306572,57.35114018309\ \329,62.65819298954054,86.1088532989731,134.735742014428 2026-10-23,"path step +50 us, sequential (neg. control)","ols_interc\ \ept_raw (orig, 1 window)",5000,79.17619090529297,20.552726646051898\ \,4.1761909052929695,20.97070957669926,49.13692428963034,81.79975119\ \732462 2026-10-23,"path step +50 us, sequential (neg. control)",ols_gated (\ \orig gate),5000,86.5470449442895,28.493022727663284,11.547044944289\ \496,30.741246244024428,81.29264729337652,91.11575583991592 2026-10-23,"path step +50 us, sequential (neg. control)",hybrid_raw,\ \5000,99.26567523321043,25.196749787787375,24.26567523321043,34.9795\ \97183958994,52.42766882633067,102.41300456550232 2026-10-23,"path step +50 us, sequential (neg. control)",hybrid_gate\ \d,5000,99.26567523321043,25.196749787787375,24.26567523321043,34.97\ \9597183958994,52.42766882633067,102.41300456550232 2026-10-23,shaper +10 us fwd for L>=1100,base48,5000,107.44665954382\ \357,3.1852378455204415,32.44665954382357,32.60259846296467,37.78967\ \9238541794,107.49385265265563 2026-10-23,shaper +10 us fwd for L>=1100,base58 (fully loaded),5000,\ \107.42821140569882,2.9543758354984413,32.42821140569882,32.56248586\ \7678404,37.3721858369225,107.46881964894551 2026-10-23,shaper +10 us fwd for L>=1100,"ols_intercept_raw (orig, 1\ \ window)",5000,73.64454633607627,6.5417771409757774,-1.355453663923\ \7256,6.680085615290051,13.17623922674771,73.93446756580482 2026-10-23,shaper +10 us fwd for L>=1100,ols_gated (orig gate),5000,\ \74.03128301746352,7.453016578096058,-0.9687169825364776,7.514969009\ \543991,13.934158282729703,74.40542461295368 2026-10-23,shaper +10 us fwd for L>=1100,hybrid_raw,5000,74.64805861\ \096029,3.1886279178720742,-0.35194138903970895,3.20767474510005,6.5\ \28478296168182,74.71611585805566 2026-10-23,shaper +10 us fwd for L>=1100,hybrid_gated,5000,76.306610\ \06264677,7.825273736841733,1.3066100626467687,7.93283631058296,23.7\ \92985656417876,76.70672331241583 2026-10-23,shaper +40 us fwd for L>=1100,base48,5000,107.47920823786\ \625,3.151595419682103,32.479208237866246,32.63172589577973,37.84661\ \4461541805,107.52539593332003 2026-10-23,shaper +40 us fwd for L>=1100,base58 (fully loaded),5000,\ \107.43364299492468,2.8878129580050143,32.43364299492468,32.56192552\ \2147995,37.221316392198275,107.47244038798326 2026-10-23,shaper +40 us fwd for L>=1100,"ols_intercept_raw (orig, 1\ \ window)",5000,69.59068564851104,6.515534410574508,-5.4093143514889\ \59,8.467843879694163,15.99313357541319,69.89497283244002 2026-10-23,shaper +40 us fwd for L>=1100,ols_gated (orig gate),5000,\ \70.18271818409659,8.015811471528846,-4.817281815903414,9.3512879858\ \45463,17.641927401632834,70.63890085929074 2026-10-23,shaper +40 us fwd for L>=1100,hybrid_raw,5000,73.49465390\ \884967,3.1536300095348775,-1.5053460911503294,3.494203774071155,7.0\ \79371810902668,73.56226985583156 2026-10-23,shaper +40 us fwd for L>=1100,hybrid_gated,5000,106.76574\ \947512313,5.791396133125262,31.76574947512313,32.28926138568716,37.\ \79589289088814,106.92267683752448 2026-10-23,quadratic fwd term +5 us at 1400 B,base48,5000,107.328424\ \80748221,3.180072282500606,32.32842480748221,32.484425309415826,37.\ \593589843937345,107.37551680343778 2026-10-23,quadratic fwd term +5 us at 1400 B,base58 (fully loaded),\ \5000,107.4444638603258,2.89395265545671,32.4444638603258,32.5732485\ \6632536,37.25733327303773,107.48342244835939 2026-10-23,quadratic fwd term +5 us at 1400 B,"ols_intercept_raw (or\ \ig, 1 window)",5000,74.60502318059386,6.606660883338708,-0.39497681\ \940613916,6.617797603561209,13.220917159248616,74.89692064571668 2026-10-23,quadratic fwd term +5 us at 1400 B,ols_gated (orig gate),\ \5000,75.04210741462724,7.542878056700537,0.04210741462723888,7.5422\ \41272376893,14.290447870952905,75.42016650475408 2026-10-23,quadratic fwd term +5 us at 1400 B,hybrid_raw,5000,74.758\ \77979565799,3.1861329885693626,-0.24122020434201374,3.1949335390816\ \147,6.443260575533841,74.82663008359955 2026-10-23,quadratic fwd term +5 us at 1400 B,hybrid_gated,5000,75.0\ \7803149441101,4.523451746457066,0.07803149441100743,4.5236724343728\ \72,6.842597025073593,75.2141498420022 2026-10-23,quadratic fwd term +30 us at 1400 B,base48,5000,107.41055\ \467396761,3.1615675860801296,32.41055467396761,32.56436034645355,37\ \.53860509366256,107.45706475550512 2026-10-23,quadratic fwd term +30 us at 1400 B,base58 (fully loaded)\ \,5000,107.43630480120184,2.91369382314679,32.43630480120184,32.5668\ \8168875207,37.22159516662162,107.47579961605055 2026-10-23,quadratic fwd term +30 us at 1400 B,"ols_intercept_raw (o\ \rig, 1 window)",5000,72.38453799582172,6.527383419077316,-2.6154620\ \041782835,7.031276871812534,13.734825310903902,72.67819173466923 2026-10-23,quadratic fwd term +30 us at 1400 B,ols_gated (orig gate)\ \,5000,72.86462981681693,7.608572251260356,-2.1353701831830705,7.901\ \8098842946,14.562072737929146,73.26071984337908 2026-10-23,quadratic fwd term +30 us at 1400 B,hybrid_raw,5000,73.99\ \832638637182,3.167447067200363,-1.001673613628185,3.321756223381004\ \,6.777762557900879,74.06607200576619 2026-10-23,quadratic fwd term +30 us at 1400 B,hybrid_gated,5000,76.\ \22305467907152,8.872668714787967,1.2230546790715238,8.9556891426819\ \53,30.193584974466752,76.7376216068825 2026-10-23,fragmentation at >=1300 B,base48,5000,107.36126232297148,\ \3.2277186506810276,32.361262322971484,32.521798584804465,37.5458146\ \2022946,107.40976087691617 2026-10-23,fragmentation at >=1300 B,base58 (fully loaded),5000,107.\ \35850925096199,2.890941058603932,32.35850925096199,32.4873666159766\ \54,37.03090944794731,107.39741792652732 2026-10-23,fragmentation at >=1300 B,"ols_intercept_raw (orig, 1 win\ \dow)",5000,70.21478878765615,6.34961060746155,-4.785211212343853,7.\ \950329408405434,15.485104477012724,70.50124861199677 2026-10-23,fragmentation at >=1300 B,ols_gated (orig gate),5000,71.3\ \0779651655304,8.867308595310195,-3.69220348344696,9.604467838214417\ \,18.041606128346967,71.85690836612892 2026-10-23,fragmentation at >=1300 B,hybrid_raw,5000,73.851015576709\ \93,3.237062968097864,-1.1489844232900737,3.434624600893363,7.012801\ \727645803,73.9219113839432 2026-10-23,fragmentation at >=1300 B,hybrid_gated,5000,107.347905270\ \27512,3.308034998617323,32.34790527027512,32.516578576284125,37.545\ \81462022946,107.3988532194312 2026-10-23,length-label noise 10%,base48,5000,107.40908492837751,3.2\ \01690372814525,32.40908492837751,32.56681680750991,37.8332761849998\ \8,107.45678338862807 2026-10-23,length-label noise 10%,base58 (fully loaded),5000,107.418\ \36844556849,2.902212884073842,32.41836844556849,32.547991761845914,\ \37.22817456025631,107.45755922486079 2026-10-23,length-label noise 10%,"ols_intercept_raw (orig, 1 window\ \)",5000,97.42390151316998,53.89483348651972,22.42390151316998,58.36\ \8685996831616,137.7114890838865,111.33502922248786 2026-10-23,length-label noise 10%,ols_gated (orig gate),5000,90.4374\ \5016383932,17.08777509800817,15.437450163839316,23.02712589424851,3\ \6.479626146451764,92.03730793284572 2026-10-23,length-label noise 10%,hybrid_raw,5000,78.49182672896549,\ \3.376518862273072,3.491826728965492,4.857103391577973,9.28117947103\ \4562,78.56440327973797 2026-10-23,length-label noise 10%,hybrid_gated,5000,78.6437435324145\ \9,3.9421484777065623,3.6437435324145895,5.367894693767127,9.4431807\ \77214325,78.7424651843309 2026-10-23,symmetric +66 B overhead (L=payload),base48,5000,131.1693\ \5684437192,3.2456815410261983,56.16935684437192,56.26303395735443,6\ \1.56940840840994,131.20949857667395 2026-10-23,symmetric +66 B overhead (L=payload),base58 (fully loaded\ \),5000,131.22701512676107,2.874830864274701,56.227015126761074,56.3\ \0044608733315,61.08842773626421,131.2584949580288 2026-10-23,symmetric +66 B overhead (L=payload),"ols_intercept_raw (\ \orig, 1 window)",5000,98.80586718614343,6.498202601412822,23.805867\ \18614343,24.676659097331203,34.7390345284519,99.01927884067533 2026-10-23,symmetric +66 B overhead (L=payload),ols_gated (orig gate\ \),5000,99.16030447793976,7.291705575595193,24.16030447793976,25.236\ \454760403273,35.554712295562034,99.42798560045779 2026-10-23,symmetric +66 B overhead (L=payload),hybrid_raw,5000,98.7\ \6794378429591,3.2549619533093006,23.76794378429591,23.9897438522273\ \06,29.199757660798745,98.8215532044496 2026-10-23,symmetric +66 B overhead (L=payload),hybrid_gated,5000,99\ \.05919807505016,4.495662860836311,24.059198075050162,24.47553787715\ \1716,29.506803596500248,99.16113989680338 2026-10-23,forward-only tunnel +50 B,base48,5000,127.33435941668783,\ \3.1558247173935015,52.33435941668783,52.42940409117813,57.675388839\ \85344,127.37345220201587 2026-10-23,forward-only tunnel +50 B,base58 (fully loaded),5000,127.\ \36726988870522,2.9579893084023454,52.36726988870522,52.450728368679\ \18,57.27731947057362,127.40160669987938 2026-10-23,forward-only tunnel +50 B,"ols_intercept_raw (orig, 1 win\ \dow)",5000,95.02212886524869,6.681441506768205,20.02212886524869,21\ \.10730623677184,30.846732115620114,95.25669376143689 2026-10-23,forward-only tunnel +50 B,ols_gated (orig gate),5000,95.4\ \0262177458527,7.495989154444517,20.40262177458527,21.73581355067369\ \4,31.865089189959857,95.69659793794888 2026-10-23,forward-only tunnel +50 B,hybrid_raw,5000,94.933645246919\ \31,3.161687898924755,19.933645246919312,20.182776913649963,25.25731\ \7199951405,94.98626885494586 2026-10-23,forward-only tunnel +50 B,hybrid_gated,5000,95.2644329041\ \9445,4.498541232383055,20.26443290419445,20.757650800931327,25.5593\ \5351491697,95.37056675097706 2026-10-23,NTPv4-style fixed 90 B response,base48,5000,107.435037840\ \14862,3.19083718382026,32.435037840148624,32.591579976078734,37.661\ \79945378833,107.4824021008064 2026-10-23,NTPv4-style fixed 90 B response,base58 (fully loaded),500\ \0,107.40294361467964,2.8831941928533253,32.40294361467964,32.530937\ \5992771,37.03667665731009,107.44162807445728 2026-10-23,NTPv4-style fixed 90 B response,"ols_intercept_raw (orig,\ \ 1 window)",5000,71.2930848042953,6.662777244950206,-3.706915195704\ \6955,7.62397156105986,14.757712442228012,71.60368470273121 2026-10-23,NTPv4-style fixed 90 B response,ols_gated (orig gate),500\ \0,71.71718012586679,7.6381679454775835,-3.28281987413321,8.31305284\ \2813676,15.640574843338294,72.12270007735034 2026-10-23,NTPv4-style fixed 90 B response,hybrid_raw,5000,71.438041\ \26689513,3.1961649874298055,-3.5619587331048734,4.785496583332689,8\ \.840568515084684,71.50949005260321 2026-10-23,NTPv4-style fixed 90 B response,hybrid_gated,5000,71.8410\ \9502426472,4.9813123182869825,-3.1589049757352825,5.898066663200771\ \,9.329300671695007,72.01355041937086 2026-10-23,queue asymmetry fwd150/rev20,base48,5000,107.996240551742\ \77,3.8001553202252074,32.99624055174277,33.21430689883832,39.612327\ \91908962,108.06306614903926 2026-10-23,queue asymmetry fwd150/rev20,base58 (fully loaded),5000,1\ \07.81396251942029,3.3362968634795176,32.813962519420286,32.98309850\ \2291,38.572963670152745,107.86556060543549 2026-10-23,queue asymmetry fwd150/rev20,"ols_intercept_raw (orig, 1 \ \window)",5000,80.1280650794675,8.572960897978115,5.128065079467504,\ \9.9888943775477,20.096473927417716,80.5852826067262 2026-10-23,queue asymmetry fwd150/rev20,ols_gated (orig gate),5000,8\ \0.98990335608269,9.788045446093156,5.989903356082692,11.47456381320\ \2868,26.049238258446422,81.57910956927434 2026-10-23,queue asymmetry fwd150/rev20,hybrid_raw,5000,75.593198556\ \45197,3.811172979087074,0.5931985564519664,3.8566849749499674,7.849\ \428368885871,75.68919211131666 2026-10-23,queue asymmetry fwd150/rev20,hybrid_gated,5000,75.9111291\ \85396,4.972149736879352,0.9111291853960068,5.054451992434851,8.3638\ \2175867343,76.07375935730553 2026-10-23,length-dependent fwd queue (x2 at 700 B),base48,5000,107.\ \439611249601,3.4215556242745837,32.439611249601,32.61951991533086,3\ \8.09764727993918,107.49406851983423 2026-10-23,length-dependent fwd queue (x2 at 700 B),base58 (fully lo\ \aded),5000,107.49603174440921,3.0506792563397656,32.49603174440921,\ \32.63888573051979,37.62552539881413,107.5393026915802 2026-10-23,length-dependent fwd queue (x2 at 700 B),"ols_intercept_r\ \aw (orig, 1 window)",5000,74.96037386698805,8.126858003880878,-0.03\ \962613301195006,8.126141894002167,16.137550856012833,75.39953754586\ \074 2026-10-23,length-dependent fwd queue (x2 at 700 B),ols_gated (orig \ \gate),5000,76.36563317791153,10.143429875940857,1.3656331779115334,\ \10.23394087293906,21.919921519730092,77.03621565521988 2026-10-23,length-dependent fwd queue (x2 at 700 B),hybrid_raw,5000,\ \74.51097269766024,3.433701549635281,-0.489027302339764,3.4680103767\ \340507,7.094792996128615,74.59003285038939 2026-10-23,length-dependent fwd queue (x2 at 700 B),hybrid_gated,500\ \0,74.95921733225613,5.137715108996005,-0.04078266774386918,5.137363\ \1897974565,7.720123205321686,75.13504575351176 2026-10-23,outliers 5% (mean +2 ms),base48,5000,107.41577016433357,3\ \.260259572323597,32.415770164333566,32.57927749302199,37.8755785870\ \2386,107.46522622047264 2026-10-23,outliers 5% (mean +2 ms),base58 (fully loaded),5000,107.3\ \8455249226011,2.955415768090805,32.38455249226011,32.51910170330292\ \,37.15637384580478,107.42520583842872 2026-10-23,outliers 5% (mean +2 ms),"ols_intercept_raw (orig, 1 wind\ \ow)",5000,74.82158261984132,6.702531924319099,-0.17841738015867747,\ \6.70423613629622,13.543045379144571,75.12113001777475 2026-10-23,outliers 5% (mean +2 ms),ols_gated (orig gate),5000,75.28\ \243517665783,7.672823560840477,0.28243517665782747,7.67725319242001\ \5,14.307521366468997,75.67235620145046 2026-10-23,outliers 5% (mean +2 ms),hybrid_raw,5000,75.0144238251829\ \,3.261420704290177,0.014423825182902306,3.2611264440532612,6.613299\ \71603665,75.08527498425732 2026-10-23,outliers 5% (mean +2 ms),hybrid_gated,5000,75.26053656007\ \721,4.263672723028318,0.26053656007721315,4.271199902511561,6.85606\ \3131656143,75.38118885119017 2026-10-23,"adversary: fwd delay 0.05 us/B, every packet",base48,500\ \0,109.65359750315467,3.20909173631503,34.65359750315467,34.80183946\ \329245,39.99937370842549,109.70053625895355 2026-10-23,"adversary: fwd delay 0.05 us/B, every packet",base58 (fu\ \lly loaded),5000,109.75111332749853,2.883016530593394,34.7511133274\ \9853,34.87047460903647,39.590381849242355,109.78896574148168 2026-10-23,"adversary: fwd delay 0.05 us/B, every packet","ols_inter\ \cept_raw (orig, 1 window)",5000,74.97470815427936,6.488890335779266\ \,-0.0252918457206448,6.488290709244736,12.831748621462518,75.254927\ \67566503 2026-10-23,"adversary: fwd delay 0.05 us/B, every packet",ols_gated \ \(orig gate),5000,75.33787187913234,7.400191610168018,0.337871879132\ \3365,7.407161447324886,13.571212452607664,75.70037531331391 2026-10-23,"adversary: fwd delay 0.05 us/B, every packet",hybrid_raw\ \,5000,75.00193292615776,3.213443482942365,0.001932926157763859,3.21\ \312270392288,6.6804739641041495,75.07072729389353 2026-10-23,"adversary: fwd delay 0.05 us/B, every packet",hybrid_gat\ \ed,5000,75.41787178341434,4.950834290281017,0.4178717834143413,4.96\ \7944730485866,7.1172429330596945,75.58016434460377 2026-10-23,adversary: +20 us fwd on 1400 B only,base48,5000,107.3609\ \3318017086,3.1484944110343056,32.36093318017086,32.51370527553552,3\ \7.61552113680953,107.40708080834342 2026-10-23,adversary: +20 us fwd on 1400 B only,base58 (fully loaded\ \),5000,107.41788000043202,2.9140861399153324,32.41788000043202,32.5\ \48565918848894,37.40445198017573,107.45739222332942 2026-10-23,adversary: +20 us fwd on 1400 B only,"ols_intercept_raw (\ \orig, 1 window)",5000,72.81061032472093,6.557875060092197,-2.189389\ \675279074,6.91307104758349,13.81435536615492,73.10528093111384 2026-10-23,adversary: +20 us fwd on 1400 B only,ols_gated (orig gate\ \),5000,73.3056162221564,7.728761701140683,-1.6943837778435977,7.911\ \557815509657,14.893364262706225,73.71183880755936 2026-10-23,adversary: +20 us fwd on 1400 B only,hybrid_raw,5000,74.4\ \5598246499785,3.1562899456408826,-0.5440175350021548,3.202519143752\ \204,6.57411587480644,74.52283877185421 2026-10-23,adversary: +20 us fwd on 1400 B only,hybrid_gated,5000,88\ \.69004770471116,16.496504819837313,13.690047704711162,21.4358963072\ \2095,35.92009057205846,90.21089072944909 2026-10-23,adversary: +200 us fwd on 1400 B only,base48,5000,107.366\ \29419575766,3.1908366704604387,32.36629419575766,32.52316716336465,\ \37.602930259357684,107.4136887538074 2026-10-23,adversary: +200 us fwd on 1400 B only,base58 (fully loade\ \d),5000,107.40776979624825,2.8901206058772115,32.407769796248246,32\ \.53635919588598,37.1712898475709,107.44663856613175 2026-10-23,adversary: +200 us fwd on 1400 B only,"ols_intercept_raw \ \(orig, 1 window)",5000,53.19163966036355,6.740985336106873,-21.8083\ \6033963645,22.82622123410653,32.665014401751954,53.616996604462166 2026-10-23,adversary: +200 us fwd on 1400 B only,ols_gated (orig gat\ \e),5000,107.10064650962711,4.984690467286833,32.10064650962711,32.4\ \8528399079936,37.605828173522724,107.21655959975097 2026-10-23,adversary: +200 us fwd on 1400 B only,hybrid_raw,5000,69.\ \94941500026572,3.1931841366695055,-5.0505849997342835,5.97518154412\ \3376,10.495923199174973,70.02224678289815 2026-10-23,adversary: +200 us fwd on 1400 B only,hybrid_gated,5000,1\ \07.36629419575766,3.1908366704604387,32.36629419575766,32.523167163\ \36465,37.602930259357684,107.4136887538074 2026-10-23,true slope 0.00 us/B,base48,5000,74.98362049102062,3.2084\ \912676076067,-0.016379508979383672,3.2082122154536172,6.63255774933\ \24115,75.05221981575546 2026-10-23,true slope 0.00 us/B,base58 (fully loaded),5000,75.071748\ \2703998,2.9110603212508774,0.07174827039979448,2.9116533368221966,6\ \.055698386176873,75.12815694341101 2026-10-23,true slope 0.00 us/B,"ols_intercept_raw (orig, 1 window)"\ \,5000,74.91930200184736,6.678091104884209,-0.08069799815264389,6.67\ \7910870315537,13.262683448778143,75.21628675937798 2026-10-23,true slope 0.00 us/B,ols_gated (orig gate),5000,74.899794\ \14853725,6.666973042653661,-0.10020585146274641,6.667059401132383,1\ \3.26126297797124,75.19586958961786 2026-10-23,true slope 0.00 us/B,hybrid_raw,5000,74.98723808809878,3.\ \2194240300601105,-0.012761911901222334,3.2191273683262036,6.6717911\ \97371023,75.05630216196587 2026-10-23,true slope 0.00 us/B,hybrid_gated,5000,74.98397765252719,\ \3.2088063594436194,-0.016022347472812726,3.2085254682445448,6.63255\ \77493324115,75.05259011892561 2026-10-23,true slope 0.02 us/B,base48,5000,76.78795520399241,3.2281\ \343299782925,1.7879552039924107,3.689925594590959,7.342458142345681\ \,76.8557664166618 2026-10-23,true slope 0.02 us/B,base58 (fully loaded),5000,76.762470\ \0848176,2.9342538508140192,1.7624700848175934,3.422634145181398,6.6\ \59215076003442,76.8185194937679 2026-10-23,true slope 0.02 us/B,"ols_intercept_raw (orig, 1 window)"\ \,5000,74.98779396962709,6.632417880269267,-0.012206030372908572,6.6\ \31765838168989,13.217920902685393,75.28047166148978 2026-10-23,true slope 0.02 us/B,ols_gated (orig gate),5000,75.006645\ \24170405,6.613519266576831,0.006645241704049454,6.612861220470484,1\ \3.209059400654514,75.29758774208382 2026-10-23,true slope 0.02 us/B,hybrid_raw,5000,74.98949199582675,3.\ \233779100927311,-0.010508004173246377,3.2334727811273187,6.69610377\ \1702996,75.05917096264987 2026-10-23,true slope 0.02 us/B,hybrid_gated,5000,75.00441052237528,\ \3.2391246776303926,0.004410522375280834,3.2388037520366018,6.704409\ \893287068,75.07430604474807 2026-10-23,true slope 0.05 us/B,base48,5000,79.5467103841938,3.17490\ \47906816403,4.546710384193801,5.545320526673191,9.81754334376276,79\ \.61003163780688 2026-10-23,true slope 0.05 us/B,base58 (fully loaded),5000,79.467399\ \25797135,2.8972553718996106,4.467399257971351,5.324478002807993,9.1\ \82132343362214,79.52018583163705 2026-10-23,true slope 0.05 us/B,"ols_intercept_raw (orig, 1 window)"\ \,5000,74.89578766781045,6.529178530805431,-0.1042123321895474,6.529\ \357277929698,13.108140320957945,75.1797888839442 2026-10-23,true slope 0.05 us/B,ols_gated (orig gate),5000,74.937192\ \288441,6.528826574872318,-0.06280771155900311,6.5284757898073975,13\ \.043506552319585,75.22100663647257 2026-10-23,true slope 0.05 us/B,hybrid_raw,5000,75.05100179829294,3.\ \1834487281501325,0.051001798292944045,3.183538930031932,6.637763632\ \817718,75.1184743579299 2026-10-23,true slope 0.05 us/B,hybrid_gated,5000,75.09679076204768,\ \3.214367602360367,0.09679076204767512,3.2155032425586327,6.67861946\ \6402285,75.16553781760665 2026-10-23,true slope 0.10 us/B,base48,5000,84.0466652773339,3.25908\ \60942605016,9.0466652773339,9.615699167584603,14.48157488396526,84.\ \10981786974439 2026-10-23,true slope 0.10 us/B,base58 (fully loaded),5000,84.001095\ \57775392,2.9452143282755605,9.001095577753915,9.470600518544366,13.\ \964051350097758,84.05270138933632 2026-10-23,true slope 0.10 us/B,"ols_intercept_raw (orig, 1 window)"\ \,5000,75.00594046146455,6.488891308908993,0.0059404614645472975,6.4\ \8824510679377,12.927151208426176,75.28604381813084 2026-10-23,true slope 0.10 us/B,ols_gated (orig gate),5000,75.094615\ \09167889,6.521630011598875,0.09461509167888948,6.5216641811855744,1\ \2.951310603344172,75.37721384771389 2026-10-23,true slope 0.10 us/B,hybrid_raw,5000,75.04659277532933,3.\ \2629463779170873,0.04659277532933004,3.2629527407031347,6.772410536\ \825274,75.11747983583756 2026-10-23,true slope 0.10 us/B,hybrid_gated,5000,75.14725622550277,\ \3.4124959478635595,0.1472562255027725,3.4153307254811653,7.03213275\ \3204785,75.2246829025542 2026-10-23,true slope 0.20 us/B,base48,5000,92.9727778474264,3.20645\ \25014076213,17.9727778474264,18.2565063725017,23.250171238065484,93\ \.0280425573018 2026-10-23,true slope 0.20 us/B,base58 (fully loaded),5000,92.991110\ \95864046,2.902247171882589,17.991110958640462,18.22365022615075,22.\ \829081451179388,93.03638036467859 2026-10-23,true slope 0.20 us/B,"ols_intercept_raw (orig, 1 window)"\ \,5000,75.04092968114243,6.412377953297156,0.040929681142429786,6.41\ \1867320564787,12.814547845102304,75.3143511869278 2026-10-23,true slope 0.20 us/B,ols_gated (orig gate),5000,75.240413\ \35394844,6.661799218032717,0.24041335394844054,6.665470087576252,13\ \.5943244149088,75.53469728926329 2026-10-23,true slope 0.20 us/B,hybrid_raw,5000,74.9683403990142,3.2\ \127094050026344,-0.03165960098580456,3.212544124363549,6.5306755807\ \27168,75.03713413772618 2026-10-23,true slope 0.20 us/B,hybrid_gated,5000,75.15542048332202,\ \3.6734235470943077,0.1554204833220183,3.6763429212835557,6.94853247\ \2493341,75.24512322917131 2026-10-23,true slope 0.36 us/B,base48,5000,107.35144774554425,3.196\ \8080636021865,32.35144774554425,32.50897889986448,37.61824431279150\ \4,107.39902639662742 2026-10-23,true slope 0.36 us/B,base58 (fully loaded),5000,107.37613\ \635142561,2.950203319637967,32.376136351425615,32.51024706047897,37\ \.303299910245606,107.41664962494048 2026-10-23,true slope 0.36 us/B,"ols_intercept_raw (orig, 1 window)"\ \,5000,75.00183318217651,6.516810155751599,0.0018331821765116274,6.5\ \1615870001206,12.61586466369427,75.28436292836791 2026-10-23,true slope 0.36 us/B,ols_gated (orig gate),5000,75.434544\ \70248649,7.465673088866127,0.434544702486491,7.477563541244235,13.7\ \60198050975148,75.80300562567635 2026-10-23,true slope 0.36 us/B,hybrid_raw,5000,74.95408762384801,3.\ \200042559665898,-0.045912376151989065,3.2000519176226283,6.48651362\ \7576672,75.02235317458845 2026-10-23,true slope 0.36 us/B,hybrid_gated,5000,75.25219458652452,\ \4.50044047131313,0.2521945865245243,4.507051780534395,6.90174557982\ \3662,75.38662151689182
Produced by the script of Section F.5. Reproduced in: Table D-1.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,scenario,nominal_baseline_us,base58_err,base58_sd,hyb_raw_\ \err,hyb_raw_sd,hyb_lof_reject,hyb_slope_not_sig,hyb_fallback,hyb_fa\ \lse_valid,hyb_applied_err,ols_raw_err,ols_raw_sd,ols_fallback,ols_f\ \alse_valid 2026-10-23,nominal,107.4,-0.00581281805825995,2.988052019572123,0.07\ \170217557300873,3.2129513526577376,0.009399999999999964,0.0,0.00939\ \9999999999964,0.0,0.07189704988836354,0.04640163682263676,6.5677610\ \44491434,0.01319999999999999,0.0012 2026-10-23,"drift 1 ppm, sequential (neg. control)",107.4,-0.0588171\ \1741891138,16.887862979454802,-1.3987182544626933,14.22815316035297\ \4,0.0006000000000000449,0.0,0.0006000000000000449,0.0376,-1.3940691\ \732223343,-20.403193690100615,6.792692355773483,0.01280000000000003\ \4,0.2368 2026-10-23,"drift 1 ppm, randomized",107.4,0.11782691249172217,16.78\ \2879285318757,-0.03160110385617543,14.27580109775702,0.011000000000\ \00001,0.0,0.01100000000000001,0.0308,-0.05001605483887772,0.0371164\ \2656787717,12.150431465773751,0.10799999999999998,0.0356 2026-10-23,"drift 5 ppm, randomized",107.4,-0.8343460835746015,83.31\ \660550877665,-0.3705211139068041,69.0616929892043,0.013599999999999\ \945,0.0,0.013599999999999945,0.778,-0.41987440033013,-0.37020792768\ \67778,49.96974582083732,0.9922,0.0064 2026-10-23,"path step +50 us, randomized",107.4,25.416703639235976,2\ \5.22427384970892,25.209032149407548,25.238941162113363,0.0010000000\ \000000009,0.0,0.0010000000000000009,0.5032,25.212425604297664,25.64\ \4255453124885,21.85364980690612,0.472,0.2782 2026-10-23,"path step +50 us, sequential (neg. control)",107.4,24.95\ \1140183093287,25.239319980306572,24.26567523321043,25.1967497877873\ \75,0.0,0.0,0.0,0.5136,24.26567523321043,4.1761909052929695,20.55272\ \6646051898,0.1402,0.1632 2026-10-23,shaper +10 us fwd for L>=1100,107.4,0.028211405698812086,\ \2.9543758354984413,-0.35194138903970895,3.1886279178720742,0.050599\ \99999999998,0.0,0.05059999999999998,0.0,-0.3430028850451805,-1.3554\ \536639237256,6.5417771409757774,0.012199999999999989,0.0012 2026-10-23,shaper +40 us fwd for L>=1100,107.4,0.03364299492467637,2\ \.8878129580050143,-1.5053460911503294,3.1536300095348775,0.979,0.0,\ \0.979,0.0,-1.4070094805702666,-5.409314351488959,6.515534410574508,\ \0.016000000000000014,0.002 2026-10-23,quadratic fwd term +5 us at 1400 B,107.4,0.04446386032579\ \1416,2.89395265545671,-0.24122020434201374,3.1861329885693626,0.009\ \800000000000031,0.0,0.009800000000000031,0.0,-0.24138097478814302,-\ \0.39497681940613916,6.606660883338708,0.013000000000000012,0.0012 2026-10-23,quadratic fwd term +30 us at 1400 B,107.4,0.0363048012018\ \3677,2.91369382314679,-1.001673613628185,3.167447067200363,0.066599\ \99999999999,0.0,0.06659999999999999,0.0,-0.9906182239248693,-2.6154\ \620041782835,6.527383419077316,0.013000000000000012,0.0008 2026-10-23,fragmentation at >=1300 B,107.4,-0.04149074903801875,2.89\ \0941058603932,-1.1489844232900737,3.237062968097864,0.9996,0.0,0.99\ \96,0.0,-3.988647170462869,-4.785211212343853,6.34961060746155,0.029\ \39999999999998,0.0014 2026-10-23,length-label noise 10%,107.4,0.01836844556848405,2.902212\ \884073842,3.491826728965492,3.376518862273072,0.005199999999999982,\ \0.0,0.005199999999999982,0.0,3.4963324513634575,22.42390151316998,5\ \3.89483348651972,0.471,0.0046 2026-10-23,symmetric +66 B overhead (L=payload),107.4,23.82701512676\ \107,2.874830864274701,23.76794378429591,3.2549619533093006,0.009000\ \000000000008,0.0,0.009000000000000008,0.3186,23.763650107004537,23.\ \80586718614343,6.498202601412822,0.01100000000000001,0.4082 2026-10-23,forward-only tunnel +50 B,107.4,19.967269888705218,2.9579\ \893084023454,19.933645246919312,3.161687898924755,0.010199999999999\ \987,0.0,0.010199999999999987,0.0566,19.93952954439942,20.0221288652\ \4869,6.681441506768205,0.011399999999999966,0.2118 2026-10-23,NTPv4-style fixed 90 B response,107.4,0.00294361467963710\ \77,2.8831941928533253,-3.5619587331048734,3.1961649874298055,0.0111\ \99999999999988,0.0,0.011199999999999988,0.0,-3.565477015896519,-3.7\ \069151957046955,6.662777244950206,0.01100000000000001,0.0024 2026-10-23,queue asymmetry fwd150/rev20,107.4,0.41396251942028073,3.\ \3362968634795176,0.5931985564519664,3.811172979087074,0.00980000000\ \0000031,0.0,0.009800000000000031,0.0,0.5934569330895272,5.128065079\ \467504,8.572960897978115,0.03859999999999997,0.0158 2026-10-23,length-dependent fwd queue (x2 at 700 B),107.4,0.09603174\ \44092027,3.0506792563397656,-0.489027302339764,3.433701549635281,0.\ \013599999999999945,0.0,0.013599999999999945,0.0,-0.4894705712520562\ \,-0.03962613301195006,8.126858003880878,0.042200000000000015,0.0028 2026-10-23,outliers 5% (mean +2 ms),107.4,-0.015447507739892785,2.95\ \5415768090805,0.014423825182902306,3.261420704290177,0.007600000000\ \000051,0.0,0.007600000000000051,0.0,0.020144707212594426,-0.1784173\ \8015867747,6.702531924319099,0.013800000000000034,0.0002 2026-10-23,"adversary: fwd delay 0.05 us/B, every packet",107.4,2.35\ \1113327498524,2.883016530593394,0.001932926157763859,3.213443482942\ \365,0.01200000000000001,0.0,0.01200000000000001,0.0,0.0028294176585\ \745845,-0.0252918457206448,6.488890335779266,0.011600000000000055,0\ \.0006 2026-10-23,adversary: +20 us fwd on 1400 B only,107.4,0.017880000432\ \01521,2.9140861399153324,-0.5440175350021548,3.1562899456408826,0.4\ \326,0.0,0.4326,0.0,-0.4472523081497286,-2.189389675279074,6.5578750\ \60092197,0.014399999999999968,0.0006 2026-10-23,adversary: +200 us fwd on 1400 B only,107.4,0.00776979624\ \8240368,2.8901206058772115,-5.0505849997342835,3.1931841366695055,1\ \.0,0.0,1.0,0.0,,-21.80836033963645,6.740985336106873,0.9952,0.0018
Produced by the script of Section F.5. Reproduced in: Table D-2.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,scenario,nominal_baseline_us,base58_err,base58_sd,hyb_raw_\ \err,hyb_raw_sd,hyb_lof_reject,hyb_slope_not_sig,hyb_fallback,hyb_fa\ \lse_valid,hyb_applied_err,ols_raw_err,ols_raw_sd,ols_fallback,ols_f\ \alse_valid 2026-10-23,true slope 0.00 us/B,75.0,0.07174827039979448,2.911060321\ \2508774,-0.012761911901222334,3.2194240300601105,0.0080000000000000\ \07,0.9978,0.9978,0.0,-0.38559651786647464,-0.08069799815264389,6.67\ \8091104884209,0.009000000000000008,0.0008 2026-10-23,true slope 0.02 us/B,76.8,-0.037529915182403784,2.9342538\ \508140192,-0.010508004173246377,3.233779100927311,0.008199999999999\ \985,0.0,0.008199999999999985,0.0,-0.012699548184571086,-0.012206030\ \372908572,6.632417880269267,0.011399999999999966,0.001 2026-10-23,true slope 0.05 us/B,79.5,-0.03260074202864871,2.89725537\ \18996106,0.051001798292944045,3.1834487281501325,0.0101999999999999\ \87,0.0,0.010199999999999987,0.0,0.051621914643050104,-0.10421233218\ \95474,6.529178530805431,0.011199999999999988,0.0002 2026-10-23,true slope 0.10 us/B,84.0,0.0010955777539152223,2.9452143\ \282755605,0.04659277532933004,3.2629463779170873,0.0111999999999999\ \88,0.0,0.011199999999999988,0.0,0.040482481380834656,0.005940461464\ \5472975,6.488891308908993,0.010600000000000054,0.0002 2026-10-23,true slope 0.20 us/B,93.0,-0.008889041359537941,2.9022471\ \71882589,-0.03165960098580456,3.2127094050026344,0.0103999999999999\ \65,0.0,0.010399999999999965,0.0,-0.027245604001791435,0.04092968114\ \2429786,6.412377953297156,0.011399999999999966,0.0006 2026-10-23,true slope 0.36 us/B,107.4,-0.02386364857439105,2.9502033\ \19637967,-0.045912376151989065,3.200042559665898,0.0091999999999999\ \86,0.0,0.009199999999999986,0.0,-0.05281287267162327,0.001833182176\ \5116274,6.516810155751599,0.013800000000000034,0.0008
Produced by the script of Section F.5. Reproduced in: Table D-3.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,scenario,nominal_baseline_us,base58_err,base58_sd,hyb_raw_\ \err,hyb_raw_sd,hyb_lof_reject,hyb_slope_not_sig,hyb_fallback,hyb_fa\ \lse_valid,hyb_applied_err,ols_raw_err,ols_raw_sd,ols_fallback,ols_f\ \alse_valid 2026-10-23,shaper us at >=1100 B = 2,107.4,-0.0027271640504977768,2.\ \9305459715297086,-0.11875541926782773,3.2460973590827242,0.00980000\ \0000000031,0.0,0.009800000000000031,0.0,-0.1223538383621019,-0.3769\ \996701851426,6.521162352268968,0.01100000000000001,0.0004 2026-10-23,shaper us at >=1100 B = 5,107.4,-0.011805998953278163,2.8\ \37769507445189,-0.14968403578122036,3.179372763472849,0.01319999999\ \999999,0.0,0.01319999999999999,0.0,-0.14081268762106447,-0.54372751\ \1588969,6.5312135423761415,0.010600000000000054,0.0006 2026-10-23,shaper us at >=1100 B = 10,107.4,-0.009018580741766868,2.\ \9219466269239898,-0.49164321349425677,3.225435886345018,0.051599999\ \99999998,0.0,0.05159999999999998,0.0,-0.4855928967119638,-1.4214463\ \007525069,6.509993266634469,0.009399999999999964,0.0004 2026-10-23,shaper us at >=1100 B = 20,107.4,-0.060560069984290976,2.\ \8999523906391556,-0.7380151100950485,3.2149928769944727,0.3234,0.0,\ \0.3234,0.0,-0.7464910114722016,-2.7172395863181578,6.51526133631005\ \9,0.010399999999999965,0.0006 2026-10-23,shaper us at >=1100 B = 40,107.4,-0.024931827735272805,2.\ \89234050190886,-1.5827757154168722,3.22911004959082,0.9796,0.0,0.97\ \96,0.0,-1.57753569612305,-5.345582970370472,6.560566350425912,0.018\ \59999999999995,0.003 2026-10-23,quadratic us at 1400 B = 2,107.4,0.013455290174732681,2.8\ \418622010114847,-0.031299669515718165,3.17619904243941,0.0080000000\ \00000007,0.0,0.008000000000000007,0.0,-0.02601293589833631,-0.15179\ \951619690257,6.588198905881405,0.011800000000000033,0.0006 2026-10-23,quadratic us at 1400 B = 5,107.4,0.014911417072767108,2.9\ \419004845895294,-0.16899448779847148,3.1643890423173344,0.010199999\ \999999987,0.0,0.010199999999999987,0.0,-0.16239841178943948,-0.3360\ \9513672547564,6.632195647054352,0.009399999999999964,0.0008 2026-10-23,quadratic us at 1400 B = 10,107.4,-0.022249828876795164,2\ \.913268305058805,-0.30728801101662384,3.1731368988239845,0.01239999\ \9999999967,0.0,0.012399999999999967,0.0,-0.30547610748652687,-0.665\ \3733990387565,6.632586991882337,0.011399999999999966,0.0006 2026-10-23,quadratic us at 1400 B = 30,107.4,0.08114390271637717,2.8\ \95949779780434,-0.9131047265764352,3.2101926095819793,0.05700000000\ \000005,0.0,0.05700000000000005,0.0,-0.902629600037244,-2.6166872867\ \679274,6.521671890511214,0.011600000000000055,0.001 2026-10-23,adv us on 1400 B only = 2,107.4,0.0008315605350190935,2.8\ \68303520031292,-0.045285383602674756,3.2633130692834498,0.011600000\ \000000055,0.0,0.011600000000000055,0.0,-0.04981362193075256,-0.2217\ \4723871442836,6.62605180463072,0.011199999999999988,0.0004 2026-10-23,adv us on 1400 B only = 5,107.4,0.03704937300574329,2.888\ \3977777601997,-0.1446115786263249,3.264113523103178,0.0181999999999\ \99994,0.0,0.018199999999999994,0.0,-0.1528551461118468,-0.494854965\ \9647483,6.592040033511019,0.012599999999999945,0.0002 2026-10-23,adv us on 1400 B only = 10,107.4,0.04223344716713484,2.87\ \85688120683344,-0.3289378356587207,3.275202239086756,0.065599999999\ \99999,0.0,0.06559999999999999,0.0,-0.31573043988805694,-1.004622388\ \8655703,6.662397492003907,0.012399999999999967,0.0008 2026-10-23,adv us on 1400 B only = 20,107.4,0.028880142440414147,2.8\ \703965482744884,-0.5725429728144746,3.2725066666068674,0.4277999999\ \9999996,0.0,0.42779999999999996,0.0,-0.609741148636644,-2.321231673\ \6682794,6.706253336231534,0.01319999999999999,0.0014 2026-10-23,adv us on 1400 B only = 50,107.4,-0.03066341273054718,2.8\ \34051728770137,-1.2546739048013649,3.250242809797062,1.0,0.0,1.0,0.\ \0,,-5.562802242210495,6.631922576343536,0.034399999999999986,0.0038 2026-10-23,adv us on 1400 B only = 200,107.4,-0.04370670729298354,2.\ \823051665820063,-5.0334456267822105,3.20362113838814,1.0,0.0,1.0,0.\ \0,,-21.901519523323536,6.578018183040987,0.9932,0.0012
Produced by the script of Section F.5. Reproduced in: Table D-4.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== test_date,M,calibration_candidates,slope_mean,slope_sd,hybrid_mean,h\ \ybrid_sd,base48_sd,lof_false_reject_at_p01,mean_se_b 2026-10-23,5,240,0.35999167475139165,0.0038549943398549958,74.973631\ \13657305,3.2137438010627206,3.1873778766179908,0.008,0.003801550134\ \521671 2026-10-23,10,480,0.3600273709498539,0.0026926068264726604,75.045370\ \66263357,3.23225703303404,3.222546043583404,0.0092,0.00270716808927\ \2138 2026-10-23,20,960,0.3599896511229239,0.0019621983286125153,75.070386\ \91133305,3.26418509641407,3.2597044896023832,0.0072,0.0019147627500\ \064027 2026-10-23,40,1920,0.3599972551442244,0.001358618982442557,74.992687\ \52904223,3.297179760558184,3.2939235496035244,0.0096,0.001355523531\ \0096574
Produced by the script of Section F.5. Reproduced in: Table D-5.¶
test_date,length_B,weight_ols_intercept,weight_hybrid_output 2026-10-23,90.0,0.49162742019884875,-0.0423861852433281 2026-10-23,250.0,0.4049712192569335,-0.03108320251177394 2026-10-23,500.0,0.269570905285191,-0.013422291993720565 2026-10-23,800.0,0.10709052851909995,0.007770800627943485 2026-10-23,1100.0,-0.055389848246991114,0.028963893249607537 2026-10-23,1400.0,-0.21787022501308215,0.050156985871271584 2026-10-23,,1.5465201465201466,0.1737833594976452
Produced by the script of Section F.6. Reproduced in: Table D-6.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== group,test_date,scenario,base58_err,base58_sd,hyb_raw_err,hyb_raw_sd\ \,hyb_lof_reject,hyb_fallback,hyb_false_valid,hyb_applied_err,ols_ra\ \w_err,ols_raw_sd,ols_fallback,ols_false_valid,predicted_hybrid_shift S2 loss,2026-10-24,nominal (control),-0.03052191318923292,2.92530834\ \59513296,-0.009687440159680705,3.233891822235761,0.0078,0.007800000\ \000000029,0.0,-0.0140400514207073,0.13726324985051974,6.72295173364\ \9183,0.008000000000000007,0.0008, S2 loss,2026-10-24,iid packet loss 20%,-0.0298419729671906,3.2615200\ \33587866,0.06415992934114456,3.592767108107424,0.0096,0.00960000000\ \0000053,0.0,0.06529695804735525,0.06956610094805171,7.6470696355694\ \58,0.019000000000000017,0.0026, S2 loss,2026-10-24,size-dependent loss 2%..32%,0.017412244334948923,\ \3.013835082787186,0.03856469212959723,3.315326150411922,0.0112,0.01\ \1199999999999988,0.0,0.0323647872414341,-0.10487072444513501,7.0820\ \37371808259,0.01980000000000004,0.001, S3 90 B-only delay,2026-10-24,+5 us fwd on 90 B packets only,2.50859\ \8581002744,2.918943026483011,2.584476288520733,3.1854209653371854,0\ \.022,0.02200000000000002,0.0,2.5844718876348765,1.2605365085502882,\ \6.511033070803393,0.009000000000000008,0.0006,2.5 S3 90 B-only delay,2026-10-24,+20 us fwd on 90 B packets only,9.9533\ \39155308015,2.9107876895578846,10.438500631073879,3.18682991305507,\ \0.568,0.5680000000000001,0.0,10.354799932279931,5.0645245199540625,\ \6.738367273886106,0.014000000000000012,0.0026,10.0 S3 90 B-only delay,2026-10-24,+200 us fwd on 90 B packets only,100.0\ \3048956001703,2.9486150449726294,104.19795956980406,3.2275453216882\ \,1.0,1.0,0.0,,49.1857561498295,6.620218683030055,0.9994,0.0006,100.0 S4 schedule-aware,2026-10-24,schedule-aware: fwd delay 0.2 us/B x (L\ \-90),-0.05020055440455451,2.9534835062373594,-8.966392729380033,3.2\ \792532224442876,0.0052,0.005199999999999982,0.0,-8.969150920826706,\ \-8.910472102736094,6.4926541461278715,0.01100000000000001,0.0086,-9\ \.0 S4 schedule-aware,2026-10-24,schedule-aware: fwd delay 0.5 us/B x (L\ \-90),-0.022492521118891773,2.954150958670136,-22.516933453369255,3.\ \248703387902787,0.0078,0.007800000000000029,0.1954,-22.510680551018\ \055,-22.534745679002,6.550327981478236,0.012599999999999945,0.3432,\ \-22.5 S4 schedule-aware,2026-10-24,schedule-aware: fwd delay 1 us/B x (L-9\ \0),0.008593639172190137,2.9100973188311823,-45.01488857206854,3.180\ \0071600179116,0.0102,0.010199999999999987,0.9898,-45.00918098796183\ \,-44.93539721962132,6.507909398925898,0.010199999999999987,0.9872,-\ \45.0
This appendix gives the checksums and the procedure for reproducing the results of this document from the files in Appendices F and G.¶
To restore a folded file, remove the two header lines when present, then remove every backslash that ends a line together with the line break and the backslash that begins the next line, and make the file end with exactly one line feed. The following program does this. Save it as unfold.py and run it as: python3 unfold.py FOLDED_FILE > ORIGINAL_FILE.¶
The SHA-256 digest of each file after unfolding, in the format read by the sha256sum -c command. All files are ASCII text with line feed line endings.¶
========== NOTE: '\\' line wrapping per RFC 8792 ========== 16ebe0cc0a7a688ed217a48269c45d7de3a231b2c3970c54316031bd637c60ac ta\ \re_core_2026-10-23.py 69d304f9d46000f7554da7014a8ffa7abf25db8cf617af846533574b0699d754 ta\ \re_monte_carlo_2026-10-23.py 011f7d8d2752d2c011fae3055e488130c40df0443399e67feb87452c0596399a ta\ \re_matched_budget_2026-10-23.py 0d44adc2b914958741c8b633cef9a7ab6629478eb6d6312abefd345133d26d0c ta\ \re_stress_2026-10-23.py b46b116d607abbcc502c1e6156db5bb9a157068a4007f654342b7749cd70b6fe ta\ \re_hybrid_2026-10-23.py 83cf68c6cf65514a2411813480c86f01d343db38d4995ef105757470fd7e0397 ta\ \re_supplement_2026-10-24.py 75fc25f0c4c9275588bc5a5e8aaace00b02ee2210eed795d979782fb2378c1bd ta\ \re_monte_carlo_results_2026-10-23.csv 45148447b2ac58da4e5217b9d599248776c0c491961034e2c425ca8d9cd01eac ta\ \re_E1_matched_budget_2026-10-23.csv 926901ff05073ef85e22a1b3f5a956bad0149fb286624150f83f123caba51d42 ta\ \re_E1_analytic_checks_2026-10-23.csv 60780e07d7f968dd3afd26915ad6db8ad559bf12b2f6a851464bd2b36608a809 ta\ \re_E2_design_sweep_2026-10-23.csv 6fe08bcdbcfef1f8771e9e743dbfc3928a5f1738e0113ebc142d4f121ccd372a ta\ \re_E2b_budget_sweep_2026-10-23.csv c3d035c0a1cb89b708ead763c8e945ba6bdacf62200a53eccc7aa9f2a4e7b720 ta\ \re_E4_length_zero_meaning_2026-10-23.csv 8532d7cb0d3115962ac2e3598cb64ee779673d244fe88373647280b2999967ae ta\ \re_stress_estimators_2026-10-23.csv a5b4fc4d496dafd70548b88ec555ccb87fd3fea7084f4bf1a7ae4f0f5c726afe ta\ \re_stress_validity_2026-10-23.csv b2910a2a532a507b5fdf3e19c9c89456e5947a97d11aa8948235f09122c50c4e ta\ \re_supplement_gate_2026-10-24.csv d0ce5e1ef7437d7562bea8c8a1258d69f098ac5aafbb18ca8758925521eecceb ta\ \re_hybrid_estimators_2026-10-23.csv 24678c553c78d45a96287611604009ae3984ffbeaf99265a6eab9a932c83a771 ta\ \re_hybrid_validity_2026-10-23.csv 50c2c36aea1e15d37c39a1483e066b524a7b565de52c020177a729e200a70f07 ta\ \re_hybrid_slope_sweep_2026-10-23.csv f34d94861ead17afeff43a3292a6b567f68d34feeb891f20c4d594e61ab610e6 ta\ \re_hybrid_power_2026-10-23.csv e68718f432575f941732ca0540abe029b661fe8f01608824dec555ce86e75a03 ta\ \re_hybrid_pooling_depth_2026-10-23.csv 550edfa9008f12df47e89b3b11c0ebf25dd6ffdb623b1a7411a634bad32f549c ta\ \re_hybrid_leverage_2026-10-23.csv 4d34ff11684e65bc4a8e9d0ab5eb3222b30ab40e15b0cda0050bd01efc2bf0d8 ta\ \re_supplement_hybrid_2026-10-24.csv
Place the six scripts of Appendix F in one directory and create an empty output directory.¶
Run each of the matched-budget, stress, hybrid, and supplementary scripts as python3 -I SCRIPT OUTDIR, where OUTDIR is the output directory. The Monte Carlo script of Appendix A takes no argument and writes its file to the current directory, so run it from inside the output directory. The order does not matter, except that tare_core_2026-10-23.py must be present for the four scripts that import it.¶
Compare the output files with Appendix G, or with sha256sum -c, using the checksums of Section H.2.¶
The environment used for the files in this document was Python 3.13, numpy 2.5.3, pandas 3.0.5, and SciPy 1.18.1. Other versions can change random streams and floating-point rounding, so a mismatch in the last digits under different versions does not by itself indicate an error.¶