Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / ntpd / ntpsim.c
blob53e08a00377bb171c8042059548801c0c021851a
1 /* $NetBSD: ntpsim.c,v 1.3 2006/06/11 19:34:12 kardel Exp $ */
3 /*
4 * NTP simulator engine - Harish Nair
5 * University of Delaware, 2001
6 */
7 #include "ntpd.h"
8 #include "ntpsim.h"
9 #include "ntpdsim-opts.h"
12 * Defines...
14 #define SIM_TIME 86400 /* end simulation time */
15 #define NET_DLY .001 /* network delay */
16 #define PROC_DLY .001 /* processing delay */
17 #define BEEP_DLY 3600 /* beep interval (s) */
18 #define SLEW 500e-6 /* correction rate (PPM) */
21 * Function pointers
23 void (*funcPtr[]) (Node *, Event) = {
24 &ndbeep, &ndeclk, &ntptmr, &netpkt
29 * ntpsim - initialize global variables and event queue and start
31 int
32 ntpsim(
33 int argc,
34 char *argv[]
37 Event e;
38 double maxtime;
39 struct timeval seed;
42 * Initialize the global node
44 ntp_node.time = 0; /* simulation time */
45 ntp_node.sim_time = SIM_TIME; /* end simulation time (-S) */
46 ntp_node.ntp_time = 0; /* client disciplined time */
47 ntp_node.adj = 0; /* remaining time correction */
48 ntp_node.slew = SLEW; /* correction rate (-H) */
50 ntp_node.clk_time = 0; /* server time (-O) */
51 ntp_node.ferr = 0; /* frequency error (-T) */
52 ntp_node.fnse = 0; /* random walk noise (-W) */
53 ntp_node.ndly = NET_DLY; /* network delay (-Y) */
54 ntp_node.snse = 0; /* phase noise (-C) */
55 ntp_node.pdly = PROC_DLY; /* processing delay (-Z) */
56 ntp_node.bdly = BEEP_DLY; /* beep interval (-B) */
58 ntp_node.events = NULL;
59 ntp_node.rbuflist = NULL;
62 * Initialize ntp variables
64 initializing = 1;
65 init_auth();
66 init_util();
67 init_restrict();
68 init_mon();
69 init_timer();
70 init_lib();
71 init_request();
72 init_control();
73 init_peer();
74 init_proto();
75 init_io();
76 init_loopfilter();
77 mon_start(MON_OFF);
80 int optct = optionProcess(&ntpdsimOptions, argc, argv);
81 argc -= optct;
82 argv += optct;
85 getconfig(argc, argv);
87 initializing = 0;
88 loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
91 * Watch out here, we want the real time, not the silly stuff.
93 gettimeofday(&seed, NULL);
94 ntp_srandom(seed.tv_usec);
97 * Push a beep and timer interrupt on the queue
99 push(event(0, BEEP), &ntp_node.events);
100 push(event(ntp_node.time + 1.0, TIMER), &ntp_node.events);
103 * Pop the queue until nothing is left or time is exceeded
105 maxtime = ntp_node.time + ntp_node.sim_time;
106 while (ntp_node.time <= maxtime && ntp_node.events != NULL ) {
107 e = pop(&ntp_node.events);
108 ndeclk(&ntp_node, e);
109 funcPtr[e.function](&ntp_node, e);
111 return (0);
116 * Return an event
118 Event
119 event(
120 double t,
121 funcTkn f
124 Event e;
126 e.time = t;
127 e.function = f;
128 return (e);
132 * Create an event queue
134 Queue
135 queue(
136 Event e,
137 Queue q
140 Queue ret;
142 if ((ret = (Queue)malloc(sizeof(struct List))) == NULL)
143 abortsim("queue-malloc");
144 ret->event = e;
145 ret->next = q;
146 return (ret);
151 * Push an event into the event queue
153 void push(
154 Event e,
155 Queue *qp
158 Queue *tmp = qp;
160 while (*tmp != NULL && ((*tmp)->event.time < e.time))
161 tmp = &((*tmp)->next);
162 *tmp = queue(e, (*tmp));
167 * Pop the first event from the event queue
169 Event
170 pop(
171 Queue *qp
174 Event ret;
175 Queue tmp;
177 tmp = *qp;
178 if (tmp == NULL)
179 abortsim("pop - empty queue");
180 ret = tmp->event;
181 *qp = tmp->next;
182 free(tmp);
183 return (ret);
188 * Update clocks
190 void
191 ndeclk(
192 Node *n,
193 Event e
196 node_clock(n, e.time);
201 * Timer interrupt. Eventually, this results in calling the
202 * srvr_rplyi() routine below.
204 void
205 ntptmr(
206 Node *n,
207 Event e
210 struct recvbuf *rbuf;
212 timer();
215 * Process buffers received. They had better be in order by
216 * receive timestamp. Note that there are no additional buffers
217 * in the current implementation of ntpsim.
219 while (n->rbuflist != NULL) {
220 rbuf = n->rbuflist;
221 n->rbuflist = NULL;
222 (rbuf->receiver)(rbuf);
223 free(rbuf);
227 * Arm the next timer interrupt.
229 push(event(e.time + (1 << EVENT_TIMEOUT), TIMER), &n->events);
234 * srvr_rply() - send packet
236 int srvr_rply(
237 Node *n,
238 struct sockaddr_storage *dest,
239 struct interface *inter, struct pkt *rpkt
242 struct pkt xpkt;
243 struct recvbuf rbuf;
244 Event xvnt;
245 double dtemp, etemp;
248 * Insert packet header values. We make this look like a
249 * stratum-1 server with a GPS clock, but nobody will ever
250 * notice that.
252 xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
253 MODE_SERVER);
254 xpkt.stratum = STRATUM_TO_PKT(((u_char)1));
255 memcpy(&xpkt.refid, "GPS", 4);
256 xpkt.ppoll = rpkt->ppoll;
257 xpkt.precision = rpkt->precision;
258 xpkt.rootdelay = 0;
259 xpkt.rootdispersion = 0;
262 * Insert the timestamps.
264 xpkt.org = rpkt->xmt;
265 dtemp = poisson(n->ndly, n->snse); /* client->server delay */
266 DTOLFP(dtemp + n->clk_time, &xpkt.rec);
267 dtemp += poisson(n->pdly, 0); /* server delay */
268 DTOLFP(dtemp + n->clk_time, &xpkt.xmt);
269 xpkt.reftime = xpkt.xmt;
270 dtemp += poisson(n->ndly, n->snse); /* server->client delay */
273 * Insert the I/O stuff.
275 rbuf.receiver = receive;
276 get_systime(&rbuf.recv_time);
277 rbuf.recv_length = LEN_PKT_NOMAC;
278 rbuf.recv_pkt = xpkt;
279 memcpy(&rbuf.srcadr, dest, sizeof(struct sockaddr_storage));
280 memcpy(&rbuf.recv_srcadr, dest,
281 sizeof(struct sockaddr_storage));
282 if ((rbuf.dstadr = malloc(sizeof(struct interface))) == NULL)
283 abortsim("server-malloc");
284 memcpy(rbuf.dstadr, inter, sizeof(struct interface));
287 * Very carefully predict the time of arrival for the received
288 * packet.
290 LFPTOD(&xpkt.org, etemp);
291 etemp += dtemp;
292 xvnt = event(etemp, PACKET);
293 xvnt.rcv_buf = rbuf;
294 push(xvnt, &n->events);
295 return (0);
300 * netpkt() - receive packet
302 void
303 netpkt(
304 Node *n,
305 Event e
308 struct recvbuf *rbuf;
309 struct recvbuf *obuf;
312 * Insert the packet on the receive queue and record the arrival
313 * time.
315 if ((rbuf = malloc(sizeof(struct recvbuf))) == NULL)
316 abortsim("ntprcv-malloc");
317 memcpy(rbuf, &e.rcv_buf, sizeof(struct recvbuf));
318 rbuf->receiver = receive;
319 DTOLFP(n->ntp_time, &rbuf->recv_time);
320 obuf = n->rbuflist;
323 * In the present incarnation, no more than one buffer can be on
324 * the queue;
326 if (obuf == NULL) {
327 n->rbuflist = rbuf;
333 * ndbeep() - progress indicator
335 void
336 ndbeep(
337 Node *n,
338 Event e
341 static int first_time = 1;
342 char *dash = "-----------------";
344 if(n->bdly > 0) {
345 if (first_time) {
346 printf(
347 "\t%4c T %4c\t%4c T+ERR %3c\t%5cT+ERR+NTP\n", ' ', ' ', ' ', ' ',' ');
348 printf("\t%s\t%s\t%s\n", dash, dash, dash);
349 first_time = 0;
350 push(event(n->bdly, BEEP), &n->events);
351 push(event(n->sim_time, BEEP), &n->events);
352 printf("\t%16.6f\t%16.6f\t%16.6f\n",
353 n->time, n->clk_time, n->ntp_time);
354 return;
356 printf("\t%16.6f\t%16.6f\t%16.6f\n",
357 n->time, n->clk_time, n->ntp_time);
358 push(event(e.time + n->bdly, BEEP), &n->events);
364 * Abort simulation
366 void
367 abortsim(
368 char *errmsg
371 perror(errmsg);
372 exit(1);