static void gpsd_parse( peerT * const peer , const l_fp * const rtime) { clockprocT * const pp = peer->procptr; gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; json_ctx jctx; const char * clsid; l_fp tmpfp; DPRINTF(2, ("GPSD_JSON(%d): gpsd_parse: time %s '%s'\n", up->unit, ulfptoa(rtime, 6), up->buffer)); /* See if we can grab anything potentially useful */ if (!json_parse_record(&jctx, up->buffer)) return; /* Now dispatch over the objects we know */ clsid = json_object_lookup_string_default( &jctx, 0, "class", "-bad-repy-"); up->tc_recv += 1; if (!strcmp("VERSION", clsid)) process_version(peer, &jctx, rtime); else if (!strcmp("TPV", clsid)) process_tpv(peer, &jctx, rtime); else if (!strcmp("PPS", clsid)) process_pps(peer, &jctx, rtime); else if (!strcmp("WATCH", clsid)) process_watch(peer, &jctx, rtime); else return; /* nothing we know about... */ /* now aggregate TPV and PPS -- no PPS? just use TPV...*/ if (up->fl_tpv) { /* TODO: also check remote receive time stamps */ tmpfp = up->tpv_local; L_SUB(&tmpfp, &up->pps_local); if (up->fl_pps && 0 == tmpfp.l_ui) { refclock_process_offset( pp, up->tpv_stamp, up->pps_recvt, 0.0); if (up->ppscount < PPS_MAXCOUNT) up->ppscount += 1; } else { refclock_process_offset( pp, up->tpv_stamp, up->tpv_recvt, 0.0); if (up->ppscount > 0) up->ppscount -= 1; } up->fl_pps = 0; up->fl_tpv = 0; up->tc_good += 1; } }
/* * 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); }
/* * refclock_process - process a sample from the clock * * 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. */ int refclock_process( struct refclockproc *pp ) { l_fp offset; /* * 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); if (pp->usec) { TVUTOTSF(pp->usec, offset.l_uf); } else { MSUTOTSF(pp->msec, offset.l_uf); } refclock_process_offset(pp, offset, pp->lastrec, pp->fudgetime1); return (1); }
/* * local_poll - called by the transmit procedure * * LOCKCLOCK: If the kernel supports the nanokernel or microkernel * system calls, the leap bits are extracted from the kernel. If there * is a kernel error or the kernel leap bits are set to 11, the NTP leap * bits are set to 11 and the stratum is set to infinity. Otherwise, the * NTP leap bits are set to the kernel leap bits and the stratum is set * as fudged. This behavior does not faithfully follow the * specification, but is probably more appropriate in a multiple-server * national laboratory network. */ static void local_poll( int unit, struct peer *peer ) { #if defined(KERNEL_PLL) && defined(LOCKCLOCK) struct timex ntv; #endif /* KERNEL_PLL LOCKCLOCK */ struct refclockproc *pp; /* * Do no evil unless the house is dark or lit with our own lamp. */ if (!(sys_peer == NULL || sys_peer == peer)) return; #if defined(VMS) && defined(VMS_LOCALUNIT) if (unit == VMS_LOCALUNIT) { extern void vms_local_poll(struct peer *); vms_local_poll(peer); return; } #endif /* VMS && VMS_LOCALUNIT */ pp = peer->procptr; pp->polls++; /* * Ramble through the usual filtering and grooming code, which * is essentially a no-op and included mostly for pretty * billboards. */ poll_time = current_time; refclock_process_offset(pp, pp->lastrec, pp->lastrec, 0); /* * If another process is disciplining the system clock, we set * the leap bits and quality indicators from the kernel. */ #if defined(KERNEL_PLL) && defined(LOCKCLOCK) memset(&ntv, 0, sizeof ntv); switch (ntp_adjtime(&ntv)) { case TIME_OK: pp->leap = LEAP_NOWARNING; peer->stratum = pp->stratum; break; case TIME_INS: pp->leap = LEAP_ADDSECOND; peer->stratum = pp->stratum; break; case TIME_DEL: pp->leap = LEAP_DELSECOND; peer->stratum = pp->stratum; break; default: pp->leap = LEAP_NOTINSYNC; peer->stratum = STRATUM_UNSPEC; } pp->disp = 0; pp->jitter = 0; #else /* KERNEL_PLL LOCKCLOCK */ pp->disp = DISPERSION; pp->jitter = 0; #endif /* KERNEL_PLL LOCKCLOCK */ pp->lastref = pp->lastrec; refclock_receive(peer); }
/****************************************************************************** * * 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() */
/* * local_poll - called by the transmit procedure * * LOCKCLOCK: If the kernel supports the nanokernel or microkernel * system calls, the leap bits are extracted from the kernel. If there * is a kernel error or the kernel leap bits are set to 11, the NTP leap * bits are set to 11 and the stratum is set to infinity. Otherwise, the * NTP leap bits are set to the kernel leap bits and the stratum is set * as fudged. This behavior does not faithfully follow the * specification, but is probably more appropriate in a multiple-server * national laboratory network. */ static void local_poll( int unit, struct peer *peer ) { #if defined(KERNEL_PLL) && defined(LOCKCLOCK) struct timex ntv; #endif /* KERNEL_PLL LOCKCLOCK */ struct refclockproc *pp; #if defined(VMS) && defined(VMS_LOCALUNIT) if (unit == VMS_LOCALUNIT) { extern void vms_local_poll(struct peer *); vms_local_poll(peer); return; } #endif /* VMS && VMS_LOCALUNIT */ pp = peer->procptr; pp->polls++; /* * Ramble through the usual filtering and grooming code, which * is essentially a no-op and included mostly for pretty * billboards. We allow a one-time time adjustment using fudge * time1 (s) and a continuous frequency adjustment using fudge * time 2 (ppm). */ get_systime(&pp->lastrec); pp->fudgetime1 += pp->fudgetime2 * 1e-6 * (current_time - poll_time); poll_time = current_time; refclock_process_offset(pp, pp->lastrec, pp->lastrec, pp->fudgetime1); /* * If another process is disciplining the system clock, we set * the leap bits and quality indicators from the kernel. */ #if defined(KERNEL_PLL) && defined(LOCKCLOCK) memset(&ntv, 0, sizeof ntv); switch (ntp_adjtime(&ntv)) { case TIME_OK: pp->leap = LEAP_NOWARNING; peer->stratum = pp->stratum; break; case TIME_INS: pp->leap = LEAP_ADDSECOND; peer->stratum = pp->stratum; break; case TIME_DEL: pp->leap = LEAP_DELSECOND; peer->stratum = pp->stratum; break; default: pp->leap = LEAP_NOTINSYNC; peer->stratum = STRATUM_UNSPEC; } pp->disp = 0; pp->jitter = 0; #else /* KERNEL_PLL LOCKCLOCK */ pp->leap = LEAP_NOWARNING; pp->disp = DISPERSION; pp->jitter = 0; #endif /* KERNEL_PLL LOCKCLOCK */ pp->lastref = pp->lastrec; refclock_receive(peer); pp->fudgetime1 = 0; }
/* * shm_timer - called once every second. * * This tries to grab a sample from the SHM segment, filtering bad ones */ static void shm_timer( int unit, struct peer *peer ) { struct refclockproc * const pp = peer->procptr; struct shmunit * const up = pp->unitptr; volatile struct shmTime *shm; l_fp tsrcv; l_fp tsref; int c; /* for formatting 'a_lastcode': */ struct calendar cd; time_t tt; vint64 ts; enum segstat_t status; struct shm_stat_t shm_stat; up->ticks++; if ((shm = up->shm) == NULL) { /* try to map again - this may succeed if meanwhile some- body has ipcrm'ed the old (unaccessible) shared mem segment */ shm = up->shm = getShmTime(unit, up->forall); if (shm == NULL) { DPRINTF(1, ("%s: no SHM segment\n", refnumtoa(&peer->srcadr))); return; } } /* query the segment, atomically */ status = shm_query(shm, &shm_stat); switch (status) { case OK: DPRINTF(2, ("%s: SHM type %d sample\n", refnumtoa(&peer->srcadr), shm_stat.mode)); break; case NO_SEGMENT: /* should never happen, but is harmless */ return; case NOT_READY: DPRINTF(1, ("%s: SHM not ready\n",refnumtoa(&peer->srcadr))); up->notready++; return; case BAD_MODE: DPRINTF(1, ("%s: SHM type blooper, mode=%d\n", refnumtoa(&peer->srcadr), shm->mode)); up->bad++; msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d", shm->mode); return; case CLASH: DPRINTF(1, ("%s: type 1 access clash\n", refnumtoa(&peer->srcadr))); msyslog (LOG_NOTICE, "SHM: access clash in shared memory"); up->clash++; return; default: DPRINTF(1, ("%s: internal error, unknown SHM fetch status\n", refnumtoa(&peer->srcadr))); msyslog (LOG_NOTICE, "internal error, unknown SHM fetch status"); up->bad++; return; } /* format the last time code in human-readable form into * 'pp->a_lastcode'. Someone claimed: "NetBSD has incompatible * tv_sec". I can't find a base for this claim, but we can work * around that potential problem. BTW, simply casting a pointer * is a receipe for disaster on some architectures. */ tt = (time_t)shm_stat.tvt.tv_sec; ts = time_to_vint64(&tt); ntpcal_time_to_date(&cd, &ts); /* add ntpq -c cv timecode in ISO 8601 format */ c = snprintf(pp->a_lastcode, sizeof(pp->a_lastcode), "%04u-%02u-%02uT%02u:%02u:%02u.%09ldZ", cd.year, cd.month, cd.monthday, cd.hour, cd.minute, cd.second, (long)shm_stat.tvt.tv_nsec); pp->lencode = ((size_t)c < sizeof(pp->a_lastcode)) ? c : 0; /* check 1: age control of local time stamp */ tt = shm_stat.tvc.tv_sec - shm_stat.tvr.tv_sec; if (tt < 0 || tt > up->max_delay) { DPRINTF(1, ("%s:SHM stale/bad receive time, delay=%llds\n", refnumtoa(&peer->srcadr), (long long)tt)); up->bad++; msyslog (LOG_ERR, "SHM: stale/bad receive time, delay=%llds", (long long)tt); return; } /* check 2: delta check */ tt = shm_stat.tvr.tv_sec - shm_stat.tvt.tv_sec - (shm_stat.tvr.tv_nsec < shm_stat.tvt.tv_nsec); if (tt < 0) tt = -tt; if (up->max_delta > 0 && tt > up->max_delta) { DPRINTF(1, ("%s: SHM diff limit exceeded, delta=%llds\n", refnumtoa(&peer->srcadr), (long long)tt)); up->bad++; msyslog (LOG_ERR, "SHM: difference limit exceeded, delta=%llds\n", (long long)tt); return; } /* if we really made it to this point... we're winners! */ DPRINTF(2, ("%s: SHM feeding data\n", refnumtoa(&peer->srcadr))); tsrcv = tspec_stamp_to_lfp(shm_stat.tvr); tsref = tspec_stamp_to_lfp(shm_stat.tvt); pp->leap = shm_stat.leap; peer->precision = shm_stat.precision; refclock_process_offset(pp, tsref, tsrcv, pp->fudgetime1); up->good++; }