Beispiel #1
0
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);
}
Beispiel #2
0
/*
 * 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, &ltemp);
	L_ADD(&offset, &ltemp);
	refclock_process_offset(pp, offset, pp->lastrec, fudge);
	return (1);
}
Beispiel #3
0
l_fp
l_fp_init_from_double( double rhs)
{
	l_fp temp;
	DTOLFP(rhs, &temp);
	return temp;
}
Beispiel #4
0
/*
 * 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);
}
Beispiel #5
0
/*
 * 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);
}
Beispiel #6
0
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);
}
Beispiel #7
0
/*
 * 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);
*/
}
Beispiel #8
0
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;
}
Beispiel #9
0
/*
 * 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, &ltemp);
	L_SUB(&rbufp->recv_time, &ltemp);
	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;
}
Beispiel #10
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);
}
Beispiel #11
0
/* 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);
}
Beispiel #12
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, &ltemp);
    L_ADD(&offset, &ltemp);
    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() */
Beispiel #13
0
/*
 * 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;
}
Beispiel #14
0
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
}
Beispiel #15
0
/*
 * 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;
		}
	}
}
Beispiel #16
0
/*
 * 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, &ltemp);
	L_ADD(&vme->lastrec, &ltemp);
	tstmp = vme->lastref;

	L_SUB(&tstmp, &vme->lastrec);
	vme->coderecv++;

	L_ADD(&tstmp, &(fudgefactor[vme->unit]));
	vme->lastref = vme->lastrec;
	refclock_receive(vme->peer);
}
Beispiel #17
0
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;
}
Beispiel #18
0
LFP::LFP(double rhs)
{
	DTOLFP(rhs, &_v);
}