~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to ntpd/ntpsim.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-10-11 16:10:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041011161027-icyjbji8ujym633o
Tags: 1:4.2.0a-10ubuntu2
Use ntp.ubuntulinux.org instead of pool.ntp.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * NTP simulator engine - Harish Nair
 
3
 * University of Delaware, 2001
 
4
 */
 
5
#include "ntpd.h"
 
6
#include "ntpsim.h"
 
7
 
 
8
/*
 
9
 * Defines...
 
10
 */
 
11
#define SIM_TIME 86400          /* end simulation time */
 
12
#define NET_DLY .001            /* network delay */
 
13
#define PROC_DLY .001           /* processing delay */
 
14
#define BEEP_DLY 3600           /* beep interval (s) */
 
15
#define SLEW    500e-6          /* correction rate (PPM) */
 
16
 
 
17
/*
 
18
 * Function pointers
 
19
 */
 
20
void (*funcPtr[]) (Node *, Event) = {
 
21
        &ndbeep, &ndeclk, &ntptmr, &netpkt
 
22
};
 
23
 
 
24
 
 
25
/*
 
26
 * ntpsim - initialize global variables and event queue and start
 
27
 */
 
28
int
 
29
ntpsim(
 
30
        int     argc,
 
31
        char    *argv[]
 
32
        )
 
33
{
 
34
        Event   e;
 
35
        double  maxtime;
 
36
        struct timeval seed;
 
37
 
 
38
        /*
 
39
         * Initialize the global node
 
40
         */
 
41
        ntp_node.time = 0;              /* simulation time */
 
42
        ntp_node.sim_time = SIM_TIME;   /* end simulation time (-S) */
 
43
        ntp_node.ntp_time = 0;          /* client disciplined time */
 
44
        ntp_node.adj = 0;               /* remaining time correction */
 
45
        ntp_node.slew = SLEW;           /* correction rate (-H) */
 
46
 
 
47
        ntp_node.clk_time = 0;          /* server time (-O) */
 
48
        ntp_node.ferr = 0;              /* frequency error (-T) */
 
49
        ntp_node.fnse = 0;              /* random walk noise (-W) */
 
50
        ntp_node.ndly = NET_DLY;        /* network delay (-Y) */
 
51
        ntp_node.snse = 0;              /* phase noise (-C) */
 
52
        ntp_node.pdly = PROC_DLY;       /* processing delay (-Z) */
 
53
        ntp_node.bdly = BEEP_DLY;       /* beep interval (-B) */
 
54
 
 
55
        ntp_node.events = NULL;
 
56
        ntp_node.rbuflist = NULL;
 
57
 
 
58
        /*
 
59
         * Initialize ntp variables
 
60
         */
 
61
        initializing = 1;
 
62
        init_auth();
 
63
        init_util();
 
64
        init_restrict();
 
65
        init_mon();
 
66
        init_timer();
 
67
        init_lib();
 
68
        init_random();
 
69
        init_request();
 
70
        init_control();
 
71
        init_peer();
 
72
        init_proto();
 
73
        init_io();
 
74
        init_loopfilter();
 
75
        mon_start(MON_OFF);
 
76
        getconfig(argc, argv);
 
77
        initializing = 0;
 
78
 
 
79
        /*
 
80
         * Watch out here, we want the real time, not the silly stuff.
 
81
         */
 
82
        gettimeofday(&seed, NULL);
 
83
        srand48(seed.tv_usec);
 
84
 
 
85
        /*
 
86
         * Push a beep and timer interrupt on the queue
 
87
         */
 
88
        push(event(0, BEEP), &ntp_node.events);
 
89
        push(event(ntp_node.time + 1.0, TIMER), &ntp_node.events);
 
90
 
 
91
        /*
 
92
         * Pop the queue until nothing is left or time is exceeded
 
93
         */
 
94
        maxtime = ntp_node.time + ntp_node.sim_time;
 
95
        while (ntp_node.time <= maxtime && ntp_node.events != NULL ) {
 
96
                e = pop(&ntp_node.events);
 
97
                ndeclk(&ntp_node, e);
 
98
                funcPtr[e.function](&ntp_node, e);
 
99
        }
 
100
        return (0);
 
101
}
 
102
 
 
103
 
 
104
/*
 
105
 * Return an event
 
106
 */
 
107
Event
 
108
event(
 
109
        double t,
 
110
        funcTkn f
 
111
        )
 
112
{
 
113
        Event e;
 
114
 
 
115
        e.time = t;
 
116
        e.function = f;
 
117
        return (e);
 
118
}
 
119
 
 
120
/*
 
121
 * Create an event queue
 
122
 */
 
123
Queue
 
124
queue(
 
125
        Event e,
 
126
        Queue q
 
127
        )
 
128
{
 
129
        Queue ret;
 
130
 
 
131
        if ((ret = (Queue)malloc(sizeof(struct List))) == NULL)
 
132
                abortsim("queue-malloc");
 
133
        ret->event = e;
 
134
        ret->next = q;
 
135
        return (ret);
 
136
}
 
137
 
 
138
 
 
139
/*
 
140
 * Push an event into the event queue
 
141
 */
 
142
void push(
 
143
        Event e,
 
144
        Queue *qp
 
145
        )
 
146
{
 
147
        Queue *tmp = qp;
 
148
 
 
149
        while (*tmp != NULL && ((*tmp)->event.time < e.time))
 
150
                tmp = &((*tmp)->next);
 
151
        *tmp = queue(e, (*tmp));
 
152
}
 
153
 
 
154
 
 
155
/*
 
156
 * Pop the first event from the event queue
 
157
 */
 
158
Event
 
159
pop(
 
160
        Queue *qp
 
161
        )
 
162
{
 
163
        Event ret;
 
164
        Queue tmp;
 
165
 
 
166
        tmp = *qp;
 
167
        if (tmp == NULL)
 
168
            abortsim("pop - empty queue");
 
169
        ret = tmp->event;
 
170
        *qp = tmp->next;
 
171
        free(tmp);
 
172
        return (ret);
 
173
}
 
174
 
 
175
 
 
176
/*
 
177
 * Update clocks
 
178
 */
 
179
void
 
180
ndeclk(
 
181
        Node *n,
 
182
        Event e
 
183
        )
 
184
{
 
185
        node_clock(n, e.time);
 
186
}
 
187
 
 
188
 
 
189
/*
 
190
 * Timer interrupt. Eventually, this results in calling the
 
191
 * srvr_rplyi() routine below.
 
192
 */
 
193
void
 
194
ntptmr(
 
195
        Node *n,
 
196
        Event e
 
197
        )
 
198
{
 
199
        struct recvbuf *rbuf;
 
200
 
 
201
        timer();
 
202
 
 
203
        /*
 
204
         * Process buffers received. They had better be in order by
 
205
         * receive timestamp.
 
206
         */
 
207
        while (n->rbuflist != NULL) {
 
208
                rbuf = n->rbuflist;
 
209
                n->rbuflist = rbuf->next;
 
210
                (rbuf->receiver)(rbuf);
 
211
                free(rbuf);
 
212
        }
 
213
 
 
214
        /*
 
215
         * Arm the next timer interrupt.
 
216
         */
 
217
        push(event(e.time + (1 << EVENT_TIMEOUT), TIMER), &n->events);
 
218
}
 
219
 
 
220
 
 
221
/*
 
222
 * srvr_rply() - send packet
 
223
 */
 
224
int srvr_rply(
 
225
        Node *n,
 
226
        struct sockaddr_storage *dest,
 
227
        struct interface *inter, struct pkt *rpkt
 
228
        )
 
229
{
 
230
        struct pkt xpkt;
 
231
        struct recvbuf rbuf;
 
232
        Event   xvnt;
 
233
        double  dtemp, etemp;
 
234
 
 
235
        /*
 
236
         * Insert packet header values. We make this look like a
 
237
         * stratum-1 server with a GPS clock, but nobody will ever
 
238
         * notice that.
 
239
         */
 
240
        xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
 
241
            MODE_SERVER);
 
242
        xpkt.stratum = STRATUM_TO_PKT(((u_char)1));
 
243
        memcpy(&xpkt.refid, "GPS", 4);
 
244
        xpkt.ppoll = rpkt->ppoll;
 
245
        xpkt.precision = rpkt->precision;
 
246
        xpkt.rootdelay = 0;
 
247
        xpkt.rootdispersion = 0;
 
248
 
 
249
        /*
 
250
         * Insert the timestamps.
 
251
         */
 
252
        xpkt.org = rpkt->xmt;
 
253
        dtemp = poisson(n->ndly, n->snse); /* client->server delay */
 
254
        DTOLFP(dtemp + n->clk_time, &xpkt.rec);
 
255
        dtemp += poisson(n->pdly, 0);   /* server delay */
 
256
        DTOLFP(dtemp + n->clk_time, &xpkt.xmt);
 
257
        xpkt.reftime = xpkt.xmt;
 
258
        dtemp += poisson(n->ndly, n->snse); /* server->client delay */
 
259
 
 
260
        /*
 
261
         * Insert the I/O stuff.
 
262
         */
 
263
        rbuf.receiver = receive;
 
264
        get_systime(&rbuf.recv_time);
 
265
        rbuf.recv_length = LEN_PKT_NOMAC;
 
266
        rbuf.recv_pkt = xpkt;
 
267
        memcpy(&rbuf.srcadr, dest, sizeof(struct sockaddr_storage));
 
268
        memcpy(&rbuf.recv_srcadr, dest,
 
269
            sizeof(struct sockaddr_storage));
 
270
        if ((rbuf.dstadr = malloc(sizeof(struct interface))) == NULL)
 
271
                abortsim("server-malloc");
 
272
        memcpy(rbuf.dstadr, inter, sizeof(struct interface));
 
273
        rbuf.next = NULL;
 
274
 
 
275
        /*
 
276
         * Very carefully predict the time of arrival for the received
 
277
         * packet. 
 
278
         */ 
 
279
        LFPTOD(&xpkt.org, etemp);
 
280
        etemp += dtemp;
 
281
        xvnt = event(etemp, PACKET);
 
282
        xvnt.rcv_buf = rbuf;
 
283
        push(xvnt, &n->events);
 
284
        return (0);
 
285
}
 
286
 
 
287
 
 
288
/*
 
289
 * netpkt() - receive packet
 
290
 */
 
291
void
 
292
netpkt(
 
293
        Node *n,
 
294
        Event e
 
295
        )
 
296
{
 
297
        struct recvbuf *rbuf;
 
298
        struct recvbuf *obuf;
 
299
 
 
300
        /*
 
301
         * Insert the packet on the receive queue and record the arrival
 
302
         * time.
 
303
         */
 
304
        if ((rbuf = malloc(sizeof(struct recvbuf))) == NULL)
 
305
                abortsim("ntprcv-malloc");
 
306
        memcpy(rbuf, &e.rcv_buf, sizeof(struct recvbuf));
 
307
        rbuf->receiver = receive;
 
308
        DTOLFP(n->ntp_time, &rbuf->recv_time);
 
309
        rbuf->next = NULL;
 
310
        obuf = n->rbuflist;
 
311
 
 
312
        /*
 
313
         * In the present incarnation, no more than one buffer can be on
 
314
         * the queue; however, we sniff the queue anyway as a hint for
 
315
         * further development.
 
316
         */
 
317
        if (obuf == NULL) {
 
318
                n->rbuflist = rbuf;
 
319
        } else {
 
320
                while (obuf->next != NULL)
 
321
                        obuf = obuf->next;
 
322
                obuf->next = rbuf;
 
323
        }
 
324
}
 
325
 
 
326
 
 
327
/*
 
328
 * ndbeep() - progress indicator
 
329
 */
 
330
void
 
331
ndbeep(
 
332
        Node *n,
 
333
        Event e
 
334
        )
 
335
{
 
336
        static int first_time = 1;
 
337
        char *dash = "-----------------";
 
338
 
 
339
        if(n->bdly > 0) {
 
340
                if (first_time) {
 
341
                        printf(
 
342
                            "\t%4c    T    %4c\t%4c  T+ERR  %3c\t%5cT+ERR+NTP\n", ' ', ' ', ' ', ' ',' ');
 
343
                        printf("\t%s\t%s\t%s\n", dash, dash, dash);
 
344
                        first_time = 0;
 
345
                        push(event(n->bdly, BEEP), &n->events);  
 
346
                        push(event(n->sim_time, BEEP), &n->events);
 
347
                        printf("\t%16.6f\t%16.6f\t%16.6f\n",
 
348
                            n->time, n->clk_time, n->ntp_time);
 
349
                        return;
 
350
                }
 
351
                printf("\t%16.6f\t%16.6f\t%16.6f\n",
 
352
                    n->time, n->clk_time, n->ntp_time);
 
353
                push(event(e.time + n->bdly, BEEP), &n->events);
 
354
        }
 
355
}
 
356
 
 
357
 
 
358
/*
 
359
 * Abort simulation
 
360
 */
 
361
void
 
362
abortsim(
 
363
        char *errmsg
 
364
        )
 
365
{
 
366
        perror(errmsg);
 
367
        exit(1);
 
368
}