Beispiel #1
0
void ntpshm_init(struct gps_context_t *context, bool enablepps)
/* attach all NTP SHM segments.  called once at startup, while still root */
{
    int i;

    for (i = 0; i < NTPSHMSEGS; i++)
	context->shmTime[i] = getShmTime(i);
    memset(context->shmTimeInuse,0,sizeof(context->shmTimeInuse));
# ifdef PPS_ENABLE
    context->shmTimePPS = enablepps;
# endif /* PPS_ENABLE */
    context->enable_ntpshm = true;
}
Beispiel #2
0
void ntpshm_context_init(struct gps_context_t *context)
/* Attach all NTP SHM segments. Called once at startup, while still root. */
{
    int i;

    for (i = 0; i < NTPSHMSEGS; i++) {
	// Only grab the first two when running as root.
	if (2 <= i || 0 == getuid()) {
	    context->shmTime[i] = getShmTime(context, i);
	}
    }
    memset(context->shmTimeInuse, 0, sizeof(context->shmTimeInuse));
}
Beispiel #3
0
void ntpshm_init(struct gps_context_t *context, bool enablepps UNUSED)
#endif /* PPS_ENABLE */
/* Attach all NTP SHM segments. Called once at startup, while still root. */
{
    int i;

    for (i = 0; i < NTPSHMSEGS; i++) {
	// Only grab the first two when running as root.
	if (2 <= i || 0 == getuid()) {
	    context->shmTime[i] = getShmTime(i);
	}
    }
    memset(context->shmTimeInuse, 0, sizeof(context->shmTimeInuse));
# ifdef PPS_ENABLE
    context->shmTimePPS = enablepps;
# endif	/* PPS_ENABLE */
    context->enable_ntpshm = true;
}
Beispiel #4
0
/*
 * shm_start - attach to shared memory
 */
static int
shm_start(
	int unit,
	struct peer *peer
	)
{
	struct refclockproc * const pp = peer->procptr;
	struct shmunit *      const up = emalloc_zero(sizeof(*up));

	pp->io.clock_recv = noentry;
	pp->io.srcclock = peer;
	pp->io.datalen = 0;
	pp->io.fd = -1;

	up->forall = (unit >= 2) && !(peer->ttl & SHM_MODE_PRIVATE);

	up->shm = getShmTime(unit, up->forall);

	/*
	 * Initialize miscellaneous peer variables
	 */
	memcpy((char *)&pp->refid, REFID, 4);
	if (up->shm != 0) {
		pp->unitptr = up;
		up->shm->precision = PRECISION;
		peer->precision = up->shm->precision;
		up->shm->valid = 0;
		up->shm->nsamples = NSAMPLES;
		pp->clockdesc = DESCRIPTION;
		/* items to be changed later in 'shm_control()': */
		up->max_delay = 5;
		up->max_delta = 4*3600;
		return 1;
	} else {
		free(up);
		pp->unitptr = NULL;
		return 0;
	}
}
Beispiel #5
0
int
main (
	int argc,
	char *argv[]
	)
{
	volatile struct shmTime *p=getShmTime(2);
	if (argc<=1) {
		printf ("usage: %s r[c][l]|w|snnn\n",argv[0]);
		printf ("       r read shared memory\n");
		printf ("        c clear valid-flag\n");
		printf ("        l loop (so, rcl will read and clear in a loop\n");
		printf ("       w write shared memory with current time\n");
		printf ("       snnnn set nsamples to nnn\n");
		printf ("       lnnnn set leap to nnn\n");
		printf ("       pnnnn set precision to -nnn\n");
		exit (0);
	}
	switch (argv[1][0]) {
	    case 's': {
		    p->nsamples=atoi(&argv[1][1]);
	    }
	    break;
	    case 'l': {
		    p->leap=atoi(&argv[1][1]);
	    }
	    break;
	    case 'p': {
		    p->precision=-atoi(&argv[1][1]);
	    }
	    break;
	    case 'r': {
		    char *ap=&argv[1][1];
		    int clear=0;
		    int loop=0;
		    printf ("reader\n");
		    while (*ap) {
			    switch (*ap) {
				case 'l' : loop=1; break;
				case 'c' : clear=1; break;
			    }
			    ap++;
		    }
		    do {
			    printf ("mode=%d, count=%d, clock=%d.%d, rec=%d.%d,\n",
				    p->mode,p->count,p->clockTimeStampSec,p->clockTimeStampUSec,
				    p->receiveTimeStampSec,p->receiveTimeStampUSec);
			    printf ("  leap=%d, precision=%d, nsamples=%d, valid=%d\n",
				    p->leap, p->precision, p->nsamples, p->valid);
			    if (!p->valid)
				printf ("***\n");
			    if (clear) {
				    p->valid=0;
				    printf ("cleared\n");
			    }
			    if (loop)
				sleep (1);
		    } while (loop);
	    }
	    break;
	    case 'w': {
		    printf ("writer\n");
		    p->mode=0;
		    if (!p->valid) {
			    p->clockTimeStampSec=time(0)-20;
			    p->clockTimeStampUSec=0;
			    p->receiveTimeStampSec=time(0)-1;
			    p->receiveTimeStampUSec=0;
			    printf ("%d %d\n",p->clockTimeStampSec, p->receiveTimeStampSec);
			    p->valid=1;
		    }
		    else {
			    printf ("p->valid still set\n"); /* not an error! */
		    }
	    }
	    break;
	}
}
Beispiel #6
0
int
main (
	int argc,
	char *argv[]
	)
{
	volatile struct shmTime *p;
	int unit;
	char *argp;

	if (argc<=1) {
	  usage:
		printf ("usage: %s [uu:]{r[c][l]|w|snnn}\n",argv[0]);
		printf ("       uu use clock unit uu (default: 2)\n");
		printf ("       r read shared memory\n");
		printf ("       c clear valid-flag\n");
		printf ("       l loop (so, rcl will read and clear in a loop\n");
		printf ("       w write shared memory with current time\n");
		printf ("       snnnn set nsamples to nnn\n");
		printf ("       lnnnn set leap to nnn\n");
		printf ("       pnnnn set precision to -nnn\n");
		exit (0);
	}

	srand(time(NULL));
		
	unit = strtoul(argv[1], &argp, 10);
	if (argp == argv[1])
		unit = 2;
	else if (*argp == ':')
		argp++;
	else
		goto usage;

	p=getShmTime(unit);
	switch (*argp) {
	case 's':
		p->nsamples=atoi(argp+1);
		break;

	case 'l':
		p->leap=atoi(argp+1);
		break;

	case 'p':
		p->precision=-atoi(argp+1);
		break;

	case 'r': {
		int clear=0;
		int loop=0;
		printf ("reader\n");		
		while (*++argp) {
			switch (*argp) {
			case 'l': loop=1; break;
			case 'c': clear=1; break;
			default : goto usage;
			}
		}
again:
		printf ("mode=%d, count=%d, clock=%ld.%09u, rec=%ld.%09u,\n",
			p->mode,p->count,
			(long)p->clockTimeStampSec,p->clockTimeStampNSec,
			(long)p->receiveTimeStampSec,p->receiveTimeStampNSec);
		printf ("  leap=%d, precision=%d, nsamples=%d, valid=%d\n",
			p->leap, p->precision, p->nsamples, p->valid);
		if (!p->valid)
			printf ("***\n");
		if (clear) {
			p->valid=0;
			printf ("cleared\n");
		}
		if (loop) {
			sleep (1);
			goto again;
		}
		break;
	}

	case 'w': {
		/* To show some life action, we read the system
		 * clock and use a bit of fuzz from 'random()' to get a
		 * bit of wobbling into the values (so we can observe a
		 * certain jitter!)
		 */
		time_t clk_sec, rcv_sec;
		uint   clk_frc, rcv_frc;

#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
		
		/* Here we have a high-resolution system clock, and
		 * we're not afraid to use it!
		 */
		struct timespec tmptime;
		if (0 == clock_gettime(CLOCK_REALTIME, &tmptime)) {
			rcv_sec = tmptime.tv_sec;
			rcv_frc = (uint)tmptime.tv_nsec;
		}
		else
#endif
		{
			time(&rcv_sec);
			rcv_frc = (uint)random() % 1000000000u;
		}
		/* add a wobble of ~3.5msec to the clock time */
		clk_sec = rcv_sec;
		clk_frc = rcv_frc + (uint)(random()%7094713 - 3547356);
		/* normalise result -- the SHM driver is picky! */
		while ((int)clk_frc < 0) {
			clk_frc += 1000000000;
			clk_sec -= 1;
		}
		while ((int)clk_frc >= 1000000000) {
			clk_frc -= 1000000000;
			clk_sec += 1;
		}
		
		/* Most 'real' time sources would create a clock
		 * (reference) time stamp where the fraction is zero,
		 * but that's not an actual requirement. So we show how
		 * to deal with the time stamps in general; changing the
		 * behaviour for cases where the fraction of the
		 * clock time is zero should be trivial.
		 */ 
		printf ("writer\n");
		p->mode=0;
		if (!p->valid) {
			p->clockTimeStampSec    = clk_sec;
			p->clockTimeStampUSec   = clk_frc / 1000; /* truncate! */
			p->clockTimeStampNSec   = clk_frc;
			p->receiveTimeStampSec  = rcv_sec;
			p->receiveTimeStampUSec = rcv_frc / 1000; /* truncate! */
			p->receiveTimeStampNSec = rcv_frc;
			printf ("%ld.%09u %ld.%09u\n",
				(long)p->clockTimeStampSec  , p->clockTimeStampNSec  ,
				(long)p->receiveTimeStampSec, p->receiveTimeStampNSec);
			p->valid=1;
		}
		else {
			printf ("p->valid still set\n"); /* not an error! */
		}
		break;
	}
	default:
		break;
	}
	return 0;
}
Beispiel #7
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++;
}
Beispiel #8
0
/* based on minimal daemon code from the daemon-HOWTO */
int main(void) {       
        /* Our process ID and Session ID */
        pid_t pid, sid;       
        /* Fork off the parent process */
        pid = fork();
        if (pid < 0) {
                exit(EXIT_FAILURE);
        }
        /* If we got a good PID, then we can exit the parent process. */
        if (pid > 0) {
                exit(EXIT_SUCCESS);
        }
        /* Change the file mode mask */
        umask(0);
                
                
        /* Create a new SID for the child process */
        sid = setsid();
        if (sid < 0) {
                //syslog(LOG_ERR,"setsid() error. EXIT.");
                exit(EXIT_FAILURE);
        }

        /* Change the current working directory */
        if ((chdir("/")) < 0) {
                /* Log the failure */
                //syslog(LOG_ERR,"chdir() error. EXIT.");
                exit(EXIT_FAILURE);
        }
        
        /* Close out the standard file descriptors */
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        
        /* Daemon-specific initialization goes here */
                /* use syslog */
        setlogmask (LOG_UPTO (LOG_NOTICE));
        openlog ("spec_ptp2ntpd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
        syslog (LOG_NOTICE, "Program started by User %d", getuid());

        // Attach to SPEC shared memory           
        int bar = BASE_BAR0;
        int bus = -1, dev_fn = -1;
        void *card;
        void *map_base;
        card = spec_open(bus, dev_fn);
        if(!card)
        {
            syslog(LOG_ERR, "Can't detect a SPEC card under the given "
                "adress. Make sure a SPEC card is present in your PC, "
                "the driver is loaded and you run the program as root. EXIT.\n");
            exit(1);
        }
        syslog(LOG_NOTICE,"Found SPEC at %x \n",(uint)card);

        map_base = spec_get_base(card, bar);
        if(!map_base || map_base == (void *) -1) {
            syslog(LOG_ERR,"mmap(/dev/mem): %s. EXIT.\n",  strerror(errno));
            syslog(LOG_ERR, "map_base = %x \n",(uint)map_base);
            exit(1);
        }
        syslog(LOG_NOTICE,"map_base = %u \n",(uint)map_base);
        syslog (LOG_NOTICE, "Attached to SPEC SHM at %x", (uint)map_base);
            
        // attach to NTP shared memory
        T = getShmTime(0);
        if (T==0) { /* error */
            syslog(LOG_ERR,"getShmTime() error");
            syslog(LOG_ERR,"EXITING.");
            exit(EXIT_FAILURE);
        } else {
            syslog (LOG_NOTICE, "Attached to NTP SHM at %x", (uint)T);
        }
        
        // initialize
        T->mode=1; // does it matter? set here or by NTP?
        T->leap=0; // ?
        T->precision=-10; //?
        T->nsamples=10; // ?
        shmdt(T); //detach
        
        struct timeval tv;
        uint32_t nsec_cycles, s_lsb,  usecs;
        double cycle = 1/125e6;
        uint32_t nsecs;
                        
        /* The Big Loop */
        while (1) {
            T = getShmTime(0); // attach to shared memory

            gettimeofday(&tv,NULL); // system time-stamp
            
            // WR time
            nsec_cycles = read_mem(map_base, 4 ); // read nanoseconds, in number of 62.5MHz ref cycles
            nsecs = (uint32_t) (cycle*nsec_cycles*1e9);
            usecs = (uint32_t) (cycle*nsec_cycles*1e6);
            s_lsb = read_mem(map_base, 8 ); // read utc lsb
            //s_msb = read_mem(map_base, 12 ); // read utc msb
            
            // clock time
            T->clockTimeStampSec =  s_lsb;
            T->clockTimeStampUSec = usecs; // offset 4 msec, just for fun
            T->clockTimeStampNSec = nsecs;
            
            // time stamp
            T->receiveTimeStampSec  = tv.tv_sec;
            T->receiveTimeStampUSec = tv.tv_usec;
            T->receiveTimeStampNSec = tv.tv_usec*1000;
            
            T->valid = 1;
            T->count += 1;
            
            shmdt(T); // detach, required here?

            syslog (LOG_NOTICE, "WR     time is %d.%09d ", (int)s_lsb,(int)nsecs);
            syslog (LOG_NOTICE, "system time is %d.%06d ", (int)tv.tv_sec,(int)tv.tv_usec);
            sleep(8); // minpoll is 4, so NTP reads every 16s
        }
    spec_close(card);
    closelog();
    exit(EXIT_SUCCESS);
}