summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd/ntpsim.c
diff options
context:
space:
mode:
authorroberto <roberto@FreeBSD.org>2004-07-20 15:01:56 +0000
committerroberto <roberto@FreeBSD.org>2004-07-20 15:01:56 +0000
commit118e757284cbb8fc4f43a713e892b41504b50a5f (patch)
tree528d12dda44ebdc3ffcc38050f159ac553a69c17 /contrib/ntp/ntpd/ntpsim.c
parenta85d9ae25e8e8696677bc30feb6eaf7fc150e529 (diff)
downloadFreeBSD-src-118e757284cbb8fc4f43a713e892b41504b50a5f.zip
FreeBSD-src-118e757284cbb8fc4f43a713e892b41504b50a5f.tar.gz
Virgin import of ntpd 4.2.0
Diffstat (limited to 'contrib/ntp/ntpd/ntpsim.c')
-rw-r--r--contrib/ntp/ntpd/ntpsim.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/contrib/ntp/ntpd/ntpsim.c b/contrib/ntp/ntpd/ntpsim.c
new file mode 100644
index 0000000..3fbae17
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpsim.c
@@ -0,0 +1,368 @@
+/*
+ * NTP simulator engine - Harish Nair
+ * University of Delaware, 2001
+ */
+#include "ntpd.h"
+#include "ntpsim.h"
+
+/*
+ * Defines...
+ */
+#define SIM_TIME 86400 /* end simulation time */
+#define NET_DLY .001 /* network delay */
+#define PROC_DLY .001 /* processing delay */
+#define BEEP_DLY 3600 /* beep interval (s) */
+#define SLEW 500e-6 /* correction rate (PPM) */
+
+/*
+ * Function pointers
+ */
+void (*funcPtr[]) (Node *, Event) = {
+ &ndbeep, &ndeclk, &ntptmr, &netpkt
+};
+
+
+/*
+ * ntpsim - initialize global variables and event queue and start
+ */
+int
+ntpsim(
+ int argc,
+ char *argv[]
+ )
+{
+ Event e;
+ double maxtime;
+ struct timeval seed;
+
+ /*
+ * Initialize the global node
+ */
+ ntp_node.time = 0; /* simulation time */
+ ntp_node.sim_time = SIM_TIME; /* end simulation time (-S) */
+ ntp_node.ntp_time = 0; /* client disciplined time */
+ ntp_node.adj = 0; /* remaining time correction */
+ ntp_node.slew = SLEW; /* correction rate (-H) */
+
+ ntp_node.clk_time = 0; /* server time (-O) */
+ ntp_node.ferr = 0; /* frequency error (-T) */
+ ntp_node.fnse = 0; /* random walk noise (-W) */
+ ntp_node.ndly = NET_DLY; /* network delay (-Y) */
+ ntp_node.snse = 0; /* phase noise (-C) */
+ ntp_node.pdly = PROC_DLY; /* processing delay (-Z) */
+ ntp_node.bdly = BEEP_DLY; /* beep interval (-B) */
+
+ ntp_node.events = NULL;
+ ntp_node.rbuflist = NULL;
+
+ /*
+ * Initialize ntp variables
+ */
+ initializing = 1;
+ init_auth();
+ init_util();
+ init_restrict();
+ init_mon();
+ init_timer();
+ init_lib();
+ init_random();
+ init_request();
+ init_control();
+ init_peer();
+ init_proto();
+ init_io();
+ init_loopfilter();
+ mon_start(MON_OFF);
+ getconfig(argc, argv);
+ initializing = 0;
+
+ /*
+ * Watch out here, we want the real time, not the silly stuff.
+ */
+ gettimeofday(&seed, NULL);
+ srand48(seed.tv_usec);
+
+ /*
+ * Push a beep and timer interrupt on the queue
+ */
+ push(event(0, BEEP), &ntp_node.events);
+ push(event(ntp_node.time + 1.0, TIMER), &ntp_node.events);
+
+ /*
+ * Pop the queue until nothing is left or time is exceeded
+ */
+ maxtime = ntp_node.time + ntp_node.sim_time;
+ while (ntp_node.time <= maxtime && ntp_node.events != NULL ) {
+ e = pop(&ntp_node.events);
+ ndeclk(&ntp_node, e);
+ funcPtr[e.function](&ntp_node, e);
+ }
+ return (0);
+}
+
+
+/*
+ * Return an event
+ */
+Event
+event(
+ double t,
+ funcTkn f
+ )
+{
+ Event e;
+
+ e.time = t;
+ e.function = f;
+ return (e);
+}
+
+/*
+ * Create an event queue
+ */
+Queue
+queue(
+ Event e,
+ Queue q
+ )
+{
+ Queue ret;
+
+ if ((ret = (Queue)malloc(sizeof(struct List))) == NULL)
+ abortsim("queue-malloc");
+ ret->event = e;
+ ret->next = q;
+ return (ret);
+}
+
+
+/*
+ * Push an event into the event queue
+ */
+void push(
+ Event e,
+ Queue *qp
+ )
+{
+ Queue *tmp = qp;
+
+ while (*tmp != NULL && ((*tmp)->event.time < e.time))
+ tmp = &((*tmp)->next);
+ *tmp = queue(e, (*tmp));
+}
+
+
+/*
+ * Pop the first event from the event queue
+ */
+Event
+pop(
+ Queue *qp
+ )
+{
+ Event ret;
+ Queue tmp;
+
+ tmp = *qp;
+ if (tmp == NULL)
+ abortsim("pop - empty queue");
+ ret = tmp->event;
+ *qp = tmp->next;
+ free(tmp);
+ return (ret);
+}
+
+
+/*
+ * Update clocks
+ */
+void
+ndeclk(
+ Node *n,
+ Event e
+ )
+{
+ node_clock(n, e.time);
+}
+
+
+/*
+ * Timer interrupt. Eventually, this results in calling the
+ * srvr_rplyi() routine below.
+ */
+void
+ntptmr(
+ Node *n,
+ Event e
+ )
+{
+ struct recvbuf *rbuf;
+
+ timer();
+
+ /*
+ * Process buffers received. They had better be in order by
+ * receive timestamp.
+ */
+ while (n->rbuflist != NULL) {
+ rbuf = n->rbuflist;
+ n->rbuflist = rbuf->next;
+ (rbuf->receiver)(rbuf);
+ free(rbuf);
+ }
+
+ /*
+ * Arm the next timer interrupt.
+ */
+ push(event(e.time + (1 << EVENT_TIMEOUT), TIMER), &n->events);
+}
+
+
+/*
+ * srvr_rply() - send packet
+ */
+int srvr_rply(
+ Node *n,
+ struct sockaddr_storage *dest,
+ struct interface *inter, struct pkt *rpkt
+ )
+{
+ struct pkt xpkt;
+ struct recvbuf rbuf;
+ Event xvnt;
+ double dtemp, etemp;
+
+ /*
+ * Insert packet header values. We make this look like a
+ * stratum-1 server with a GPS clock, but nobody will ever
+ * notice that.
+ */
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
+ MODE_SERVER);
+ xpkt.stratum = STRATUM_TO_PKT(((u_char)1));
+ memcpy(&xpkt.refid, "GPS", 4);
+ xpkt.ppoll = rpkt->ppoll;
+ xpkt.precision = rpkt->precision;
+ xpkt.rootdelay = 0;
+ xpkt.rootdispersion = 0;
+
+ /*
+ * Insert the timestamps.
+ */
+ xpkt.org = rpkt->xmt;
+ dtemp = poisson(n->ndly, n->snse); /* client->server delay */
+ DTOLFP(dtemp + n->clk_time, &xpkt.rec);
+ dtemp += poisson(n->pdly, 0); /* server delay */
+ DTOLFP(dtemp + n->clk_time, &xpkt.xmt);
+ xpkt.reftime = xpkt.xmt;
+ dtemp += poisson(n->ndly, n->snse); /* server->client delay */
+
+ /*
+ * Insert the I/O stuff.
+ */
+ rbuf.receiver = receive;
+ get_systime(&rbuf.recv_time);
+ rbuf.recv_length = LEN_PKT_NOMAC;
+ rbuf.recv_pkt = xpkt;
+ memcpy(&rbuf.srcadr, dest, sizeof(struct sockaddr_storage));
+ memcpy(&rbuf.recv_srcadr, dest,
+ sizeof(struct sockaddr_storage));
+ if ((rbuf.dstadr = malloc(sizeof(struct interface))) == NULL)
+ abortsim("server-malloc");
+ memcpy(rbuf.dstadr, inter, sizeof(struct interface));
+ rbuf.next = NULL;
+
+ /*
+ * Very carefully predict the time of arrival for the received
+ * packet.
+ */
+ LFPTOD(&xpkt.org, etemp);
+ etemp += dtemp;
+ xvnt = event(etemp, PACKET);
+ xvnt.rcv_buf = rbuf;
+ push(xvnt, &n->events);
+ return (0);
+}
+
+
+/*
+ * netpkt() - receive packet
+ */
+void
+netpkt(
+ Node *n,
+ Event e
+ )
+{
+ struct recvbuf *rbuf;
+ struct recvbuf *obuf;
+
+ /*
+ * Insert the packet on the receive queue and record the arrival
+ * time.
+ */
+ if ((rbuf = malloc(sizeof(struct recvbuf))) == NULL)
+ abortsim("ntprcv-malloc");
+ memcpy(rbuf, &e.rcv_buf, sizeof(struct recvbuf));
+ rbuf->receiver = receive;
+ DTOLFP(n->ntp_time, &rbuf->recv_time);
+ rbuf->next = NULL;
+ obuf = n->rbuflist;
+
+ /*
+ * In the present incarnation, no more than one buffer can be on
+ * the queue; however, we sniff the queue anyway as a hint for
+ * further development.
+ */
+ if (obuf == NULL) {
+ n->rbuflist = rbuf;
+ } else {
+ while (obuf->next != NULL)
+ obuf = obuf->next;
+ obuf->next = rbuf;
+ }
+}
+
+
+/*
+ * ndbeep() - progress indicator
+ */
+void
+ndbeep(
+ Node *n,
+ Event e
+ )
+{
+ static int first_time = 1;
+ char *dash = "-----------------";
+
+ if(n->bdly > 0) {
+ if (first_time) {
+ printf(
+ "\t%4c T %4c\t%4c T+ERR %3c\t%5cT+ERR+NTP\n", ' ', ' ', ' ', ' ',' ');
+ printf("\t%s\t%s\t%s\n", dash, dash, dash);
+ first_time = 0;
+ push(event(n->bdly, BEEP), &n->events);
+ push(event(n->sim_time, BEEP), &n->events);
+ printf("\t%16.6f\t%16.6f\t%16.6f\n",
+ n->time, n->clk_time, n->ntp_time);
+ return;
+ }
+ printf("\t%16.6f\t%16.6f\t%16.6f\n",
+ n->time, n->clk_time, n->ntp_time);
+ push(event(e.time + n->bdly, BEEP), &n->events);
+ }
+}
+
+
+/*
+ * Abort simulation
+ */
+void
+abortsim(
+ char *errmsg
+ )
+{
+ perror(errmsg);
+ exit(1);
+}
OpenPOWER on IntegriCloud