Implement a course offset adjustment for large time steps.
[dragonfly.git] / usr.sbin / dntpd / client.h
1 /*
2  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/usr.sbin/dntpd/client.h,v 1.5 2005/04/25 17:42:49 dillon Exp $
35  */
36
37 struct server_info {
38         int fd;                 /* udp descriptor */
39         int poll_sleep;         /* countdown for poll (in seconds) */
40         int poll_mode;          /* mode of operation */
41         int poll_count;         /* number of polls in current mode */
42         int poll_failed;        /* count of NTP failures */
43         char *target;           /* target hostname or IP (string) */
44
45         /*
46          * A second linear regression playing hopskip with the first.  This
47          * is maintained by the check function.
48          */
49         struct server_info *altinfo;
50
51         /*
52          * Linear regression accumulator
53          *
54          * note: the starting base time is where all corrections get applied
55          * to eventually.  The linear regression makes a relative microseconds
56          * calculation between the current base time and the starting base
57          * time to figure out what corrections the system has made to the
58          * clock.
59          */
60         struct timeval lin_tv;  /* starting real time */
61         struct timeval lin_btv; /* starting base time */
62         double lin_count;       /* samples      */
63         double lin_sumx;        /* sum(x)       */
64         double lin_sumy;        /* sum(y)       */
65         double lin_sumxy;       /* sum(x*y)     */
66         double lin_sumx2;       /* sum(x^2)     */
67         double lin_sumy2;       /* sum(y^2)     */
68
69         /*
70          * Offsets are accumulated for a straight average.  When a
71          * correction is made we have to reset the averaging code
72          * or follow-up corrections will oscillate wildly because
73          * the new offsets simply cannot compete with the dozens
74          * of previously polls in the sum.
75          */
76         double lin_sumoffset;   /* sum of compensated offsets */
77         double lin_sumoffset2;  /* sum of compensated offsets^2 */
78         double lin_countoffset; /* count is reset after a correction is made */
79
80         /*
81          * Cached results
82          */
83         double lin_cache_slope; /* (freq calculations) */
84         double lin_cache_yint;  /* (freq calculations) */
85         double lin_cache_corr;  /* (freq calculations) */
86         double lin_cache_stddev; /* (offset calculations) */
87
88         double lin_cache_offset; /* last sampled offset (NOT an average) */
89         double lin_cache_freq;  /* last frequency correction (s/s) */
90 };
91
92 /*
93  * Polling modes and max polls for specific modes.  Note that the polling
94  * mode basically just effects the polling rate.  It does not effect the
95  * linear regression.
96  */
97 #define POLL_FIXED      0       /* fixed internal (nom_sleep_opt seconds) */
98 #define POLL_STARTUP    1       /* startup fastpoll for offset adjust (min) */
99 #define POLL_ACQUIRE    2       /* acquisition for frequency adjust (nom) */
100 #define POLL_MAINTAIN   3       /* maintainance mode (max) */
101 #define POLL_FAILED_1   4       /* recent failure state (nom) */
102 #define POLL_FAILED_2   5       /* aged failure state (nom) */
103
104 #define POLL_STARTUP_MAX        6       /* max polls in this mode */
105 #define POLL_ACQUIRE_MAX        16      /* max polls in this mode */
106 #define POLL_FAIL_RESET         3       /* reset the regression after 3 fails */
107 #define POLL_RECOVERY_RESTART   10      /* ->ACQ vs ->STARTUP after recovery */
108
109 /*
110  * We start a second linear regression a LIN_RESTART / 2 and it
111  * replaces the first one (and we start a third) at LIN_RESTART.
112  */
113 #define LIN_RESTART     30
114
115 /*
116  * A course correction is made if the time gets more then 10 minutes
117  * off.
118  */
119 #define COURSE_OFFSET_CORRECTION_LIMIT  600.0
120
121 typedef struct server_info *server_info_t;
122
123 void client_init(void);
124 int client_main(struct server_info **info_ary, int count);
125 void client_poll(server_info_t info, int poll_interval);
126 void client_check(struct server_info **check, 
127                   struct server_info **best_off,
128                   struct server_info **best_freq);
129 void client_manage_polling_mode(struct server_info *info);
130
131 void lin_regress(server_info_t info, 
132                  struct timeval *ltv, struct timeval *lbtv, double offset);
133 void lin_reset(server_info_t info);
134 void lin_resetalloffsets(struct server_info **info_ary, int count);
135 void lin_resetoffsets(server_info_t info);
136