static void gpsd_control( int unit, const struct refclockstat * in_st, struct refclockstat * out_st, peerT * peer ) { clockprocT * const pp = peer->procptr; gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; /* save preprocessed fudge times */ DTOLFP(pp->fudgetime1, &up->pps_fudge); DTOLFP(pp->fudgetime2, &up->tpv_fudge); }
/* * refclock_process - process a sample from the clock * refclock_process_f - refclock_process with other than time1 fudge * * This routine converts the timecode in the form days, hours, minutes, * seconds and milliseconds/microseconds to internal timestamp format, * then constructs a new entry in the median filter circular buffer. * Return success (1) if the data are correct and consistent with the * converntional calendar. * * Important for PPS users: Normally, the pp->lastrec is set to the * system time when the on-time character is received and the pp->year, * ..., pp->second decoded and the seconds fraction pp->nsec in * nanoseconds). When a PPS offset is available, pp->nsec is forced to * zero and the fraction for pp->lastrec is set to the PPS offset. */ int refclock_process_f( struct refclockproc *pp, /* refclock structure pointer */ double fudge ) { l_fp offset, ltemp; /* * Compute the timecode timestamp from the days, hours, minutes, * seconds and milliseconds/microseconds of the timecode. Use * clocktime() for the aggregate seconds and the msec/usec for * the fraction, when present. Note that this code relies on the * filesystem time for the years and does not use the years of * the timecode. */ if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT, pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) return (0); offset.l_uf = 0; DTOLFP(pp->nsec / 1e9, <emp); L_ADD(&offset, <emp); refclock_process_offset(pp, offset, pp->lastrec, fudge); return (1); }
l_fp l_fp_init_from_double( double rhs) { l_fp temp; DTOLFP(rhs, &temp); return temp; }
/* * refclock_buginfo - return debugging info * * This routine is used mainly for debugging. It returns designated * values from the interface structure that can be displayed using * ntpdc and the clkbug command. */ void refclock_buginfo( struct sockaddr_storage *srcadr, /* clock address */ struct refclockbug *bug /* output structure */ ) { struct peer *peer; struct refclockproc *pp; u_char clktype; int unit; int i; /* * Check for valid address and peer structure */ if (srcadr->ss_family != AF_INET) return; if (!ISREFCLOCKADR(srcadr)) return; clktype = (u_char) REFCLOCKTYPE(srcadr); unit = REFCLOCKUNIT(srcadr); if (clktype >= num_refclock_conf || unit >= MAXUNIT) return; peer = typeunit[clktype][unit]; if (peer == NULL) return; pp = peer->procptr; /* * Copy structure values */ bug->nvalues = 8; bug->svalues = 0x0000003f; bug->values[0] = pp->year; bug->values[1] = pp->day; bug->values[2] = pp->hour; bug->values[3] = pp->minute; bug->values[4] = pp->second; bug->values[5] = pp->nsec; bug->values[6] = pp->yearstart; bug->values[7] = pp->coderecv; bug->stimes = 0xfffffffc; bug->times[0] = pp->lastref; bug->times[1] = pp->lastrec; for (i = 2; i < (int)bug->ntimes; i++) DTOLFP(pp->filter[i - 2], &bug->times[i]); /* * Give the stuff to the clock */ if (refclock_conf[clktype]->clock_buginfo != noentry) (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer); }
/* * refclock_buginfo - return debugging info * * This routine is used mainly for debugging. It returns designated * values from the interface structure that can be displayed using * ntpdc and the clkbug command. */ void refclock_buginfo( sockaddr_u *srcadr, /* clock address */ struct refclockbug *bug /* output structure */ ) { struct peer *peer; struct refclockproc *pp; int clktype; int unit; unsigned u; /* * Check for valid address and peer structure */ if (!ISREFCLOCKADR(srcadr)) return; clktype = (u_char) REFCLOCKTYPE(srcadr); unit = REFCLOCKUNIT(srcadr); peer = findexistingpeer(srcadr, NULL, -1); if (NULL == peer || NULL == peer->procptr) return; pp = peer->procptr; /* * Copy structure values */ bug->nvalues = 8; bug->svalues = 0x0000003f; bug->values[0] = pp->year; bug->values[1] = pp->day; bug->values[2] = pp->hour; bug->values[3] = pp->minute; bug->values[4] = pp->second; bug->values[5] = pp->nsec; bug->values[6] = pp->yearstart; bug->values[7] = pp->coderecv; bug->stimes = 0xfffffffc; bug->times[0] = pp->lastref; bug->times[1] = pp->lastrec; for (u = 2; u < bug->ntimes; u++) DTOLFP(pp->filter[u - 2], &bug->times[u]); /* * Give the stuff to the clock */ if (refclock_conf[clktype]->clock_buginfo != noentry) (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer); }
void sim_event_recv_packet(Event *e) { struct recvbuf *rbuf; /* Allocate a receive buffer and copy the packet to it */ if ((rbuf = get_node(sizeof(*rbuf))) == NULL) abortsim("get_node failed in sim_event_recv_packet"); memcpy(rbuf, &e->rcv_buf, sizeof(*rbuf)); /* Store the local time in the received packet */ DTOLFP(simclock.local_time, &rbuf->recv_time); /* Insert the packet received onto the receive queue */ enqueue(recv_queue, rbuf); }
/* * get_systime - return the system time in NTP timestamp format */ void get_systime( l_fp *now /* current system time in l_fp */ ) { /* * To fool the code that determines the local clock precision, * we advance the clock a minimum of 200 nanoseconds on every * clock read. This is appropriate for a typical modern machine * with nanosecond clocks. Note we make no attempt here to * simulate reading error, since the error is so small. This may * change when the need comes to implement picosecond clocks. */ 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); /* OLD Code if (ntp_node.ntp_time == ntp_node.last_time) ntp_node.ntp_time += 200e-9; ntp_node.last_time = ntp_node.ntp_time; DTOLFP(ntp_node.ntp_time, now); */ }
int step_systime( double step ) { time_t pivot; /* for ntp era unfolding */ struct timeval timetv, tvlast, tvdiff; struct timespec timets; struct calendar jd; l_fp fp_ofs, fp_sys; /* offset and target system time in FP */ /* * Get pivot time for NTP era unfolding. Since we don't step * very often, we can afford to do the whole calculation from * scratch. And we're not in the time-critical path yet. */ #if SIZEOF_TIME_T > 4 /* * This code makes sure the resulting time stamp for the new * system time is in the 2^32 seconds starting at 1970-01-01, * 00:00:00 UTC. */ pivot = 0x80000000; #if USE_COMPILETIME_PIVOT /* * Add the compile time minus 10 years to get a possible target * area of (compile time - 10 years) to (compile time + 126 * years). This should be sufficient for a given binary of * NTPD. */ if (ntpcal_get_build_date(&jd)) { jd.year -= 10; pivot += ntpcal_date_to_time(&jd); } else { msyslog(LOG_ERR, "step-systime: assume 1970-01-01 as build date"); } #else UNUSED_LOCAL(jd); #endif /* USE_COMPILETIME_PIVOT */ #else UNUSED_LOCAL(jd); /* This makes sure the resulting time stamp is on or after * 1969-12-31/23:59:59 UTC and gives us additional two years, * from the change of NTP era in 2036 to the UNIX rollover in * 2038. (Minus one second, but that won't hurt.) We *really* * need a longer 'time_t' after that! Or a different baseline, * but that would cause other serious trouble, too. */ pivot = 0x7FFFFFFF; #endif /* get the complete jump distance as l_fp */ DTOLFP(sys_residual, &fp_sys); DTOLFP(step, &fp_ofs); L_ADD(&fp_ofs, &fp_sys); /* ---> time-critical path starts ---> */ /* get the current time as l_fp (without fuzz) and as struct timeval */ get_ostime(&timets); fp_sys = tspec_stamp_to_lfp(timets); tvlast.tv_sec = timets.tv_sec; tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; /* get the target time as l_fp */ L_ADD(&fp_sys, &fp_ofs); /* unfold the new system time */ timetv = lfp_stamp_to_tval(fp_sys, &pivot); /* now set new system time */ if (ntp_set_tod(&timetv, NULL) != 0) { msyslog(LOG_ERR, "step-systime: %m"); return FALSE; } /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ sys_residual = 0; lamport_violated = (step < 0); if (step_callback) (*step_callback)(); #ifdef NEED_HPUX_ADJTIME /* * CHECKME: is this correct when called by ntpdate????? */ _clear_adjtime(); #endif /* * FreeBSD, for example, has: * struct utmp { * char ut_line[UT_LINESIZE]; * char ut_name[UT_NAMESIZE]; * char ut_host[UT_HOSTSIZE]; * long ut_time; * }; * and appends line="|", name="date", host="", time for the OLD * and appends line="{", name="date", host="", time for the NEW * to _PATH_WTMP . * * Some OSes have utmp, some have utmpx. */ /* * Write old and new time entries in utmp and wtmp if step * adjustment is greater than one second. * * This might become even Uglier... */ tvdiff = abs_tval(sub_tval(timetv, tvlast)); if (tvdiff.tv_sec > 0) { #ifdef HAVE_UTMP_H struct utmp ut; #endif #ifdef HAVE_UTMPX_H struct utmpx utx; #endif #ifdef HAVE_UTMP_H ZERO(ut); #endif #ifdef HAVE_UTMPX_H ZERO(utx); #endif /* UTMP */ #ifdef UPDATE_UTMP # ifdef HAVE_PUTUTLINE # ifndef _PATH_UTMP # define _PATH_UTMP UTMP_FILE # endif utmpname(_PATH_UTMP); ut.ut_type = OLD_TIME; strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); ut.ut_time = tvlast.tv_sec; setutent(); pututline(&ut); ut.ut_type = NEW_TIME; strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); ut.ut_time = timetv.tv_sec; setutent(); pututline(&ut); endutent(); # else /* not HAVE_PUTUTLINE */ # endif /* not HAVE_PUTUTLINE */ #endif /* UPDATE_UTMP */ /* UTMPX */ #ifdef UPDATE_UTMPX # ifdef HAVE_PUTUTXLINE utx.ut_type = OLD_TIME; strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); utx.ut_tv = tvlast; setutxent(); pututxline(&utx); utx.ut_type = NEW_TIME; strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); utx.ut_tv = timetv; setutxent(); pututxline(&utx); endutxent(); # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ #endif /* UPDATE_UTMPX */ /* WTMP */ #ifdef UPDATE_WTMP # ifdef HAVE_PUTUTLINE # ifndef _PATH_WTMP # define _PATH_WTMP WTMP_FILE # endif utmpname(_PATH_WTMP); ut.ut_type = OLD_TIME; strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); ut.ut_time = tvlast.tv_sec; setutent(); pututline(&ut); ut.ut_type = NEW_TIME; strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); ut.ut_time = timetv.tv_sec; setutent(); pututline(&ut); endutent(); # else /* not HAVE_PUTUTLINE */ # endif /* not HAVE_PUTUTLINE */ #endif /* UPDATE_WTMP */ /* WTMPX */ #ifdef UPDATE_WTMPX # ifdef HAVE_PUTUTXLINE utx.ut_type = OLD_TIME; utx.ut_tv = tvlast; strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); # ifdef HAVE_UPDWTMPX updwtmpx(WTMPX_FILE, &utx); # else /* not HAVE_UPDWTMPX */ # endif /* not HAVE_UPDWTMPX */ # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ # ifdef HAVE_PUTUTXLINE utx.ut_type = NEW_TIME; utx.ut_tv = timetv; strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); # ifdef HAVE_UPDWTMPX updwtmpx(WTMPX_FILE, &utx); # else /* not HAVE_UPDWTMPX */ # endif /* not HAVE_UPDWTMPX */ # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ #endif /* UPDATE_WTMPX */ } return TRUE; }
/* * chu_audio_receive - receive data from the audio device */ static void chu_audio_receive( struct recvbuf *rbufp /* receive buffer structure pointer */ ) { struct chuunit *up; struct refclockproc *pp; struct peer *peer; double sample; /* codec sample */ u_char *dpt; /* buffer pointer */ int bufcnt; /* buffer counter */ l_fp ltemp; /* l_fp temp */ peer = rbufp->recv_peer; pp = peer->procptr; up = pp->unitptr; /* * Main loop - read until there ain't no more. Note codec * samples are bit-inverted. */ DTOLFP((double)rbufp->recv_length / SECOND, <emp); L_SUB(&rbufp->recv_time, <emp); up->timestamp = rbufp->recv_time; dpt = rbufp->recv_buffer; for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) { sample = up->comp[~*dpt++ & 0xff]; /* * Clip noise spikes greater than MAXAMP. If no clips, * increase the gain a tad; if the clips are too high, * decrease a tad. */ if (sample > MAXAMP) { sample = MAXAMP; up->clipcnt++; } else if (sample < -MAXAMP) { sample = -MAXAMP; up->clipcnt++; } chu_rf(peer, sample); L_ADD(&up->timestamp, &up->tick); /* * Once each second ride gain. */ up->seccnt = (up->seccnt + 1) % SECOND; if (up->seccnt == 0) { chu_gain(peer); } } /* * Set the input port and monitor gain for the next buffer. */ if (pp->sloppyclockflag & CLK_FLAG2) up->port = 2; else up->port = 1; if (pp->sloppyclockflag & CLK_FLAG3) up->mongain = MONGAIN; else up->mongain = 0; }
/* * chu_start - open the devices and initialize data for processing */ static int chu_start( int unit, /* instance number (not used) */ struct peer *peer /* peer structure pointer */ ) { struct chuunit *up; struct refclockproc *pp; char device[20]; /* device name */ int fd; /* file descriptor */ #ifdef ICOM int temp; #endif /* ICOM */ #ifdef HAVE_AUDIO int fd_audio; /* audio port file descriptor */ int i; /* index */ double step; /* codec adjustment */ /* * Open audio device. Don't complain if not there. */ fd_audio = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit); #ifdef DEBUG if (fd_audio >= 0 && debug) audio_show(); #endif /* * If audio is unavailable, Open serial port in raw mode. */ if (fd_audio >= 0) { fd = fd_audio; } else { snprintf(device, sizeof(device), DEVICE, unit); fd = refclock_open(device, SPEED232, LDISC_RAW); } #else /* HAVE_AUDIO */ /* * Open serial port in raw mode. */ snprintf(device, sizeof(device), DEVICE, unit); fd = refclock_open(device, SPEED232, LDISC_RAW); #endif /* HAVE_AUDIO */ if (fd < 0) return (0); /* * Allocate and initialize unit structure */ up = emalloc_zero(sizeof(*up)); pp = peer->procptr; pp->unitptr = up; pp->io.clock_recv = chu_receive; pp->io.srcclock = peer; pp->io.datalen = 0; pp->io.fd = fd; if (!io_addclock(&pp->io)) { close(fd); pp->io.fd = -1; free(up); pp->unitptr = NULL; return (0); } /* * Initialize miscellaneous variables */ peer->precision = PRECISION; pp->clockdesc = DESCRIPTION; strlcpy(up->ident, "CHU", sizeof(up->ident)); memcpy(&pp->refid, up->ident, 4); DTOLFP(CHAR, &up->charstamp); #ifdef HAVE_AUDIO /* * The companded samples are encoded sign-magnitude. The table * contains all the 256 values in the interest of speed. We do * this even if the audio codec is not available. C'est la lazy. */ up->fd_audio = fd_audio; up->gain = 127; up->comp[0] = up->comp[OFFSET] = 0.; up->comp[1] = 1; up->comp[OFFSET + 1] = -1.; up->comp[2] = 3; up->comp[OFFSET + 2] = -3.; step = 2.; for (i = 3; i < OFFSET; i++) { up->comp[i] = up->comp[i - 1] + step; up->comp[OFFSET + i] = -up->comp[i]; if (i % 16 == 0) step *= 2.; } DTOLFP(1. / SECOND, &up->tick); #endif /* HAVE_AUDIO */ #ifdef ICOM temp = 0; #ifdef DEBUG if (debug > 1) temp = P_TRACE; #endif if (peer->ttl > 0) { if (peer->ttl & 0x80) up->fd_icom = icom_init("/dev/icom", B1200, temp); else up->fd_icom = icom_init("/dev/icom", B9600, temp); } if (up->fd_icom > 0) { if (chu_newchan(peer, 0) != 0) { msyslog(LOG_NOTICE, "icom: radio not found"); close(up->fd_icom); up->fd_icom = 0; } else { msyslog(LOG_NOTICE, "icom: autotune enabled"); } } #endif /* ICOM */ return (1); }
/* 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); }
/****************************************************************************** * * Function: tsync_poll() * Description: Retrieve time from the TSYNC device. * * Parameters: * IN: unit - not used. * *peer - pointer to this reference clock's peer structure * Returns: none. * *******************************************************************************/ static void tsync_poll(int unit, struct peer *peer) { char device[32]; struct refclockproc *pp; struct calendar jt; TsyncUnit *up; unsigned char synch; double seconds; int err; int err1; int err2; int err3; int i; int j; unsigned int itAllocationLength; unsigned int itAllocationLength1; unsigned int itAllocationLength2; NtpTimeObj TimeContext; BoardObj hBoard; char timeRef[TSYNC_REF_LEN + 1]; char ppsRef [TSYNC_REF_LEN + 1]; TIME_SCALE tmscl = TIME_SCALE_UTC; LeapSecondObj leapSec; ioctl_trans_di *it; ioctl_trans_di *it1; ioctl_trans_di *it2; l_fp offset; l_fp ltemp; ReferenceObj * pRefObj; /* Construct the device name */ sprintf(device, "%s%d", DEVICE, (int)peer->refclkunit); printf("Polling device number %d...\n", (int)peer->refclkunit); /* Open the TSYNC device */ hBoard.file_descriptor = open(device, O_RDONLY | O_NDELAY, 0777); /* If error opening TSYNC device... */ if (hBoard.file_descriptor < 0) { msyslog(LOG_ERR, "Couldn't open device"); return; } /* If error while initializing the board... */ if (ioctl(hBoard.file_descriptor, IOCTL_TPRO_OPEN, &hBoard) < 0) { msyslog(LOG_ERR, "Couldn't initialize device"); close(hBoard.file_descriptor); return; } /* Allocate memory for ioctl message */ itAllocationLength = (sizeof(ioctl_trans_di) - DI_PAYLOADS_STARTER_LENGTH) + TSYNC_REF_IN_LEN + TSYNC_REF_MAX_OUT_LEN; it = (ioctl_trans_di*)alloca(itAllocationLength); if (it == NULL) { msyslog(LOG_ERR, "Couldn't allocate transaction memory - Reference"); return; } /* Build SS_GetRef ioctl message */ it->dest = TSYNC_REF_DEST_ID; it->iid = TSYNC_REF_IID; it->inPayloadOffset = TSYNC_REF_IN_PYLD_OFF; it->inLength = TSYNC_REF_IN_LEN; it->outPayloadOffset = TSYNC_REF_OUT_PYLD_OFF; it->maxOutLength = TSYNC_REF_MAX_OUT_LEN; it->actualOutLength = 0; it->status = 0; memset(it->payloads, 0, TSYNC_REF_MAX_OUT_LEN); /* Read the reference from the TSYNC-PCI device */ err = ioctl(hBoard.file_descriptor, IOCTL_TSYNC_GET, (char *)it); /* Allocate memory for ioctl message */ itAllocationLength1 = (sizeof(ioctl_trans_di) - DI_PAYLOADS_STARTER_LENGTH) + TSYNC_TMSCL_IN_LEN + TSYNC_TMSCL_MAX_OUT_LEN; it1 = (ioctl_trans_di*)alloca(itAllocationLength1); if (it1 == NULL) { msyslog(LOG_ERR, "Couldn't allocate transaction memory - Time Scale"); return; } /* Build CS_GetTimeScale ioctl message */ it1->dest = TSYNC_TMSCL_DEST_ID; it1->iid = TSYNC_TMSCL_IID; it1->inPayloadOffset = TSYNC_TMSCL_IN_PYLD_OFF; it1->inLength = TSYNC_TMSCL_IN_LEN; it1->outPayloadOffset = TSYNC_TMSCL_OUT_PYLD_OFF; it1->maxOutLength = TSYNC_TMSCL_MAX_OUT_LEN; it1->actualOutLength = 0; it1->status = 0; memset(it1->payloads, 0, TSYNC_TMSCL_MAX_OUT_LEN); /* Read the Time Scale info from the TSYNC-PCI device */ err1 = ioctl(hBoard.file_descriptor, IOCTL_TSYNC_GET, (char *)it1); /* Allocate memory for ioctl message */ itAllocationLength2 = (sizeof(ioctl_trans_di) - DI_PAYLOADS_STARTER_LENGTH) + TSYNC_LEAP_IN_LEN + TSYNC_LEAP_MAX_OUT_LEN; it2 = (ioctl_trans_di*)alloca(itAllocationLength2); if (it2 == NULL) { msyslog(LOG_ERR, "Couldn't allocate transaction memory - Leap Second"); return; } /* Build CS_GetLeapSec ioctl message */ it2->dest = TSYNC_LEAP_DEST_ID; it2->iid = TSYNC_LEAP_IID; it2->inPayloadOffset = TSYNC_LEAP_IN_PYLD_OFF; it2->inLength = TSYNC_LEAP_IN_LEN; it2->outPayloadOffset = TSYNC_LEAP_OUT_PYLD_OFF; it2->maxOutLength = TSYNC_LEAP_MAX_OUT_LEN; it2->actualOutLength = 0; it2->status = 0; memset(it2->payloads, 0, TSYNC_LEAP_MAX_OUT_LEN); /* Read the leap seconds info from the TSYNC-PCI device */ err2 = ioctl(hBoard.file_descriptor, IOCTL_TSYNC_GET, (char *)it2); pp = peer->procptr; up = (TsyncUnit*)pp->unitptr; /* Read the time from the TSYNC-PCI device */ err3 = ioctl(hBoard.file_descriptor, IOCTL_TPRO_GET_NTP_TIME, (char *)&TimeContext); /* Close the TSYNC device */ close(hBoard.file_descriptor); // Check for errors if ((err < 0) ||(err1 < 0) || (err2 < 0) || (err3 < 0) || (it->status != 0) || (it1->status != 0) || (it2->status != 0) || (it->actualOutLength != TSYNC_REF_OUT_LEN) || (it1->actualOutLength != TSYNC_TMSCL_OUT_LEN) || (it2->actualOutLength != TSYNC_LEAP_OUT_LEN)) { refclock_report(peer, CEVNT_FAULT); return; } // Extract reference identifiers from ioctl payload memset(timeRef, '\0', sizeof(timeRef)); memset(ppsRef, '\0', sizeof(ppsRef)); pRefObj = (void *)it->payloads; memcpy(timeRef, pRefObj->time, TSYNC_REF_LEN); memcpy(ppsRef, pRefObj->pps, TSYNC_REF_LEN); // Extract the Clock Service Time Scale and convert to correct byte order memcpy(&tmscl, ((TIME_SCALE*)(it1->payloads)), sizeof(tmscl)); tmscl = ntohl(tmscl); // Extract leap second info from ioctl payload and perform byte swapping for (i = 0; i < (sizeof(leapSec) / 4); i++) { for (j = 0; j < 4; j++) { ((unsigned char*)&leapSec)[(i * 4) + j] = ((unsigned char*)(it2->payloads))[(i * 4) + (3 - j)]; } } // Determine time reference ID from reference name for (i = 0; RefIdLookupTbl[i].pRef != NULL; i++) { // Search RefID table if (strstr(timeRef, RefIdLookupTbl[i].pRef) != NULL) { // Found the matching string break; } } // Determine pps reference ID from reference name for (j = 0; RefIdLookupTbl[j].pRef != NULL; j++) { // Search RefID table if (strstr(ppsRef, RefIdLookupTbl[j].pRef) != NULL) { // Found the matching string break; } } // Determine synchronization state from flags synch = (TimeContext.timeObj.flags == 0x4) ? 1 : 0; // Pull seconds information from time object seconds = (double) (TimeContext.timeObj.secsDouble); seconds /= (double) 1000000.0; /* ** Convert the number of microseconds to double and then place in the ** peer's last received long floating point format. */ DTOLFP(((double)TimeContext.tv.tv_usec / 1000000.0), &pp->lastrec); /* ** The specTimeStamp is the number of seconds since 1/1/1970, while the ** peer's lastrec time should be compatible with NTP which is seconds since ** 1/1/1900. So Add the number of seconds between 1900 and 1970 to the ** specTimeStamp and place in the peer's lastrec long floating point struct. */ pp->lastrec.Ul_i.Xl_ui += (unsigned int)TimeContext.tv.tv_sec + SECONDS_1900_TO_1970; pp->polls++; /* ** set the reference clock object */ sprintf(pp->a_lastcode, "%03d %02d:%02d:%02.6f", TimeContext.timeObj.days, TimeContext.timeObj.hours, TimeContext.timeObj.minutes, seconds); pp->lencode = strlen (pp->a_lastcode); pp->day = TimeContext.timeObj.days; pp->hour = TimeContext.timeObj.hours; pp->minute = TimeContext.timeObj.minutes; pp->second = (int) seconds; seconds = (seconds - (double) (pp->second / 1.0)) * 1000000000; pp->nsec = (long) seconds; /* ** calculate year start */ jt.year = TimeContext.timeObj.year; jt.yearday = 1; jt.monthday = 1; jt.month = 1; jt.hour = 0; jt.minute = 0; jt.second = 0; pp->yearstart = caltontp(&jt); // Calculate and report reference clock offset offset.l_ui = (long)(((pp->day - 1) * 24) + pp->hour + GMT); offset.l_ui = (offset.l_ui * 60) + (long)pp->minute; offset.l_ui = (offset.l_ui * 60) + (long)pp->second; offset.l_ui = offset.l_ui + (long)pp->yearstart; offset.l_uf = 0; DTOLFP(pp->nsec / 1e9, <emp); L_ADD(&offset, <emp); refclock_process_offset(pp, offset, pp->lastrec, pp->fudgetime1); // KTS in sync if (synch) { // Subtract leap second info by one second to determine effective day ApplyTimeOffset(&(leapSec.utcDate), -1); // If there is a leap second today and the KTS is using a time scale // which handles leap seconds then if ((tmscl != TIME_SCALE_GPS) && (tmscl != TIME_SCALE_TAI) && (leapSec.utcDate.year == (unsigned int)TimeContext.timeObj.year) && (leapSec.utcDate.doy == (unsigned int)TimeContext.timeObj.days)) { // If adding a second if (leapSec.offset == 1) { pp->leap = LEAP_ADDSECOND; } // Else if removing a second else if (leapSec.offset == -1) { pp->leap = LEAP_DELSECOND; } // Else report no leap second pending (no handling of offsets // other than +1 or -1) else { pp->leap = LEAP_NOWARNING; } } // Else report no leap second pending else { pp->leap = LEAP_NOWARNING; } peer->leap = pp->leap; refclock_report(peer, CEVNT_NOMINAL); // If reference name reported, then not in holdover if ((RefIdLookupTbl[i].pRef != NULL) && (RefIdLookupTbl[j].pRef != NULL)) { // Determine if KTS being synchronized by host (identified as // "LOCL") if ((strcmp(RefIdLookupTbl[i].pRefId, TSYNC_REF_LOCAL) == 0) || (strcmp(RefIdLookupTbl[j].pRefId, TSYNC_REF_LOCAL) == 0)) { // Clear prefer flag peer->flags &= ~FLAG_PREFER; // Set reference clock stratum level as unusable pp->stratum = STRATUM_UNSPEC; peer->stratum = pp->stratum; // If a valid peer is available if ((sys_peer != NULL) && (sys_peer != peer)) { // Store reference peer stratum level and ID up->refStratum = sys_peer->stratum; up->refId = addr2refid(&sys_peer->srcadr); } } else { // Restore prefer flag peer->flags |= up->refPrefer; // Store reference stratum as local clock up->refStratum = TSYNC_LCL_STRATUM; strncpy((char *)&up->refId, RefIdLookupTbl[j].pRefId, TSYNC_REF_LEN); // Set reference clock stratum level as local clock pp->stratum = TSYNC_LCL_STRATUM; peer->stratum = pp->stratum; } // Update reference name strncpy((char *)&pp->refid, RefIdLookupTbl[j].pRefId, TSYNC_REF_LEN); peer->refid = pp->refid; } // Else in holdover else { // Restore prefer flag peer->flags |= up->refPrefer; // Update reference ID to saved ID pp->refid = up->refId; peer->refid = pp->refid; // Update stratum level to saved stratum level pp->stratum = up->refStratum; peer->stratum = pp->stratum; } } // Else KTS not in sync else { // Place local identifier in peer RefID strncpy((char *)&pp->refid, TSYNC_REF_LOCAL, TSYNC_REF_LEN); peer->refid = pp->refid; // Report not in sync pp->leap = LEAP_NOTINSYNC; peer->leap = pp->leap; } if (pp->coderecv == pp->codeproc) { refclock_report(peer, CEVNT_TIMEOUT); return; } record_clock_stats(&peer->srcadr, pp->a_lastcode); refclock_receive(peer); /* Increment the number of times the reference has been polled */ pp->polls++; } /* End - tsync_poll() */
/* * 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; }
static void check_leapsec( u_int32 now , const time_t * tpiv , int/*BOOL*/ reset) { static const char leapmsg_p_step[] = "Positive leap second, stepped backward."; static const char leapmsg_p_slew[] = "Positive leap second, no step correction. " "System clock will be inaccurate for a long time."; static const char leapmsg_n_step[] = "Negative leap second, stepped forward."; static const char leapmsg_n_slew[] = "Negative leap second, no step correction. " "System clock will be inaccurate for a long time."; leap_result_t lsdata; u_int32 lsprox; #ifdef AUTOKEY int/*BOOL*/ update_autokey = FALSE; #endif #ifndef SYS_WINNT /* WinNT port has its own leap second handling */ # ifdef KERNEL_PLL leapsec_electric(pll_control && kern_enable); # else leapsec_electric(0); # endif #endif #ifdef LEAP_SMEAR leap_smear.enabled = leap_smear_intv != 0; #endif if (reset) { lsprox = LSPROX_NOWARN; leapsec_reset_frame(); memset(&lsdata, 0, sizeof(lsdata)); } else { int fired = leapsec_query(&lsdata, now, tpiv); DPRINTF(1, ("*** leapsec_query: fired %i, now %u (0x%08X), tai_diff %i, ddist %u\n", fired, now, now, lsdata.tai_diff, lsdata.ddist)); #ifdef LEAP_SMEAR leap_smear.in_progress = 0; leap_smear.doffset = 0.0; if (leap_smear.enabled) { if (lsdata.tai_diff) { if (leap_smear.interval == 0) { leap_smear.interval = leap_smear_intv; leap_smear.intv_end = lsdata.ttime.Q_s; leap_smear.intv_start = leap_smear.intv_end - leap_smear.interval; DPRINTF(1, ("*** leapsec_query: setting leap_smear interval %li, begin %.0f, end %.0f\n", leap_smear.interval, leap_smear.intv_start, leap_smear.intv_end)); } } else { if (leap_smear.interval) DPRINTF(1, ("*** leapsec_query: clearing leap_smear interval\n")); leap_smear.interval = 0; } if (leap_smear.interval) { double dtemp = now; if (dtemp >= leap_smear.intv_start && dtemp <= leap_smear.intv_end) { double leap_smear_time = dtemp - leap_smear.intv_start; /* * For now we just do a linear interpolation over the smear interval */ #if 0 // linear interpolation leap_smear.doffset = -(leap_smear_time * lsdata.tai_diff / leap_smear.interval); #else // Google approach: lie(t) = (1.0 - cos(pi * t / w)) / 2.0 leap_smear.doffset = -((double) lsdata.tai_diff - cos( M_PI * leap_smear_time / leap_smear.interval)) / 2.0; #endif /* * TODO see if we're inside an inserted leap second, so we need to compute * leap_smear.doffset = 1.0 - leap_smear.doffset */ leap_smear.in_progress = 1; #if 0 && defined( DEBUG ) msyslog(LOG_NOTICE, "*** leapsec_query: [%.0f:%.0f] (%li), now %u (%.0f), smear offset %.6f ms\n", leap_smear.intv_start, leap_smear.intv_end, leap_smear.interval, now, leap_smear_time, leap_smear.doffset); #else DPRINTF(1, ("*** leapsec_query: [%.0f:%.0f] (%li), now %u (%.0f), smear offset %.6f ms\n", leap_smear.intv_start, leap_smear.intv_end, leap_smear.interval, now, leap_smear_time, leap_smear.doffset)); #endif } } } else leap_smear.interval = 0; /* * Update the current leap smear offset, eventually 0.0 if outside smear interval. */ DTOLFP(leap_smear.doffset, &leap_smear.offset); #endif /* LEAP_SMEAR */ if (fired) { /* Full hit. Eventually step the clock, but always * announce the leap event has happened. */ const char *leapmsg = NULL; if (lsdata.warped < 0) { if (clock_max_back > 0.0 && clock_max_back < abs(lsdata.warped)) { step_systime(lsdata.warped); leapmsg = leapmsg_p_step; } else { leapmsg = leapmsg_p_slew; } } else if (lsdata.warped > 0) { if (clock_max_fwd > 0.0 && clock_max_fwd < abs(lsdata.warped)) { step_systime(lsdata.warped); leapmsg = leapmsg_n_step; } else { leapmsg = leapmsg_n_slew; } } if (leapmsg) msyslog(LOG_NOTICE, "%s", leapmsg); report_event(EVNT_LEAP, NULL, NULL); #ifdef AUTOKEY update_autokey = TRUE; #endif lsprox = LSPROX_NOWARN; leapsec = LSPROX_NOWARN; sys_tai = lsdata.tai_offs; } else { #ifdef AUTOKEY update_autokey = (sys_tai != (u_int)lsdata.tai_offs); #endif lsprox = lsdata.proximity; sys_tai = lsdata.tai_offs; } } /* We guard against panic alarming during the red alert phase. * Strange and evil things might happen if we go from stone cold * to piping hot in one step. If things are already that wobbly, * we let the normal clock correction take over, even if a jump * is involved. * Also make sure the alarming events are edge-triggered, that is, * ceated only when the threshold is crossed. */ if ( (leapsec > 0 || lsprox < LSPROX_ALERT) && leapsec < lsprox ) { if ( leapsec < LSPROX_SCHEDULE && lsprox >= LSPROX_SCHEDULE) { if (lsdata.dynamic) report_event(PEVNT_ARMED, sys_peer, NULL); else report_event(EVNT_ARMED, NULL, NULL); } leapsec = lsprox; } if (leapsec > lsprox) { if ( leapsec >= LSPROX_SCHEDULE && lsprox < LSPROX_SCHEDULE) { report_event(EVNT_DISARMED, NULL, NULL); } leapsec = lsprox; } if (leapsec >= LSPROX_SCHEDULE) leapdif = lsdata.tai_diff; else leapdif = 0; check_leap_sec_in_progress(&lsdata); #ifdef AUTOKEY if (update_autokey) crypto_update_taichange(); #endif }
/* * 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; } } }
/* * vme_poll - called by the transmit procedure */ static void vme_poll( int unit, struct peer *peer ) { struct vmedate *tptr; struct vmeunit *vme; l_fp tstmp; time_t tloc; struct tm *tadr; long ltemp; if (unit >= MAXUNITS) { msyslog(LOG_ERR, "vme_poll: unit %d invalid", unit); return; } if (!unitinuse[unit]) { msyslog(LOG_ERR, "vme_poll: unit %d not in use", unit); return; } vme = vmeunits[unit]; /* Here is the structure */ vme->polls++; tptr = &vme->vmedata; if ((tptr = get_gpsvme_time()) == NULL ) { vme_report_event(vme, CEVNT_BADREPLY); return; } get_systime(&vme->lastrec); vme->lasttime = current_time; /* * Get VME time and convert to timestamp format. * The year must come from the system clock. */ /* time(&tloc); tadr = gmtime(&tloc); tptr->year = (unsigned short)(tadr->tm_year + 1900); */ sprintf(vme->lastcode, "%3.3d %2.2d:%2.2d:%2.2d.%.6d %1d\0", tptr->doy, tptr->hr, tptr->mn, tptr->sec, tptr->frac, tptr->status); record_clock_stats(&(vme->peer->srcadr), vme->lastcode); vme->lencode = (u_short) strlen(vme->lastcode); vme->day = tptr->doy; vme->hour = tptr->hr; vme->minute = tptr->mn; vme->second = tptr->sec; vme->nsec = tptr->frac * 1000; #ifdef DEBUG if (debug) printf("vme: %3d %02d:%02d:%02d.%06ld %1x\n", vme->day, vme->hour, vme->minute, vme->second, vme->nsec, tptr->status); #endif if (tptr->status ) { /* Status 0 is locked to ref., 1 is not */ vme_report_event(vme, CEVNT_BADREPLY); return; } /* * Now, compute the reference time value. Use the heavy * machinery for the seconds and the millisecond field for the * fraction when present. If an error in conversion to internal * format is found, the program declares bad data and exits. * Note that this code does not yet know how to do the years and * relies on the clock-calendar chip for sanity. */ if (!clocktime(vme->day, vme->hour, vme->minute, vme->second, GMT, vme->lastrec.l_ui, &vme->yearstart, &vme->lastref.l_ui)) { vme->baddata++; vme_report_event(vme, CEVNT_BADTIME); msyslog(LOG_ERR, "refclock_gpsvme: bad data!!"); return; } vme->lastref.l_uf = 0; DTOLFP(vme->nsec / 1e9, <emp); L_ADD(&vme->lastrec, <emp); tstmp = vme->lastref; L_SUB(&tstmp, &vme->lastrec); vme->coderecv++; L_ADD(&tstmp, &(fudgefactor[vme->unit])); vme->lastref = vme->lastrec; refclock_receive(vme->peer); }
static int burst_process(mapidflib_function_instance_t *instance, MAPI_UNUSED unsigned char* dev_pkt, MAPI_UNUSED unsigned char* link_pkt, mapid_pkthdr_t* pkt_head) { struct burst_inst_struct *internal_data_ptr; int cat; // count with l_fp l_fp pkt_ts_min, pkt_ts_max, pkt_ts_exa, len_ts_min, len_ts_max, len_ts_exa; // store final values in ull unsigned long long pkt_ts_ull_min, pkt_ts_ull_max, pkt_ts_ull_exa; // gap unsigned long long gap_len_frac; double gap_len_s; unsigned long long gap_len_b; // Debugging {{{ // just ascii art, not code #ifdef __BURST_DEBUG l_fp delta, pkt_ts, len_ts, assumed_ts; double d_i, d_f; #endif #ifdef __BURST_DEBUG_LAG_LEAD l_fp laglead; #ifndef __BURST_DEBUG l_fp len_ts, assumed_ts; double d_i, d_f; #endif #endif #ifdef __BURST_DEBUG_LAG_LEAD_MAX unsigned long long assumed_ts_ull, len_ts_ull, laglead_ull; #ifndef __BURST_DEBUG_LAG_LEAD l_fp laglead; #ifndef __BURST_DEBUG l_fp len_ts; double d_i, d_f; #endif #endif #endif // }}} internal_data_ptr = (struct burst_inst_struct *) (instance->internal_data); // count min / max ts // start with last_pkt_ts pkt_ts_max = internal_data_ptr->last_pkt_ts; pkt_ts_min = internal_data_ptr->last_pkt_ts; pkt_ts_exa = internal_data_ptr->last_pkt_ts; // add wlen, iatime, +- DTOLFP(internal_data_ptr->last_pkt_wlen * internal_data_ptr->B_s + internal_data_ptr->iatime_s - internal_data_ptr->lead_s, len_ts_min); DTOLFP(internal_data_ptr->last_pkt_wlen * internal_data_ptr->B_s + internal_data_ptr->iatime_s + internal_data_ptr->lag_s, len_ts_max); DTOLFP(internal_data_ptr->last_pkt_wlen * internal_data_ptr->B_s + internal_data_ptr->iatime_s, len_ts_exa); L_ADD(pkt_ts_min, len_ts_min); L_ADD(pkt_ts_max, len_ts_max); L_ADD(pkt_ts_exa, len_ts_exa); // Debugging {{{ #ifdef __BURST_DEBUG_WARNINGS unsigned long long lastullts; LFPTOULL(internal_data_ptr->last_pkt_ts, lastullts); if(pkt_head->ts == lastullts) printf("* OMG, same timestamp as previous. Deja vu or what? Timestamps does not seem to be very reliable.\n"); if(pkt_head->ts < lastullts) printf("* OMG^2, timestamp smaller than previous. Timestamps does not seem to be very reliable.\n"); #endif #ifdef __BURST_DEBUG printf(">>> [ pkt_head->wlen: %d (B) ]\n", pkt_head->wlen); ULLTOLFP(pkt_head->ts, delta); L_SUB(delta, internal_data_ptr->last_pkt_ts); LFPTODD(delta, d_i, d_f); printf("with delt/\\: %012lu.%012lu (ntp) == %010.0f + %.012f (sec)\n", delta.l_ui, delta.l_uf, d_i, d_f); //////printf("count with me: %u * %023.012f = %023.012f a+ %023.012f = %023.012f ok???\n", internal_data_ptr->last_pkt_wlen, internal_data_ptr->B_s, internal_data_ptr->last_pkt_wlen * internal_data_ptr->B_s, internal_data_ptr->iatime_s, internal_data_ptr->last_pkt_wlen * internal_data_ptr->B_s + internal_data_ptr->iatime_s); assumed_ts = internal_data_ptr->last_pkt_ts; DTOLFP(internal_data_ptr->last_pkt_wlen * internal_data_ptr->B_s + internal_data_ptr->iatime_s, len_ts); L_ADD(assumed_ts, len_ts); LFPTODD(assumed_ts, d_i, d_f); printf("assumed_ts=: %012lu.%012lu (ntp) == %010.0f + %.012f (sec)\n", assumed_ts.l_ui, assumed_ts.l_uf, d_i, d_f); ULLTOLFP(pkt_head->ts, pkt_ts); LFPTODD(pkt_ts, d_i, d_f); printf("current_ts=: %012lu.%012lu (ntp) == %010.0f + %.012f (sec) %llu\n", pkt_ts.l_ui, pkt_ts.l_uf, d_i, d_f, pkt_head->ts); // //LFPTODD(pkt_ts_min, d_i, d_f); //printf(" -: %012lu.%012lu (ntp) == %010.0f + %.012f (sec)\n", pkt_ts_min.l_ui, pkt_ts_min.l_uf, d_i, d_f); // //LFPTODD(pkt_ts_max, d_i, d_f); //printf(" +: %012lu.%012lu (ntp) == %010.0f + %.012f (sec)\n", pkt_ts_max.l_ui, pkt_ts_max.l_uf, d_i, d_f); #endif #ifdef __BURST_DEBUG_LAG_LEAD assumed_ts = internal_data_ptr->last_pkt_ts; DTOLFP(internal_data_ptr->last_pkt_wlen * internal_data_ptr->B_s + internal_data_ptr->iatime_s, len_ts); L_ADD(assumed_ts, len_ts); ULLTOLFP(pkt_head->ts, laglead); L_SUB(laglead, assumed_ts); LFPTODD(laglead, d_i, d_f); printf("so lag/lead: %012lu.%012lu (ntp) == %010.0f + %.012f (sec)\n", laglead.l_ui, laglead.l_uf, d_i, d_f); #endif #ifdef __BURST_DEBUG_LAG_LEAD_MAX LFPTOULL(internal_data_ptr->last_pkt_ts, assumed_ts_ull); DTOLFP(internal_data_ptr->last_pkt_wlen * internal_data_ptr->B_s + internal_data_ptr->iatime_s, len_ts); LFPTOULL(len_ts, len_ts_ull); assumed_ts_ull += len_ts_ull; laglead_ull = pkt_head->ts - assumed_ts_ull; if(pkt_head->ts >= assumed_ts_ull) { // lag if(laglead_ull > internal_data_ptr->lagmax) { // update if(internal_data_ptr->initialized == 0) { // first time internal_data_ptr->initialized = 1; // initialize } else { // update internal_data_ptr->lagmax = laglead_ull; ULLTOLFP(laglead_ull, laglead); LFPTODD(laglead, d_i, d_f); printf("lagmax : %012lu.%012lu (ntp) == %010.0f + %.012f (sec)\n", laglead.l_ui, laglead.l_uf, d_i, d_f); } } } else { // lead if(laglead_ull < internal_data_ptr->leadmax) { // update if(internal_data_ptr->initialized == 0) { // first time internal_data_ptr->initialized = 1; // initialize } else { internal_data_ptr->leadmax = laglead_ull; ULLTOLFP(laglead_ull, laglead); LFPTODD(laglead, d_i, d_f); printf("leadmax : %012lu.%012lu (ntp) == %010.0f + %.012f (sec)\n", laglead.l_ui, laglead.l_uf, d_i, d_f); } } } #endif // }}} // resolve bursts LFPTOULL(pkt_ts_min, pkt_ts_ull_min); LFPTOULL(pkt_ts_max, pkt_ts_ull_max); LFPTOULL(pkt_ts_exa, pkt_ts_ull_exa); // not burst if(pkt_head->ts < pkt_ts_ull_min || pkt_head->ts > pkt_ts_ull_max) { // count measurement into results if(internal_data_ptr->burst_bytes < (unsigned long) internal_data_ptr->min) { // Debugging {{{ #ifdef __BURST_VERBOSE printf("process: I am sed :-( I wish I have [0.x] to save this burst into.\n"); #endif // }}} cat = 0; } else cat = ((internal_data_ptr->burst_bytes - internal_data_ptr->min) / internal_data_ptr->step) + 1; // +1: category 0 is reserved for <0, min> if(cat > internal_data_ptr->cats) { // Debugging {{{ #ifdef __BURST_VERBOSE printf("process: I am sed :-( I wish I have [%d] to save this burst into.\n", cat); #endif // }}} cat = internal_data_ptr->cats; } ((burst_category_t *)instance->result.data)[cat].bytes += internal_data_ptr->burst_bytes; ((burst_category_t *)instance->result.data)[cat].packets += internal_data_ptr->burst_packets; if(internal_data_ptr->burst_bytes > 0) // not the very first packet ((burst_category_t *)instance->result.data)[cat].bursts++; // Debugging {{{ #ifdef __BURST_VERBOSE printf("process: save [%d / %d] += %lu B (= %lu B), += %lu pkts (= %lu pkts), +1 burst (= %lu bursts)\n", cat, internal_data_ptr->cats, internal_data_ptr->burst_bytes, ((burst_category_t *)instance->result.data)[cat].bytes, internal_data_ptr->burst_packets, ((burst_category_t *)instance->result.data)[cat].packets, ((burst_category_t *)instance->result.data)[cat].bursts); #endif // }}} // and start new measurement internal_data_ptr->burst_bytes = 0; // reset collectors internal_data_ptr->burst_packets = 0; // NEW: store inter-burst gap size too if(internal_data_ptr->last_pkt_wlen) { // if not first packet if(pkt_head->ts > pkt_ts_ull_exa) { gap_len_frac = pkt_head->ts - pkt_ts_ull_exa; ULLTOD(gap_len_frac, gap_len_s); gap_len_b = (unsigned long long) (gap_len_s / internal_data_ptr->B_s); } else gap_len_b = 0; if(gap_len_b < (unsigned) internal_data_ptr->min) { cat = 0; } else cat = ((gap_len_b - internal_data_ptr->min) / internal_data_ptr->step) + 1; // +1: category 0 is reserved for <0, min> if(cat > internal_data_ptr->cats) { cat = internal_data_ptr->cats; } ((burst_category_t *)instance->result.data)[cat].gap_bytes += gap_len_b; if(internal_data_ptr->burst_bytes > 0) // not the very first packet ((burst_category_t *)instance->result.data)[cat].gaps++; } } else { // if one bursts, show goes on // Debugging {{{ #ifdef __BURST_VERBOSE printf("process: collect [x] (BURST detected)\n"); #endif // }}} } // count current into collector internal_data_ptr->burst_bytes += (unsigned long) pkt_head->wlen; internal_data_ptr->burst_packets++; // save pktinfo for next generation ULLTOLFP(pkt_head->ts, internal_data_ptr->last_pkt_ts); internal_data_ptr->last_pkt_wlen = pkt_head->wlen; return 1; }
LFP::LFP(double rhs) { DTOLFP(rhs, &_v); }