int determine_recv_buf_ordering(struct recvbuf *b1, struct recvbuf *b2) { double recv_time1, recv_time2; /* Simply convert the time received to double and subtract */ LFPTOD(&b1->recv_time, recv_time1); LFPTOD(&b2->recv_time, recv_time2); return ((int)(recv_time1 - recv_time2)); }
double l_fp_convert_to_double(const l_fp first) { double res; LFPTOD(&first, res); return res; }
/* * refclock_process_offset - update median filter * * This routine uses the given offset and timestamps to construct a new * entry in the median filter circular buffer. Samples that overflow the * filter are quietly discarded. */ void refclock_process_offset( struct refclockproc *pp, l_fp offset, l_fp lastrec, double fudge ) { double doffset; pp->lastref = offset; pp->lastrec = lastrec; L_SUB(&offset, &lastrec); LFPTOD(&offset, doffset); SAMPLE(doffset + fudge); }
/* * refclock_process_offset - update median filter * * This routine uses the given offset and timestamps to construct a new * entry in the median filter circular buffer. Samples that overflow the * filter are quietly discarded. */ void refclock_process_offset( struct refclockproc *pp, /* refclock structure pointer */ l_fp lasttim, /* last timecode timestamp */ l_fp lastrec, /* last receive timestamp */ double fudge ) { l_fp lftemp; double doffset; pp->lastrec = lastrec; lftemp = lasttim; L_SUB(&lftemp, &lastrec); LFPTOD(&lftemp, doffset); SAMPLE(doffset + fudge); }
/* Define a function to simulate a server. * This function processes the sent packet according to the server script, * creates a reply packet and pushes the reply packet onto the event queue */ int simulate_server( sockaddr_u *serv_addr, /* Address of the server */ struct interface *inter, /* Interface on which the reply should be inserted */ struct pkt *rpkt /* Packet sent to the server that needs to be processed. */ ) { struct pkt xpkt; /* Packet to be transmitted back to the client */ struct recvbuf rbuf; /* Buffer for the received packet */ Event *e; /* Packet receive event */ server_info *server; /* Pointer to the server being simulated */ script_info *curr_script; /* Current script being processed */ int i; double d1, d2, d3; /* Delays while the packet is enroute */ double t1, t2, t3, t4; /* The four timestamps in the packet */ memset(&xpkt, 0, sizeof(xpkt)); memset(&rbuf, 0, sizeof(rbuf)); /* Search for the server with the desired address */ 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!!!"); /* Get the current script for the server */ curr_script = server->curr_script; /* Create a server reply packet. * Masquerade the reply as a stratum-1 server with a GPS clock */ 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; /* TIMESTAMP CALCULATIONS t1 t4 \ / d1 \ / d3 \ / t2 ----------------- t3 d2 */ /* Compute the delays */ 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); /* Note: In the transmitted packet: * 1. t1 and t4 are times in the client according to the local clock. * 2. t2 and t3 are server times according to the simulated server. * Compute t1, t2, t3 and t4 * Note: This function is called at time t1. */ LFPTOD(&rpkt->xmt, t1); t2 = server->server_time + d1; t3 = server->server_time + d1 + d2; t4 = t1 + d1 + d2 + d3; /* Save the timestamps */ xpkt.org = rpkt->xmt; DTOLFP(t2, &xpkt.rec); DTOLFP(t3, &xpkt.xmt); xpkt.reftime = xpkt.xmt; /* Ok, we are done with the packet. Now initialize the receive buffer for * the packet. */ rbuf.receiver = receive; /* Function to call to process the packet */ 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)); /* rbuf.link = NULL; */ /* Create a packet event and insert it onto the event_queue at the * arrival time (t4) of the packet at the client */ e = event(t4, PACKET); e->rcv_buf = rbuf; enqueue(event_queue, e); /* Check if the time of the script has expired. If yes, delete the script. * If not, re-enqueue the script onto the server script queue */ if (curr_script->duration > simulation.sim_time && !empty(server->script)) { printf("Hello\n"); /* * For some reason freeing up the curr_script memory kills the * simulation. Further debugging is needed to determine why. * free_node(curr_script); */ curr_script = dequeue(server->script); } return (0); }
void offset_calculation ( struct pkt *rpkt, int rpktl, struct timeval *tv_dst, double *offset, double *precision, double *root_dispersion ) { l_fp p_rec, p_xmt, p_ref, p_org, tmp, dst; u_fp p_rdly, p_rdsp; double t21, t34, delta; /* Convert timestamps from network to host byte order */ p_rdly = NTOHS_FP(rpkt->rootdelay); p_rdsp = NTOHS_FP(rpkt->rootdisp); NTOHL_FP(&rpkt->reftime, &p_ref); NTOHL_FP(&rpkt->org, &p_org); NTOHL_FP(&rpkt->rec, &p_rec); NTOHL_FP(&rpkt->xmt, &p_xmt); *precision = LOGTOD(rpkt->precision); #ifdef DEBUG printf("sntp precision: %f\n", *precision); #endif /* DEBUG */ *root_dispersion = FPTOD(p_rdsp); #ifdef DEBUG printf("sntp rootdelay: %f\n", FPTOD(p_rdly)); printf("sntp rootdisp: %f\n", *root_dispersion); pkt_output(rpkt, rpktl, stdout); printf("sntp offset_calculation: rpkt->reftime:\n"); l_fp_output(&(rpkt->reftime), stdout); printf("sntp offset_calculation: rpkt->org:\n"); l_fp_output(&(rpkt->org), stdout); printf("sntp offset_calculation: rpkt->rec:\n"); l_fp_output(&(rpkt->rec), stdout); printf("sntp offset_calculation: rpkt->rec:\n"); l_fp_output_bin(&(rpkt->rec), stdout); printf("sntp offset_calculation: rpkt->rec:\n"); l_fp_output_dec(&(rpkt->rec), stdout); printf("sntp offset_calculation: rpkt->xmt:\n"); l_fp_output(&(rpkt->xmt), stdout); #endif /* Compute offset etc. */ tmp = p_rec; L_SUB(&tmp, &p_org); LFPTOD(&tmp, t21); TVTOTS(tv_dst, &dst); dst.l_ui += JAN_1970; tmp = p_xmt; L_SUB(&tmp, &dst); LFPTOD(&tmp, t34); *offset = (t21 + t34) / 2.; delta = t21 - t34; if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp offset_calculation:\tt21: %.6f\t\t t34: %.6f\n\t\tdelta: %.6f\t offset: %.6f\n", t21, t34, delta, *offset); }
void offset_calculation( struct pkt *rpkt, int rpktl, struct timeval *tv_dst, double *offset, double *precision, double *synch_distance ) { l_fp p_rec, p_xmt, p_ref, p_org, tmp, dst; u_fp p_rdly, p_rdsp; double t21, t34, delta; /* Convert timestamps from network to host byte order */ p_rdly = NTOHS_FP(rpkt->rootdelay); p_rdsp = NTOHS_FP(rpkt->rootdisp); NTOHL_FP(&rpkt->reftime, &p_ref); NTOHL_FP(&rpkt->org, &p_org); NTOHL_FP(&rpkt->rec, &p_rec); NTOHL_FP(&rpkt->xmt, &p_xmt); *precision = LOGTOD(rpkt->precision); TRACE(3, ("offset_calculation: LOGTOD(rpkt->precision): %f\n", *precision)); /* Compute offset etc. */ tmp = p_rec; L_SUB(&tmp, &p_org); LFPTOD(&tmp, t21); TVTOTS(tv_dst, &dst); dst.l_ui += JAN_1970; tmp = p_xmt; L_SUB(&tmp, &dst); LFPTOD(&tmp, t34); *offset = (t21 + t34) / 2.; delta = t21 - t34; // synch_distance is: // (peer->delay + peer->rootdelay) / 2 + peer->disp // + peer->rootdisp + clock_phi * (current_time - peer->update) // + peer->jitter; // // and peer->delay = fabs(peer->offset - p_offset) * 2; // and peer->offset needs history, so we're left with // p_offset = (t21 + t34) / 2.; // peer->disp = 0; (we have no history to augment this) // clock_phi = 15e-6; // peer->jitter = LOGTOD(sys_precision); (we have no history to augment this) // and ntp_proto.c:set_sys_tick_precision() should get us sys_precision. // // so our answer seems to be: // // (fabs(t21 + t34) + peer->rootdelay) / 3. // + 0 (peer->disp) // + peer->rootdisp // + 15e-6 (clock_phi) // + LOGTOD(sys_precision) INSIST( FPTOD(p_rdly) >= 0. ); #if 1 *synch_distance = (fabs(t21 + t34) + FPTOD(p_rdly)) / 3. + 0. + FPTOD(p_rdsp) + 15e-6 + 0. /* LOGTOD(sys_precision) when we can get it */ ; INSIST( *synch_distance >= 0. ); #else *synch_distance = (FPTOD(p_rdly) + FPTOD(p_rdsp))/2.0; #endif #ifdef DEBUG if (debug > 3) { printf("sntp rootdelay: %f\n", FPTOD(p_rdly)); printf("sntp rootdisp: %f\n", FPTOD(p_rdsp)); printf("sntp syncdist: %f\n", *synch_distance); pkt_output(rpkt, rpktl, stdout); printf("sntp offset_calculation: rpkt->reftime:\n"); l_fp_output(&p_ref, stdout); printf("sntp offset_calculation: rpkt->org:\n"); l_fp_output(&p_org, stdout); printf("sntp offset_calculation: rpkt->rec:\n"); l_fp_output(&p_rec, stdout); printf("sntp offset_calculation: rpkt->xmt:\n"); l_fp_output(&p_xmt, stdout); } #endif TRACE(3, ("sntp offset_calculation:\trec - org t21: %.6f\n" "\txmt - dst t34: %.6f\tdelta: %.6f\toffset: %.6f\n", t21, t34, delta, *offset)); return; }
/* * get_systime - return system time in NTP timestamp format. */ void get_systime( l_fp *now /* system time */ ) { static struct timespec ts_prev; /* prior os time */ static l_fp lfp_prev; /* prior result */ static double dfuzz_prev; /* prior fuzz */ struct timespec ts; /* seconds and nanoseconds */ struct timespec ts_min; /* earliest permissible */ struct timespec ts_lam; /* lamport fictional increment */ struct timespec ts_prev_log; /* for msyslog only */ double dfuzz; double ddelta; l_fp result; l_fp lfpfuzz; l_fp lfpdelta; get_ostime(&ts); DEBUG_REQUIRE(systime_init_done); ENTER_GET_SYSTIME_CRITSEC(); /* * After default_get_precision() has set a nonzero sys_fuzz, * ensure every reading of the OS clock advances by at least * sys_fuzz over the prior reading, thereby assuring each * fuzzed result is strictly later than the prior. Limit the * necessary fiction to 1 second. */ if (!USING_SIGIO()) { ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec); if (cmp_tspec(ts, ts_min) < 0) { ts_lam = sub_tspec(ts_min, ts); if (ts_lam.tv_sec > 0 && !lamport_violated) { msyslog(LOG_ERR, "get_systime Lamport advance exceeds one second (%.9f)", ts_lam.tv_sec + 1e-9 * ts_lam.tv_nsec); exit(1); } if (!lamport_violated) ts = ts_min; } ts_prev_log = ts_prev; ts_prev = ts; } else { /* * Quiet "ts_prev_log.tv_sec may be used uninitialized" * warning from x86 gcc 4.5.2. */ ZERO(ts_prev_log); } /* convert from timespec to l_fp fixed-point */ result = tspec_stamp_to_lfp(ts); /* * Add in the fuzz. */ dfuzz = ntp_random() * 2. / FRAC * sys_fuzz; DTOLFP(dfuzz, &lfpfuzz); L_ADD(&result, &lfpfuzz); /* * Ensure result is strictly greater than prior result (ignoring * sys_residual's effect for now) once sys_fuzz has been * determined. */ if (!USING_SIGIO()) { if (!L_ISZERO(&lfp_prev) && !lamport_violated) { if (!L_ISGTU(&result, &lfp_prev) && sys_fuzz > 0.) { msyslog(LOG_ERR, "ts_prev %s ts_min %s", tspectoa(ts_prev_log), tspectoa(ts_min)); msyslog(LOG_ERR, "ts %s", tspectoa(ts)); msyslog(LOG_ERR, "sys_fuzz %ld nsec, prior fuzz %.9f", sys_fuzz_nsec, dfuzz_prev); msyslog(LOG_ERR, "this fuzz %.9f", dfuzz); lfpdelta = lfp_prev; L_SUB(&lfpdelta, &result); LFPTOD(&lfpdelta, ddelta); msyslog(LOG_ERR, "prev get_systime 0x%x.%08x is %.9f later than 0x%x.%08x", lfp_prev.l_ui, lfp_prev.l_uf, ddelta, result.l_ui, result.l_uf); } } lfp_prev = result; dfuzz_prev = dfuzz; if (lamport_violated) lamport_violated = FALSE; } LEAVE_GET_SYSTIME_CRITSEC(); *now = result; }
/* * vme_control - set fudge factors, return statistics2 */ static void vme_control( u_int unit, struct refclockstat *in, struct refclockstat *out, struct peer * peer ) { register struct vmeunit *vme; if (unit >= MAXUNITS) { msyslog(LOG_ERR, "vme_control: unit %d invalid)", unit); return; } if (in != 0) { if (in->haveflags & CLK_HAVETIME1) DTOLFP(in->fudgetime1, &fudgefactor[unit]); /* added mjb lmco 12/20/99 */ if (in->haveflags & CLK_HAVEVAL1) { stratumtouse[unit] = (u_char)(in->fudgeval1 & 0xf); if (unitinuse[unit]) { struct peer *peer; /* * Should actually reselect clock, but * will wait for the next timecode */ vme = vmeunits[unit]; peer = vme->peer; peer->stratum = stratumtouse[unit]; if (stratumtouse[unit] <= 1) memcpy( (char *)&peer->refid, USNOREFID,4); else peer->refid = htonl(VMEHSREFID); } } if (in->haveflags & CLK_HAVEFLAG1) { sloppyclockflag[unit] = in->flags & CLK_FLAG1; } } if (out != 0) { out->type = 16; /*set by RES SHOULD BE CHANGED */ out->haveflags = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1; out->clockdesc = VMEDESCRIPTION; LFPTOD(&fudgefactor[unit], out->fudgetime1); /* added mjb lmco 12/20/99 */ out ->fudgetime2 = 0; /* should do what above was supposed to do mjb lmco 12/20/99 */ out->fudgeval1 = (long)stratumtouse[unit]; /*changed from above LONG was not defined mjb lmco 12/15/99 */ out->fudgeval2 = 0; out->flags = sloppyclockflag[unit]; if (unitinuse[unit]) { vme = vmeunits[unit]; out->lencode = vme->lencode; out->p_lastcode = vme->lastcode; out->timereset = current_time - vme->timestarted; out->polls = vme->polls; out->noresponse = vme->noreply; out->badformat = vme->badformat; out->baddata = vme->baddata; out->lastevent = vme->lastevent; out->currentstatus = vme->status; } else { out->lencode = 0; out->p_lastcode = ""; out->polls = out->noresponse = 0; out->badformat = out->baddata = 0; out->timereset = 0; out->currentstatus = out->lastevent = CEVNT_NOMINAL; } } }
void jitter(const iomode mode) { l_fp tr; int i; double gtod[NBUF]; /* * Force pages into memory */ for (i = 0; i < NBUF; i ++) gtod[i] = 0; /* * Construct gtod array */ for (i = 0; i < NBUF; i ++) { get_clocktime(&tr); LFPTOD(&tr, gtod[i]); } /* * Write out gtod array for later processing with Matlab */ average = 0; for (i = 0; i < NBUF - 2; i++) { gtod[i] = gtod[i + 1] - gtod[i]; if (mode == raw) printf("%13.9f\n", gtod[i]); average += gtod[i]; } if (mode == raw) exit(0); /* * Sort the gtod array and display deciles */ qsort(gtod, NBUF, sizeof(gtod[0]), doublecmp); average = average / (NBUF - 2); if (mode == json) { fprintf(stdout, "{\"Average\":%13.9f,", average); fprintf(stdout, "\"First rank\":["); for (i = 0; i < NSAMPLES; i++) { fprintf(stdout, "%13.9f", gtod[i]); if (i < NSAMPLES - 1) fputc(',', stdout); fputs("],", stdout); } fprintf(stdout, "\"Last rank\":"); for (i = NBUF - 12; i < NBUF - 2; i++) { fprintf(stdout, "%13.9f\n", gtod[i]); if (i < NSAMPLES - 1) fputc(',', stdout); fputs("]}\n", stdout); } } else if (mode != raw) { fprintf(stdout, "Average %13.9f\n", average); fprintf(stdout, "First rank\n"); for (i = 0; i < NSAMPLES; i++) fprintf(stdout, "%2d %13.9f\n", i, gtod[i]); fprintf(stdout, "Last rank\n"); for (i = NBUF - 12; i < NBUF - 2; i++) fprintf(stdout, "%2d %13.9f\n", i, gtod[i]); } exit(0); }
LFP::operator double() const { double res; LFPTOD(&_v, res); return res; }