#include "ntpd.h"
#include "ntpsim.h"
#include "ntpdsim-opts.h"
#define SIM_TIME 86400
#define NET_DLY .001
#define PROC_DLY .001
#define BEEP_DLY 3600
#define SLEW 500e-6
void (*funcPtr[]) (Node *, Event) = {
&ndbeep, &ndeclk, &ntptmr, &netpkt
};
int
ntpsim(
int argc,
char *argv[]
)
{
Event e;
double maxtime;
struct timeval seed;
ntp_node.time = 0;
ntp_node.sim_time = SIM_TIME;
ntp_node.ntp_time = 0;
ntp_node.adj = 0;
ntp_node.slew = SLEW;
ntp_node.clk_time = 0;
ntp_node.ferr = 0;
ntp_node.fnse = 0;
ntp_node.ndly = NET_DLY;
ntp_node.snse = 0;
ntp_node.pdly = PROC_DLY;
ntp_node.bdly = BEEP_DLY;
ntp_node.events = NULL;
ntp_node.rbuflist = NULL;
initializing = 1;
init_auth();
init_util();
init_restrict();
init_mon();
init_timer();
init_lib();
init_request();
init_control();
init_peer();
init_proto();
init_io();
init_loopfilter();
mon_start(MON_OFF);
{
int optct = optionProcess(&ntpdsimOptions, argc, argv);
argc -= optct;
argv += optct;
}
getconfig(argc, argv);
initializing = 0;
loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
gettimeofday(&seed, NULL);
ntp_srandom(seed.tv_usec);
push(event(0, BEEP), &ntp_node.events);
push(event(ntp_node.time + 1.0, TIMER), &ntp_node.events);
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);
}
Event
event(
double t,
funcTkn f
)
{
Event e;
e.time = t;
e.function = f;
return (e);
}
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);
}
void push(
Event e,
Queue *qp
)
{
Queue *tmp = qp;
while (*tmp != NULL && ((*tmp)->event.time < e.time))
tmp = &((*tmp)->next);
*tmp = queue(e, (*tmp));
}
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);
}
void
ndeclk(
Node *n,
Event e
)
{
node_clock(n, e.time);
}
void
ntptmr(
Node *n,
Event e
)
{
struct recvbuf *rbuf;
timer();
while (n->rbuflist != NULL) {
rbuf = n->rbuflist;
n->rbuflist = NULL;
(rbuf->receiver)(rbuf);
free(rbuf);
}
push(event(e.time + (1 << EVENT_TIMEOUT), TIMER), &n->events);
}
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;
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;
xpkt.org = rpkt->xmt;
dtemp = poisson(n->ndly, n->snse);
DTOLFP(dtemp + n->clk_time, &xpkt.rec);
dtemp += poisson(n->pdly, 0);
DTOLFP(dtemp + n->clk_time, &xpkt.xmt);
xpkt.reftime = xpkt.xmt;
dtemp += poisson(n->ndly, n->snse);
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));
LFPTOD(&xpkt.org, etemp);
etemp += dtemp;
xvnt = event(etemp, PACKET);
xvnt.rcv_buf = rbuf;
push(xvnt, &n->events);
return (0);
}
void
netpkt(
Node *n,
Event e
)
{
struct recvbuf *rbuf;
struct recvbuf *obuf;
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);
obuf = n->rbuflist;
if (obuf == NULL) {
n->rbuflist = rbuf;
}
}
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);
}
}
void
abortsim(
char *errmsg
)
{
perror(errmsg);
exit(1);
}