Skip to content

Repository files navigation

ntp

A multi-threaded NTP server in Rust implementing RFC 10030Network Time Protocol (NTP) over the Precision Time Protocol (PTP) — layered on RFC 5905 (NTPv4) and RFC 7822 (extension fields).

RFC 10030 encapsulates unmodified NTP messages inside PTP event messages so that NTP inherits what many NICs and switches provide only for PTP: hardware timestamping and on-path (transparent-clock) delay correction — without adopting PTP's weaker security model or clock hierarchy.

Highlights

  • Serves both transports: plain NTP over UDP (port 123) and NTP over PTP (PTP event port 319), from the same process.
  • Share-nothing hot path: one socket per worker (SO_REUSEPORT on Linux), lock-free state publication via arc-swap, zero allocation per packet. Measured per-packet service demand: ~5 ns plain NTP, ~28 ns over PTP.
  • Safety by construction: #![forbid(unsafe_code)] everywhere, panic-free lints denied on all network-facing code, and the RFC's MUST-level rules (anti-amplification, domain verification, negative-correction rejection) encoded in the type system so they cannot be skipped.
  • Adversarially tested: property tests over arbitrary byte strings, exhaustive bit-flip and length-field sweeps, worst observed amplification factor exactly 1.0.

See docs/SPECIFICATION.md for the full implementation specification: architecture, wire formats, the RFC conformance matrix, the safety argument, and the performance model.

Requirements

  • Rust 1.85 or newer (stable; rust-toolchain.toml pins the channel and pulls clippy/rustfmt).
  • A local reference daemon (chronyd or another ntpd) for the server to mirror. This server deliberately does not discipline the clock itself — it republishes the state of a daemon that does.
  • Linux is the supported deployment target (SO_REUSEPORT load balancing, and — where the NIC supports it — hardware timestamping). The code also compiles on macOS for development, but runs there with a single effective receive queue per address.
  • Optional, for the verification/benchmark harness: cargo-audit, a nightly toolchain with miri, and Python 3 (used by bench.sh for a stub reference daemon).

Build

cargo build --release

Binaries land in target/release/: ntpd (the server) and ntpload (the measurement client). Prebuilt Linux binaries (x86-64 and aarch64) are published on the releases page.

Usage

Start the server, mirroring a local reference daemon and serving both transports:

ntpd --upstream 127.0.0.1:123 --stats 5

Common options (see ntpd --help for the full list):

-a, --udp-address ADDR:PORT   plain NTP listen address   (default 0.0.0.0:123)
-b, --ptp-address ADDR:PORT   NTP-over-PTP listen address (default 0.0.0.0:319)
    --no-udp / --no-ptp       disable one of the transports
-4, --udp-threads N           worker threads for plain NTP    (default 1)
-6, --ptp-threads N           worker threads for NTP over PTP (default 1)
    --domain N                PTP domainNumber to accept (default 123)
    --sdo-id N                PTP sdoId to accept        (default 0)
    --link-speed BPS          link speed for the receive-duration correction
-s, --upstream ADDR:PORT      reference daemon to mirror (default 127.0.0.1:11123)
    --rate N / --burst N      per-worker response rate limit
    --rcvbuf BYTES            SO_RCVBUF per worker (default 4 MiB)
    --stats SECONDS           print per-interval counters

Ports 123 and 319 are privileged on most systems; either run with the needed capability (setcap cap_net_bind_service=+ep on Linux) or bind high ports for testing.

Drive it with the bundled load generator:

ntpload --server 127.0.0.1:319 --transport ptp --threads 8 --seconds 10

Verifying and benchmarking

./verify.sh   # build, lints, tests, cargo-audit, Miri — every safety claim
./bench.sh    # criterion benchmarks and load sweeps

Both scripts print PASS/FAIL/SKIP per check and are the reproduction path for every claim in docs/SPECIFICATION.md.

Development

cargo fmt --all
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace

The workspace denies the panicking clippy lints (unwrap_used, indexing_slicing, arithmetic_side_effects, …) on all library and server code; tests and benches opt out locally with written reasons.

License

Licensed under the Apache License, Version 2.0.

About

A multi-threaded NTP server in Rust implementing RFC 10030 — Network Time Protocol (NTP) over the Precision Time Protocol (PTP) — layered on RFC 5905 (NTPv4) and RFC 7822.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages