]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: optimize detection of clients using interleaved mode
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 14 Oct 2021 10:03:49 +0000 (12:03 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 14 Oct 2021 15:17:05 +0000 (17:17 +0200)
Use the lowest bit of the server RX and TX timestamp as a flag
indicating RX timestamp. This allows the server to detect potential
interleaved requests without having to save all its RX timestamps. It
significantly reduces the amount of memory needed to support clients
using the interleaved mode if most of the server's clients are using the
basic mode (e.g. a public server).

Capture the TX timestamp on the first response to the request which has
the flag set to not further delay the first interleaved response.

False positives are possible with broken clients which set the origin
timestamp to something else than zero or the server RX or TX timestamp.
This causes an unnecessary RX timestamp to be saved and TX timestamp
captured and saved.

doc/chrony.conf.adoc
ntp_core.c

index c7254120974be63a50891c6449b4ef3e0c09a79d..89f63bb1133e34023cf98bfc70458d88356e3fc5 100644 (file)
@@ -1494,9 +1494,11 @@ directive.
 This directive specifies the maximum amount of memory that *chronyd* is allowed
 to allocate for logging of client accesses and the state that *chronyd* as an
 NTP server needs to support the interleaved mode for its clients. The default
-limit is 524288 bytes, which is sufficient for monitoring about four thousand
-clients at the same time. The maximum value is 2^32-1 (4 GB) on 32-bit systems
-and 2^35 (32 GB) on 64-bit systems.
+limit is 524288 bytes, which enables monitoring of up to 4096 IP addresses at
+the same time and holding NTP timestamps for up to 4096 clients using the
+interleaved mode (depending on uniformity of their polling interval). The
+maximum value is 2^32-1 (4 GB) on 32-bit systems and 2^35 (32 GB) on 64-bit
+systems.
 +
 An example of the use of this directive is:
 +
index 1f11b2bf2305518374314464e0c15d70c71d1c79..0a5cd4470d7c0c5f0c7a49ead0b1eed96ffdacdf 100644 (file)
@@ -1083,6 +1083,13 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
            UTI_IsEqualAnyNtp64(&message.transmit_ts, &message.receive_ts,
                                &message.originate_ts, local_ntp_tx));
 
+  /* Encode in server timestamps a flag indicating RX timestamp to avoid
+     saving all RX timestamps for detection of interleaved requests */
+  if (my_mode == MODE_SERVER || my_mode == MODE_PASSIVE) {
+    message.receive_ts.lo |= htonl(1);
+    message.transmit_ts.lo &= ~htonl(1);
+  }
+
   /* Generate the authentication data */
   if (auth) {
     if (!NAU_GenerateRequestAuth(auth, &message, &info)) {
@@ -2110,21 +2117,23 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
   tx_ts = NULL;
   interleaved = 0;
 
-  /* Check if the client is using the interleaved mode.  If it is, save the
-     new transmit timestamp and if the old transmit timestamp is valid, respond
-     in the interleaved mode.  This means the third reply to a new client is
-     the earliest one that can be interleaved.  We don't want to waste time
-     on clients that are not using the interleaved mode. */
-  if (kod == 0 &&
+  /* Handle requests formed in the interleaved mode.  As an optimisation to
+     avoid saving all receive timestamps, require that the origin timestamp
+     has the lowest bit equal to 1, which indicates it was set to one of our
+     receive timestamps instead of transmit timestamps or zero.  Respond in the
+     interleaved mode if the receive timestamp is found and it has a non-zero
+     transmit timestamp (this is verified in transmit_packet()).  For a new
+     client starting with a zero origin timestamp, the third response is the
+     earliest one that can be interleaved. */
+  if (kod == 0 && message->originate_ts.lo & htonl(1) &&
       UTI_CompareNtp64(&message->receive_ts, &message->transmit_ts) != 0) {
     ntp_rx = message->originate_ts;
     local_ntp_rx = &ntp_rx;
     interleaved = CLG_GetNtpTxTimestamp(&ntp_rx, &local_tx.ts);
 
-    if (interleaved) {
-      tx_ts = &local_tx;
+    tx_ts = &local_tx;
+    if (interleaved)
       CLG_DisableNtpTimestamps(&ntp_rx);
-    }
   }
 
   /* Suggest the client to increase its polling interval if it indicates