From e6ef692106a9371d5b611f9991023e5f7d6abdb0 Mon Sep 17 00:00:00 2001 From: Oleg Obleukhov Date: Thu, 4 Jun 2026 09:01:04 -0700 Subject: [PATCH] Use SWRX timestamps in server tests to match production Summary: TestServer fails non-deterministically (and consistently on newer kernels, e.g. Fedora rawhide where it breaks the RPM %check stage) with a UDP read timeout at server_test.go:223. Root cause: the tests configure the server with TimestampType: timestamp.SW, a value production never uses. cmd/ntpresponder defaults to SWRX and Config.Validate() only accepts SWRX/HWRX. SW routes through EnableSWTimestamps, which additionally turns on TX software timestamping (SOF_TIMESTAMPING_TX_SOFTWARE). Every response the worker sends then makes the kernel clone the packet onto the socket error queue. The responder never drains MSG_ERRQUEUE, so those clones accumulate; error-queue skbs are charged to sk_rmem_alloc and bounded by SO_RCVBUF. Once that budget fills, the kernel silently drops incoming requests, the listener never sees them, and the client's synchronous read blocks until the 10s deadline. How quickly it fills relative to the 1000-request loop depends on skb truesize / rmem accounting, which is why it passes on some kernels and fails on others; the earlier 1MB buffer bump only delays the fill. Measured difference (1MB rcvbuf, 4000 sends, no draining): | Mode | sk_rmem_alloc after sends | |------|---------------------------| | SWRX (production, RX only) | 0 bytes | | SW (test, TX+RX) | 2,096,640 bytes (entire 2MB rcvbuf) | Switch TestServer and TestListener to timestamp.SWRX so the tests exercise the real production code path and no longer accumulate TX timestamps. Differential Revision: D107533486 --- ntp/responder/server/server_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ntp/responder/server/server_test.go b/ntp/responder/server/server_test.go index 8307d0e4..058d84bd 100644 --- a/ntp/responder/server/server_test.go +++ b/ntp/responder/server/server_test.go @@ -124,7 +124,7 @@ func TestListener(t *testing.T) { ExpectedListeners: 1, ExpectedWorkers: 0, }, - Config: Config{Workers: 42, TimestampType: timestamp.SW, Iface: "lo"}, + Config: Config{Workers: 42, TimestampType: timestamp.SWRX, Iface: "lo"}, } conn := tryListenUDP(t) defer conn.Close() @@ -172,7 +172,7 @@ func TestServer(t *testing.T) { }, Stats: &stats.JSONStats{}, tasks: make(chan task, workers), - Config: Config{Workers: workers, TimestampType: timestamp.SW, Iface: "lo"}, + Config: Config{Workers: workers, TimestampType: timestamp.SWRX, Iface: "lo"}, } // create workers for range workers {