#ifdef SIM
#include "ntpd.h"
#include "ntpsim.h"
#include "ntp_data_structures.h"
sim_info simulation;
local_clock_info simclock;
queue *event_queue;
queue *recv_queue;
static double sys_residual = 0;
void (*event_ptr[]) (Event *) = {
sim_event_beep, sim_update_clocks, sim_event_timer, sim_event_recv_packet
};
int determine_event_ordering(Event *e1, Event *e2);
int determine_event_ordering(Event *e1, Event *e2)
{
return (e1->time - e2->time);
}
int determine_recv_buf_ordering(struct recvbuf *b1, struct recvbuf *b2);
int determine_recv_buf_ordering(struct recvbuf *b1, struct recvbuf *b2)
{
double recv_time1, recv_time2;
LFPTOD(&b1->recv_time, recv_time1);
LFPTOD(&b2->recv_time, recv_time2);
return ((int)(recv_time1 - recv_time2));
}
void create_server_associations()
{
int i;
for (i = 0;i < simulation.num_of_servers;++i) {
printf("%s\n", stoa(simulation.servers[i].addr));
if (peer_config(simulation.servers[i].addr,
ANY_INTERFACE_CHOOSE(simulation.servers[i].addr),
MODE_CLIENT,
NTP_VERSION,
NTP_MINDPOLL,
NTP_MAXDPOLL,
0,
0,
0,
(u_char *)"*" ) == 0) {
fprintf(stderr, "ERROR!! Could not create association for: %s",
stoa(simulation.servers[i].addr));
}
}
}
int ntpsim(int argc, char *argv[])
{
Event *curr_event;
struct timeval seed;
simclock.local_time = 0;
simclock.adj = 0;
simclock.slew = 0;
simulation.num_of_servers = 0;
simulation.beep_delay = BEEP_DLY;
simulation.sim_time = 0;
simulation.end_time = SIM_TIME;
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);
getconfig(argc, argv);
initializing = 0;
loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
gettimeofday(&seed, NULL);
ntp_srandom(seed.tv_usec);
event_queue = create_priority_queue((int(*)(void *, void*))
determine_event_ordering);
recv_queue = create_priority_queue((int(*)(void *, void*))
determine_recv_buf_ordering);
enqueue(event_queue, event(0, BEEP));
enqueue(event_queue, event(simulation.sim_time + 1.0, TIMER));
while (simulation.sim_time <= simulation.end_time &&
(!empty(event_queue))) {
curr_event = dequeue(event_queue);
sim_update_clocks(curr_event);
event_ptr[curr_event->function](curr_event);
free_node(curr_event);
}
return (0);
}
Event *event(double t, funcTkn f)
{
Event *e;
if ((e = get_node(sizeof(*e))) == NULL)
abortsim("get_node failed in event");
e->time = t;
e->function = f;
return (e);
}
void sim_event_timer(Event *e)
{
struct recvbuf *rbuf;
timer();
while (!empty(recv_queue)) {
rbuf = (struct recvbuf *)dequeue(recv_queue);
(rbuf->receiver)(rbuf);
free_node(rbuf);
}
enqueue(event_queue,
event(simulation.sim_time + (1 << EVENT_TIMEOUT), TIMER));
}
int simulate_server(
sockaddr_u *serv_addr,
struct interface *inter,
struct pkt *rpkt
)
{
struct pkt xpkt;
struct recvbuf rbuf;
Event *e;
server_info *server;
script_info *curr_script;
int i;
double d1, d2, d3;
double t1, t2, t3, t4;
memset(&xpkt, 0, sizeof(xpkt));
memset(&rbuf, 0, sizeof(rbuf));
server = NULL;
for (i = 0; i < simulation.num_of_servers; ++i) {
fprintf(stderr,"Checking address: %s\n", stoa(simulation.servers[i].addr));
if (memcmp(simulation.servers[i].addr, serv_addr,
sizeof(*serv_addr)) == 0) {
server = &simulation.servers[i];
break;
}
}
fprintf(stderr, "Received packet for: %s\n", stoa(serv_addr));
if (server == NULL)
abortsim("Server with specified address not found!!!");
curr_script = server->curr_script;
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.rootdisp = 0;
d1 = poisson(curr_script->prop_delay, curr_script->jitter);
d2 = poisson(curr_script->proc_delay, 0);
d3 = poisson(curr_script->prop_delay, curr_script->jitter);
LFPTOD(&rpkt->xmt, t1);
t2 = server->server_time + d1;
t3 = server->server_time + d1 + d2;
t4 = t1 + d1 + d2 + d3;
xpkt.org = rpkt->xmt;
DTOLFP(t2, &xpkt.rec);
DTOLFP(t3, &xpkt.xmt);
xpkt.reftime = xpkt.xmt;
rbuf.receiver = receive;
rbuf.recv_length = LEN_PKT_NOMAC;
rbuf.recv_pkt = xpkt;
rbuf.used = 1;
memcpy(&rbuf.srcadr, serv_addr, sizeof(rbuf.srcadr));
memcpy(&rbuf.recv_srcadr, serv_addr, sizeof(rbuf.recv_srcadr));
if ((rbuf.dstadr = malloc(sizeof(*rbuf.dstadr))) == NULL)
abortsim("malloc failed in simulate_server");
memcpy(rbuf.dstadr, inter, sizeof(*rbuf.dstadr));
e = event(t4, PACKET);
e->rcv_buf = rbuf;
enqueue(event_queue, e);
if (curr_script->duration > simulation.sim_time &&
!empty(server->script)) {
printf("Hello\n");
curr_script = dequeue(server->script);
}
return (0);
}
void sim_update_clocks (Event *e)
{
double time_gap;
double adj;
int i;
time_gap = e->time - simulation.sim_time;
simclock.local_time = e->time + time_gap;
simulation.sim_time = e->time;
for (i = 0;i < simulation.num_of_servers; ++i) {
simulation.servers[i].curr_script->freq_offset +=
gauss(0, time_gap * simulation.servers[i].curr_script->wander);
simulation.servers[i].server_time += time_gap *
(1 + simulation.servers[i].curr_script->freq_offset);
}
adj = time_gap * simclock.slew;
if (adj < fabs(simclock.adj)) {
if (simclock.adj < 0) {
simclock.adj += adj;
simclock.local_time -= adj;
}
else {
simclock.adj -= adj;
simclock.local_time += adj;
}
}
else {
simclock.local_time += simclock.adj;
simclock.adj = 0;
}
}
void sim_event_recv_packet(Event *e)
{
struct recvbuf *rbuf;
if ((rbuf = get_node(sizeof(*rbuf))) == NULL)
abortsim("get_node failed in sim_event_recv_packet");
memcpy(rbuf, &e->rcv_buf, sizeof(*rbuf));
DTOLFP(simclock.local_time, &rbuf->recv_time);
enqueue(recv_queue, rbuf);
}
void sim_event_beep(Event *e)
{
#if 0
static int first_time = 1;
char *dash = "-----------------";
#endif
fprintf(stderr, "BEEP!!!\n");
enqueue(event_queue, event(e->time + simulation.beep_delay, BEEP));
#if 0
if(simulation.beep_delay > 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;
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",
simclock.local_time,
n->time, n->clk_time, n->ntp_time);
#endif
}
void abortsim(char *errmsg)
{
perror(errmsg);
exit(1);
}
void
get_systime(
l_fp *now )
{
if (simclock.local_time == simclock.last_read_time)
simclock.local_time += 200e-9;
simclock.last_read_time = simclock.local_time;
DTOLFP(simclock.local_time, now);
}
int
adj_systime(
double now
)
{
struct timeval adjtv;
double dtemp;
long ticks;
int isneg = 0;
dtemp = now + sys_residual;
if (dtemp < 0) {
isneg = 1;
dtemp = -dtemp;
}
adjtv.tv_sec = (long)dtemp;
dtemp -= adjtv.tv_sec;
ticks = (long)(dtemp / sys_tick + .5);
adjtv.tv_usec = (long)(ticks * sys_tick * 1e6);
dtemp -= adjtv.tv_usec / 1e6;
sys_residual = dtemp;
if (isneg) {
adjtv.tv_sec = -adjtv.tv_sec;
adjtv.tv_usec = -adjtv.tv_usec;
sys_residual = -sys_residual;
}
simclock.adj = now;
return (1);
}
int
step_systime(
double now
)
{
#ifdef DEBUG
if (debug)
printf("step_systime: time %.6f adj %.6f\n",
simclock.local_time, now);
#endif
simclock.local_time += now;
return (1);
}
double
gauss(
double m,
double s
)
{
double q1, q2;
if (s == 0)
return (m);
while ((q1 = drand48()) == 0);
q2 = drand48();
return (m + s * sqrt(-2. * log(q1)) * cos(2. * PI * q2));
}
double
poisson(
double m,
double s
)
{
double q1;
if (s == 0)
return (m);
while ((q1 = drand48()) == 0);
return (m - s * log(q1 * s));
}
#endif