Recently I made the switch from ntp to openntpd.  Seemingly random
memory write errors by the ntp daemon finally convinced me that ntp had
become too bloated for the reliability I desired.

So far, my experience with openntpd has been very good.  But I missed
some of the status reporting ability of ntp (e.g, the 'ntpq -c peer'
command).  As part of the daily.local script, I like to capture the
openntpd SIGINFO status, but somehow "4 out of 4 peers valid" was not
the level of information I wanted.  I decided to offer my first code
patch here.

In this patch, I had the following goals:
- no changes to existing time-computation algorithms and data
structures
- no new include files required for compiling
- no new libraries required for linking
- no changes to any files used by make
- treat current openntpd data structures as read-only
- leave current status messages unchanged, as some folk may be using
log file scanners
- log the new status informaiton as "info" priority to avoid cluttering
more important log files
- within the above constraints, provide useful status of openntpd's
interaction with the peers

This is the output you will see in daemon.log when a SIGINFO signal is
received (presuming that syslog puts daemon.info into that file)

=== start of output
 ntpd[1503]: 4 out of 4 peers valid
 ntpd[1503]: clock is synced, stratum 3
 ntpd[1503]: peer
 ntpd[1503]:    wt tl st  next  poll          offset       delay
jitter
 ntpd[1503]: 10.20.1.1 ntp.89lr.home 
 ntpd[1503]:     1 10  3  688s 1550s         0.985mS     0.346mS
0.081mS
 ntpd[1503]: 64.113.32.10 from pool 1.us.pool.ntp.org 
 ntpd[1503]:     1 10  2  721s 1609s         6.404mS    51.893mS
2.624mS
 ntpd[1503]: 67.18.187.111 from pool 1.us.pool.ntp.org 
 ntpd[1503]:     1 10  2  684s 1533s        -2.835mS    80.682mS
4.734mS
 ntpd[1503]: 208.53.158.34 from pool 1.us.pool.ntp.org 
 ntpd[1503]:     1 10  2  641s 1547s        -0.624mS    41.273mS
0.388mS
=== end of output

where the columns for each peer are: weight, trustlevel, stratum, time
remaining to the next poll, poll interval, local clock's offset from
the peer's clock, network delay, jitter in the network delay.



With the above goals in mind, I offer the following patch for 5.1.  

=== begin file ntp_5-1.patch

Apply by doing:
        cd /usr/src
        patch -p0 < ntp_5-1.patch    

And then rebuild and install ntpd:
        cd /usr/src/usr.sbin/ntpd       
        make obj
        make depend
        make
        make install

And finally, run the new version:
        /etc/rc.d/ntpd restart

===================================================================
--- usr.sbin/ntpd/ntp.c
+++ usr.sbin/ntpd/ntp.c  Sun Jun 10 15:07:30 2012
@@ -761,23 +761,103 @@
        }
        lastreport = now;
        if (peer_cnt > 0) {
-               log_warnx("%u out of %u peers valid", peer_cnt - badpeers,
-                   peer_cnt);
+
+               log_warnx("%u out of %u peers valid", 
+                   peer_cnt - badpeers, peer_cnt);
+                   
+               if (conf->status.synced == 1) 
+                   log_info("clock is synced, stratum %u", 
+                       conf->status.stratum);
+               else log_info("clock is unsynced");
+
+               log_info("peer");
+               log_info("   wt tl st  next  poll          offset       "
+                   "delay      jitter");
+
                TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
+                       const char *a = "not resolved";
+                       const char *pool = "";
+
+                       if (p->addr)
+                               a = log_sockaddr(
+                                   (struct sockaddr *)&p->addr->ss);
+                       if (p->addr_head.pool)
+                               pool = "from pool ";
+
+                       log_info("%s %s%s %s",
+                           a, pool, p->addr_head.name, 
+                           print_rtable(p->rtable) );
+
                        if (p->trustlevel < TRUSTLEVEL_BADPEER) {
-                               const char *a = "not resolved";
-                               const char *pool = "";
-                               if (p->addr)
-                                       a = log_sockaddr(
-                                           (struct sockaddr *)&p->addr->ss);
-                               if (p->addr_head.pool)
-                                       pool = "from pool ";
                                log_warnx("bad peer %s%s (%s) %s",
                                    pool, p->addr_head.name, a,
                                    print_rtable(p->rtable));
                        }
+                       else {
+                               u_int8_t shift, best, validdelaycnt, jittercnt;
+                               double avg_offset, avg_delay, jitter;
+
+                               validdelaycnt = best = 0;
+                               avg_offset = avg_delay = 0.0;
+                               for (shift = 0; shift < OFFSET_ARRAY_SIZE; 
+                                   shift++) {
+                                       if (p->reply[shift].delay > 0.0) {
+                                               avg_offset += 
+                                                   p->reply[shift].offset;
+                                               avg_delay += 
+                                                   p->reply[shift].delay;
+
+                                               if (p->reply[shift].delay < 
+                                                   p->reply[best].delay) 
+                                                       best = shift;
+
+                                               validdelaycnt++;
+                                       }
+                               }
+
+                               if (validdelaycnt > 0) {
+                                       avg_offset /= validdelaycnt;
+                                       avg_delay /= validdelaycnt;
+                               }
+
+                               /* use simple average for jitter */
+                               /* calculation, as the RFC5905-recommended */ 
+                               /* RMS average needs the math library */
+                               jittercnt = 0;
+                               jitter = 0.0;
+                               for (shift = 0; shift < OFFSET_ARRAY_SIZE; 
+                                   shift++) {
+                                       if (p->reply[shift].delay > 0.0 && 
+                                           shift != best) {
+                                               jitter += 
+                                                   p->reply[shift].delay - 
+                                                   p->reply[best].delay;
+                                               jittercnt++;
+                                       }
+                               }
+
+                               if (jittercnt > 0) jitter /= jittercnt;
+
+                               if (p->shift == 0) 
+                                   shift = OFFSET_ARRAY_SIZE - 1;
+                               else shift = p->shift - 1;
+
+                               log_info("   %2u %2u %2u %4us %4us   %11.3fmS "
+                                   "%9.3fmS  %8.3fmS", 
+                                   p->weight,
+                                   p->trustlevel, 
+                                   p->reply[shift].status.stratum, 
+                                   p->next - now, 
+                                   p->next - p->reply[shift].rcvd,
+                                   /* milliseconds to reduce number of */
+                                   /*    leading zeroes */
+                                   avg_offset * 1000.0, 
+                                   avg_delay * 1000.0,
+                                   jitter * 1000.0);
+                       }
                }
        }
+
        if (sensors_cnt > 0) {
                log_warnx("%u out of %u sensors valid",
                    sensors_cnt - badsensors, sensors_cnt);



--- usr.sbin/ntpd/ntpd.8
+++ usr.sbin/ntpd/ntpd.8        Sun Jun 10 22:17:40 2012
@@ -122,7 +122,12 @@
 receives a
 .Dv SIGINFO
 signal, it writes its peer and sensor status to
-.Xr syslog 3 .
+.Xr syslog 3 .  Included in the status for each peer are: weight, 
+trustlevel, stratum, time remaining to the next poll (seconds), 
+poll interval (seconds), local clock's offset from the peer's clock 
+(milliseconds), network delay (milliseconds), and jitter in the 
+network delay (milliseconds).
+
 .Sh FILES
 .Bl -tag -width "/var/db/ntpd.driftXXX" -compact
 .It Pa /etc/ntpd.conf

=== end file ntp_5-1.patch

Reply via email to