# ============================================================================= # settings.conf - every tunable value for the Chrony kit, in one place # ============================================================================= # Both start-chrony.sh and test-chrony.sh read this file. # After changing a value in sections 1-2, run ./start-chrony.sh again so the # test server picks it up. # # Any value can also be overridden for a single run from the command line: # DURATION=30 ./test-chrony.sh latency # ============================================================================= # ----------------------------------------------------------------------------- # 1. The test server (a separate chronyd, next to the normal one) # ----------------------------------------------------------------------------- # The kit runs its OWN chronyd process with its own configuration file and # its own systemd service. The normal chronyd.service and /etc/chrony.conf # are not changed, so this host keeps its time exactly as before. # # The test chronyd is started with "-x": it NEVER changes the system clock. # It only answers NTP requests, using the system clock as its time source. # # It listens on 127.0.0.1 only, so no other machine can reach it and no # firewall change is needed. "./start-chrony.sh cleanup" removes everything. TEST_SERVICE="chronyd-perf-test" # systemd service name TEST_UNIT_FILE="/etc/systemd/system/$TEST_SERVICE.service" TEST_CONF="/etc/chrony-perf-test.conf" # chronyd configuration TEST_PIDFILE="/run/chrony/chronyd-perf-test.pid" # process ID of the test chronyd TEST_SOCKET="/run/chrony/chronyd-perf-test.sock" # chronyc talks to it through this TEST_STATE_FILE="/etc/chrony-perf-test.state" # remembers what to undo LISTEN_ADDRESS="127.0.0.1" # address the test server answers on # UDP port of the test server. The normal NTP port is 123. The kit uses # another port so it can never clash with a real NTP server on this host. # With SELinux on, start-chrony.sh gives this port the label "ntp_port_t" # (with semanage), because chronyd may otherwise only use port 123. NTP_PORT="${NTP_PORT:-11123}" # ----------------------------------------------------------------------------- # 2. chronyd settings (written to /etc/chrony-perf-test.conf) # ----------------------------------------------------------------------------- # An offline network has no internet time servers, so the server uses its # own clock as the reference ("local stratum"). Clients see this stratum # number; 10 is the usual choice for "local clock, no better source". LOCAL_STRATUM="${LOCAL_STRATUM:-10}" # Memory chronyd may use to remember its clients (for rate limiting and # "chronyc clients"), in bytes. 524288 (512 KB) is chronyd's own default. # A server with many thousands of clients needs more (see # PERFORMANCE-METRICS.md, section 4.10). CLIENT_LOG_LIMIT="${CLIENT_LOG_LIMIT:-524288}" # Extra chronyd command-line options. "-F 2" is RHEL's default (in # /etc/sysconfig/chronyd): a system-call filter that makes chronyd safer. # "-x" (never change the clock) and "-f " are always added. CHRONYD_OPTIONS="${CHRONYD_OPTIONS:--F 2}" # The "ratelimit" test restarts the test server with this line added, then # restarts it again without it. Meaning (man chrony.conf, "ratelimit"): # interval 3 = each client may send 1 request per 2^3 = 8 seconds on average # burst 8 = ... but up to 8 requests in a short burst # leak 2 = of the requests over the limit, about 1 in 2^2 = 4 is still # answered (so a client whose address is faked is not cut off) RATELIMIT_LINE="${RATELIMIT_LINE:-ratelimit interval 3 burst 8 leak 2}" # ----------------------------------------------------------------------------- # 3. How hard and how long each test runs # ----------------------------------------------------------------------------- # Every 127.x.y.z address belongs to this machine, so the load generator # (lib/ntpload.py) can send each request from a different address. The # server then sees many different clients, as on a real network. DURATION="${DURATION:-10}" # seconds of load for each test run # "throughput", "cpu": parallel senders, each keeping this many requests # in flight. chronyd answers with ONE thread, so 2 senders are usually # enough to keep it fully busy. "auto" = 2 (1 on a machine with 1-2 cores). # The report warns when the senders themselves were the limit; then try 4. THROUGHPUT_WORKERS="${THROUGHPUT_WORKERS:-auto}" THROUGHPUT_WINDOW="${THROUGHPUT_WINDOW:-64}" # "latency", "loss", "accuracy": a steady, realistic load of LOAD_RATE # requests per second, spread over LOAD_CLIENTS different client addresses. LOAD_RATE="${LOAD_RATE:-1000}" LOAD_CLIENTS="${LOAD_CLIENTS:-500}" # "clients": the same total load, spread over more and more client # addresses, step by step. CLIENT_STEPS="${CLIENT_STEPS:-10 1000 10000 50000}" CLIENT_STEPS_RATE="${CLIENT_STEPS_RATE:-5000}" # requests per second, all clients together # "ratelimit": one misbehaving client floods the server while normal # clients ask at a normal pace. FLOOD_RATE="${FLOOD_RATE:-200}" # requests per second from the flooding client NORMAL_CLIENTS="${NORMAL_CLIENTS:-200}" # well-behaved clients ... NORMAL_RATE="${NORMAL_RATE:-20}" # ... sending this many requests per second together # "memory": this many new clients each send one request. MEMORY_CLIENTS="${MEMORY_CLIENTS:-20000}" STARTUP_ROUNDS="${STARTUP_ROUNDS:-5}" # restarts measured by the "startup" test # ----------------------------------------------------------------------------- # 4. Pass / fail targets # ----------------------------------------------------------------------------- # Sensible starting points for a RHEL 9 NTP server in an offline company # network. Adjust them to your own needs. A result that misses its target # is reported as FAIL; see PERFORMANCE-METRICS.md. TARGET_STARTUP_MAX_MS="${TARGET_STARTUP_MAX_MS:-2000}" # start until the server answers TARGET_MAX_STRATUM="${TARGET_MAX_STRATUM:-15}" # 16 = "not synchronized", clients ignore it TARGET_THROUGHPUT_MIN_PER_S="${TARGET_THROUGHPUT_MIN_PER_S:-20000}" # answered requests per second TARGET_LATENCY_P95_MAX_MS="${TARGET_LATENCY_P95_MAX_MS:-1}" # 95% of answers faster than TARGET_LATENCY_P99_MAX_MS="${TARGET_LATENCY_P99_MAX_MS:-2}" # 99% of answers faster than TARGET_LOSS_MAX_PCT="${TARGET_LOSS_MAX_PCT:-0}" # unanswered or bad answers, at most % TARGET_OFFSET_P99_MAX_US="${TARGET_OFFSET_P99_MAX_US:-100}" # time error seen by clients, microseconds TARGET_CLIENTS_MIN="${TARGET_CLIENTS_MIN:-10000}" # clients served with no loss and p99 <= target TARGET_RATELIMIT_NORMAL_MIN_PCT="${TARGET_RATELIMIT_NORMAL_MIN_PCT:-100}" # normal clients answered, at least % TARGET_RATELIMIT_FLOOD_MAX_PCT="${TARGET_RATELIMIT_FLOOD_MAX_PCT:-35}" # flooding client answered, at most % TARGET_CPU_MAX_US_PER_REQUEST="${TARGET_CPU_MAX_US_PER_REQUEST:-20}" # chronyd CPU microseconds per answer TARGET_MEMORY_MAX_BYTES_PER_CLIENT="${TARGET_MEMORY_MAX_BYTES_PER_CLIENT:-512}" # chronyd memory per remembered client