change NTP sync code

This commit is contained in:
Marty Kraimer
2005-04-18 13:43:53 +00:00
parent b307ef1746
commit 7009ea2784
2 changed files with 307 additions and 201 deletions

View File

@@ -66,17 +66,12 @@
/* functions used by this driver */
static long TSgetUnixTime(struct timespec*);
static long TSinitClockFromUnix(void);
static long TSgetMasterTime(struct timespec*);
static long TSgetBroadcastAddr(int soc, struct sockaddr*);
static int TSgetSocket(int port, struct sockaddr_in* sin);
static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin);
static void TSsyncServer();
static void TSsyncClient();
static long TSasyncClient();
static long TSsyncTheTime(struct timespec* cts, struct timespec* ts);
static long TSgetData(char* buf, int buf_size, int soc,
struct sockaddr* to_sin, struct sockaddr* from_sin,
struct timespec* round_trip);
static void TSaddStamp( struct timespec* result,
struct timespec* op1, struct timespec* op2);
static void TSwdIncTime();
@@ -96,6 +91,14 @@ static long TSstartSyncClient();
static long TSstartAsyncClient();
static long TSstartStampServer();
static long TSuserGetJunk(int event_number,struct timespec* sp);
/* network utilities*/
static long TSgetBroadcastAddr(int soc, struct sockaddr*);
static int TSgetNtpSocketAddr(struct sockaddr_in *sin);
static int TSgetSocket(int port, struct sockaddr_in* sin);
static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin);
static long TSgetData(char* buf, int buf_size, int soc,
struct sockaddr* to_sin, struct sockaddr* from_sin,
struct timespec* round_trip);
/* event system and time clock functions */
static long (*TSregisterEventHandler)(int Card, void(*func)());
@@ -134,7 +137,8 @@ TSinfo TSdata =
0,NULL,
TS_SYNC_RATE_SEC,TS_CLOCK_RATE_HZ,0,TS_TIME_OUT_MS,0,
TS_MASTER_PORT,TS_SLAVE_PORT,1,0,0,0,0,
NULL, {NULL}, {NULL}
NULL, {NULL}, {NULL},
0,0,10
};
extern char* sysBootLine;
@@ -175,6 +179,7 @@ unsigned long TSepochNtpToUnix(struct timespec* ts)
unsigned long nfssecs = (unsigned long)ts->tv_sec;
unsigned long secs = 0;
if(!TSinitialized) TSinit();
/*If high order bit is not set then nfssecs has overflowed */
if(!(nfssecs & 0x80000000ul)) {
/*secs = nfssecs - TS_1900_TO_VXWORKS_EPOCH + 2**32 */
@@ -281,6 +286,10 @@ long TSreport()
if(TSdata.has_direct_time)
printf("Event system has time directly available\n");
printf("syncReportThreshold %lu milliseconds\n",
TSdata.syncReportThreshold);
printf("syncUnixReportThreshold %lu milliseconds\n",
TSdata.syncUnixReportThreshold);
return 0;
}
@@ -586,7 +595,7 @@ long TSinit(void)
if(TSdata.master_timing_IOC)
{
/* master */
if(TSsetClockFromUnix()<0)
if(TSinitClockFromUnix()<0)
{
/* bad, cannot get time - accessing starts ticking */
struct timespec tp;
@@ -620,7 +629,7 @@ long TSinit(void)
else
{
/* slave */
if(TSsetClockFromUnix()<0)
if(TSinitClockFromUnix()<0)
{
struct timespec tp;
clock_gettime(CLOCK_REALTIME,&tp);
@@ -747,14 +756,13 @@ static void TSwdIncTime() /*increment the time stamp at a 60 Hz rate*/
return;
}
/* TSwdIncTimeSync called at interrupt level! */
static void TSwdIncTimeSync()
{
wdStart(wd,1, (FUNCPTR)TSwdIncTimeSync,NULL);
TSaccurateTimeStamp(&TSdata.event_table[0]);
}
/* following are all interrupt service routines */
/*
TSeventHandler() - receive events from event system; update the event table
@@ -778,6 +786,7 @@ static void TSeventHandler(int Card,int EventNum,unsigned long Ticks)
}
#endif
/* calculate a time stamp from the Tick count */
ts.tv_sec = Ticks / TSdata.clock_hz;
ts.tv_nsec = (Ticks - (ts.tv_sec * TSdata.clock_hz)) * TSdata.clock_conv;
@@ -855,38 +864,18 @@ static void TSerrorHandler(int Card, int ErrorNum)
static long TSgetUnixTime(struct timespec* ts)
{
BOOT_PARAMS bootParms;
unsigned long buf_data,timeValue;
TS_NTP buf_ntp;
struct sockaddr_in sin;
int soc;
char host_addr[BOOT_ADDR_LEN];
int status;
Debug0(2,"in TSgetUnixTime()\n");
if(envGetConfigParam(&EPICS_TS_NTP_INET,BOOT_ADDR_LEN,host_addr)==NULL ||
strlen(host_addr)==0)
{
/* use boot host if the environment variable not set */
bootStringToStruct(sysBootLine,&bootParms);
/* bootParms.had = host IP address */
strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN);
soc = TSgetNtpSocketAddr(&sin);
if(soc<0) {
TSdata.async_type=TS_async_none;
return -1;
}
if( (soc=TSgetSocket(0,&sin)) <0)
{ Debug0(1,"TSgetsocket failed\n"); return -1; }
/* set up for ntp transaction to boot server */
Debug(5,"host addr = %s\n",host_addr);
/* well known registered NTP port - or whatever port they specify */
status = aToIPAddr (host_addr, UDP_NTP_PORT, &sin);
if (status) {
Debug0(2,"bad host name or IP address\n");
TSdata.async_type=TS_async_none;
close(soc);
return -1;
}
TSdata.async_type=TS_async_ntp;
memset(&buf_ntp,0,sizeof(buf_ntp));
buf_ntp.info[0]=0x0b;
@@ -929,6 +918,48 @@ static long TSgetUnixTime(struct timespec* ts)
close(soc);
return 0;
}
/*
TSinitClockFromUnix() - query the time from boot server and set the
vxworks clock.
*/
static long TSinitClockFromUnix(void)
{
struct timespec tp;
int key;
unsigned long ulongtemp;
if(!TSinitialized) TSinit();
Debug0(3,"in TSinitClockFromUnix()\n");
if(TSgetUnixTime(&tp)!=0) return -1;
ulongtemp = TSepochNtpToUnix(&tp);
tp.tv_sec = (long)ulongtemp;
if(MAKE_DEBUG>=9)
printf("set time: %9.9lu.%9.9lu\n", tp.tv_sec,tp.tv_nsec);
/* set the vxWorks clock to the correct time */
if(clock_settime(CLOCK_REALTIME,&tp)<0)
{ Debug0(1,"clock_settime failed\n"); }
/* adjust time to use the EPICS EPOCH of 1990 */
/* this is wrong if leap seconds accounted for */
ulongtemp = TSepochUnixToEpics(&tp);
tp.tv_sec = ulongtemp;
key=intLock();
TSdata.mask |= TS_STAMP_FROM_UNIX;
TSdata.event_table[TSdata.sync_event]=tp;
TSdata.event_table[0]=tp;
intUnlock(key);
if(MAKE_DEBUG>=9)
printf("epics time: %9.9lu.%9.9lu\n",
TSdata.event_table[TSdata.sync_event].tv_sec,
TSdata.event_table[TSdata.sync_event].tv_nsec);
return 0;
}
/*
TSgetMasterTime() - query the master timing IOC for it's current time
@@ -1006,46 +1037,19 @@ static long TSgetMasterTime(struct timespec* tsp)
}
/*
TSsetClockFromUnix() - query the time from boot server and set the
vxworks clock.
TSsetClockFromUnix() - make next sync event get time from unix
*/
long TSsetClockFromUnix(void)
{
struct timespec tp;
int key;
unsigned long ulongtemp;
if(!TSinitialized) TSinit();
Debug0(3,"in TSsetClockFromUnix()\n");
if(TSgetUnixTime(&tp)!=0) return -1;
ulongtemp = TSepochNtpToUnix(&tp);
tp.tv_sec = (long)ulongtemp;
if(MAKE_DEBUG>=9)
printf("set time: %9.9lu.%9.9lu\n", tp.tv_sec,tp.tv_nsec);
/* set the vxWorks clock to the correct time */
if(clock_settime(CLOCK_REALTIME,&tp)<0)
{ Debug0(1,"clock_settime failed\n"); }
/* adjust time to use the EPICS EPOCH of 1990 */
/* this is wrong if leap seconds accounted for */
ulongtemp = TSepochUnixToEpics(&tp);
tp.tv_sec = ulongtemp;
/* set the EPICS event time table sync entry (current time) */
key=intLock();
TSdata.event_table[TSdata.sync_event]=tp;
TSdata.event_table[0]=tp;
intUnlock(key);
if(MAKE_DEBUG>=9)
printf("epics time: %9.9lu.%9.9lu\n",
TSdata.event_table[TSdata.sync_event].tv_sec,
TSdata.event_table[TSdata.sync_event].tv_nsec);
TSdata.mask |= TS_STAMP_FROM_UNIX;
return 0;
}
long TSsetSyncReportThreshold(
unsigned long syncMilliseconds,unsigned long syncUnixMilliseconds)
{
TSdata.syncReportThreshold = syncMilliseconds;
TSdata.syncUnixReportThreshold = syncUnixMilliseconds;
return 0;
}
@@ -1078,83 +1082,6 @@ static long TSsetClockFromMaster()
}
/**************************************************************************/
/* broadcast socket creation utilites */
/**************************************************************************/
/*
TSgetBroadcastSocket() - return a broadcast socket for a port, return
a sockaddr also.
*/
static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin)
{
int on=1;
int soc;
sin->sin_port=htons(port);
sin->sin_family=AF_INET;
sin->sin_addr.s_addr=htonl(INADDR_ANY);
if( (soc=socket(AF_INET,SOCK_DGRAM,0)) < 0 )
{ perror("socket create failed"); return -1; }
setsockopt(soc,SOL_SOCKET,SO_BROADCAST,(char*)&on,sizeof(on));
if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 )
{ perror("socket bind failed"); close(soc); return -1; }
if( TSgetBroadcastAddr(soc,(struct sockaddr*)sin) < 0 ) return -1;
return soc;
}
/*
TSgetBroadcastAddr() - Determine the broadcast address, this is
directly from the Sun Network Programmer's guide.
*/
static long TSgetBroadcastAddr(int soc, struct sockaddr* sin)
{
struct ifconf ifc;
struct ifreq* ifr;
struct ifreq* save;
char buf[BUFSIZ];
int tot,i;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if(ioctl(soc,SIOCGIFCONF,(int)&ifc) < 0)
{ perror("ioctl SIOCGIFCONF failed"); return -1; }
ifr = ifc.ifc_req;
tot = ifc.ifc_len/sizeof(struct ifreq);
save=(struct ifreq*)NULL;
i=0;
do
{
if(ifr->ifr_addr.sa_family==AF_INET)
{
if(ioctl(soc,SIOCGIFFLAGS,(int)ifr)<0)
{ perror("ioctl SIOCGIFFLAGS failed"); return -1; }
if( (ifr->ifr_flags&IFF_UP) &&
!(ifr->ifr_flags&IFF_LOOPBACK) &&
(ifr->ifr_flags&IFF_BROADCAST))
{ save=ifr; }
}
/*ifreq_size is defined in osiSock.h*/
ifr = (struct ifreq*)((char *)ifr + ifreq_size(ifr));
} while( !save && ++i<tot );
if(save)
{
if(ioctl(soc,SIOCGIFBRDADDR,(int)save)<0)
{ perror("ioctl SIOCGIFBRDADDR failed"); return -1; }
memcpy((char*)sin,(char*)&save->ifr_broadaddr,
sizeof(save->ifr_broadaddr));
}
else
{ Debug0(1,"no broadcast address found\n"); return -1; }
return 0;
}
/**************************************************************************/
/* time stamp utility routines */
/**************************************************************************/
@@ -1220,16 +1147,22 @@ long TSstartSyncServer()
static void TSsyncServer()
{
TSstampTrans stran;
struct sockaddr_in sin;
int soc;
struct sockaddr_in sinBroadcast;
int socBroadcast;
struct sockaddr_in sinNtp;
int socNtp;
unsigned long mask;
int setStampFromUnix;
if( (soc=TSgetBroadcastSocket(0,&sin)) <0)
if( (socBroadcast=TSgetBroadcastSocket(0,&sinBroadcast)) <0)
{ Debug0(1,"TSgetBroadcastSocket failed\n"); return; }
sin.sin_port = htons(TSdata.slave_port);
sinBroadcast.sin_port = htons(TSdata.slave_port);
stran.type=(TStype)htonl(TS_sync_msg);
stran.magic=htonl(TS_MAGIC);
stran.sync_rate=htonl(TSdata.sync_rate);
stran.clock_hz=htonl(TSdata.clock_hz);
socNtp = TSgetNtpSocketAddr(&sinNtp);
if(socNtp<0) TSprintf("TSsyncServer TSgetNtpSocketAddr failed\n");
while(1)
{
/* wait for a sync to occur */
@@ -1251,17 +1184,71 @@ static void TSsyncServer()
TSdata.event_table[TSdata.sync_event].tv_sec=ts.tv_sec;
intUnlock(key);
}
/* Use while so that errors can break out of while*/
setStampFromUnix = 0;
while(TSdata.mask & TS_STAMP_FROM_UNIX) {
TS_NTP buf_ntp;
struct timespec tp;
unsigned long ulongtemp;
int key;
unsigned long ticksStart,ticksEnd;
if(socNtp<0) {
TSprintf("TSsyncServer cant contact NTP server\n");
break;
}
TSgetTicks(0,&ticksStart);
memset(&buf_ntp,0,sizeof(buf_ntp));
buf_ntp.info[0]=0x0b;
if(TSgetData((char*)&buf_ntp,sizeof(buf_ntp),socNtp,
(struct sockaddr*)&sinNtp,0,0) < 0) {
TSprintf("TSsyncServer TSgetData for NTP failed\n");
break;
}
tp.tv_sec = ntohl(buf_ntp.transmit_ts.tv_sec);
ulongtemp = ntohl(buf_ntp.transmit_ts.tv_nsec);
tp.tv_nsec = TSfractionToNano(ulongtemp);
ulongtemp = TSepochNtpToUnix(&tp);
tp.tv_sec = (long)ulongtemp;
TSgetTicks(0,&ticksEnd);
if(ticksEnd<ticksStart) {
TSprintf("TSsyncServer clock overflow\n");
break;
}
if((ticksEnd-ticksStart) > TS_MAX_TICKS_GET_NTP) {
TSprintf("TSsyncServer NTP TSgetData took %lu clock ticks\n",
(ticksEnd - ticksStart));
break;
}
setStampFromUnix = 1;
if(clock_settime(CLOCK_REALTIME,&tp)<0) {
TSprintf("TSsyncServer clock_settime failed\n");
}
ulongtemp = TSepochUnixToEpics(&tp);
tp.tv_sec = ulongtemp;
key=intLock();
TSdata.event_table[TSdata.sync_event]=tp;
TSdata.event_table[0]=tp;
intUnlock(key);
break;
}
stran.master_time.tv_sec=
htonl(TSdata.event_table[TSdata.sync_event].tv_sec);
stran.master_time.tv_nsec=
htonl(TSdata.event_table[TSdata.sync_event].tv_nsec);
if(sendto(soc,(char*)&stran,sizeof(stran),0,
(struct sockaddr*)&sin,sizeof(sin))<0)
mask = TSdata.mask;
if(!setStampFromUnix) mask &= ~TS_STAMP_FROM_UNIX;
stran.mask = htonl(mask);
if(setStampFromUnix)TSdata.mask &= ~TS_STAMP_FROM_UNIX;
stran.syncReportThreshold = htonl(TSdata.syncReportThreshold);
stran.syncUnixReportThreshold = htonl(TSdata.syncUnixReportThreshold);
if(sendto(socBroadcast,(char*)&stran,sizeof(stran),0,
(struct sockaddr*)&sinBroadcast,sizeof(sinBroadcast))<0)
{ perror("sendto failed"); }
Debug(8,"time send secs = %lu\n",stran.master_time.tv_sec);
Debug(8,"time send nsecs = %lu\n",stran.master_time.tv_nsec);
}
close(soc);
close(socBroadcast);
return;
}
@@ -1285,40 +1272,19 @@ long TSstartAsyncClient()
*/
static long TSasyncClient()
{
BOOT_PARAMS bootParms;
TSstampTrans stran;
TS_NTP buf_ntp;
struct sockaddr_in sin_unix,sin_bc,sin_master;
int count,soc_unix,soc_master,soc_bc,buf_size;
struct timespec ts,diff_time,cts,curr_time;
unsigned long nsecs;
char host_addr[BOOT_ADDR_LEN];
int status;
Debug0(2,"in TSasyncClient()\n");
/* could open two sockets here, one to contact unix, one to find master */
/*------socket for unix server----------*/
if(envGetConfigParam(&EPICS_TS_NTP_INET,BOOT_ADDR_LEN,host_addr)==NULL
|| strlen(host_addr)==0)
{
/* use boot host if the environment variable not set */
bootStringToStruct(sysBootLine,&bootParms);
/* bootParms.had = host IP address */
strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN);
soc_unix = TSgetNtpSocketAddr(&sin_unix);
if(soc_unix<0) {
printf("TSasyncClient TSgetNtpSocketAddr failed\n");
return -1;
}
if( (soc_unix=TSgetSocket(0,&sin_unix)) <0)
{ Debug0(1,"TSgetSocket failed\n"); return -1; }
status = aToIPAddr (host_addr, UDP_NTP_PORT, &sin_unix);
if (status) {
Debug0(2,"bad host name or IP address\n");
close (soc_unix);
return -1;
}
/*------socket for finding master----------*/
if( (soc_bc=TSgetBroadcastSocket(0,&sin_bc)) <0)
{ Debug0(1,"TSgetBroadcastSocket failed\n"); close(soc_unix); return -1; }
@@ -1463,6 +1429,7 @@ static void TSsyncClient()
struct sockaddr fs;
int num,mlen,soc,fl;
struct timespec mast_time;
struct timespec mytime;
fd_set readfds;
int key;
@@ -1479,6 +1446,12 @@ static void TSsyncClient()
{ Debug0(1,"TSgetSocket failed\n"); return; }
while(1)
{
unsigned long mask;
unsigned long syncReportThreshold;
unsigned long syncUnixReportThreshold;
double reportThreshold;
double unixReportThreshold;
FD_ZERO(&readfds);
FD_SET(soc,&readfds);
@@ -1489,6 +1462,7 @@ static void TSsyncClient()
if(num==ERROR) { perror("select failed"); continue; }
fl = sizeof(fs);
memset(&stran,0,sizeof(stran));
if((mlen=recvfrom(soc,(char*)&stran,sizeof(stran),0,&fs,&fl))<0)
{ perror("recvfrom failed"); continue; }
@@ -1497,30 +1471,44 @@ static void TSsyncClient()
TSprintf("TSsyncClient: invalid packet received\n");
continue;
}
/* get the master time out of packet */
mask = ntohl(stran.mask);
syncReportThreshold = ntohl(stran.syncReportThreshold);
syncUnixReportThreshold = ntohl(stran.syncUnixReportThreshold);
if(TSdata.syncReportThreshold>syncReportThreshold)
syncReportThreshold = TSdata.syncReportThreshold;
if(TSdata.syncUnixReportThreshold>syncUnixReportThreshold)
syncUnixReportThreshold = TSdata.syncUnixReportThreshold;
mast_time.tv_sec=ntohl(stran.master_time.tv_sec);
mast_time.tv_nsec=ntohl(stran.master_time.tv_nsec);
Debug0(6,"Received sync request from master\n");
if(MAKE_DEBUG>=8)
{
printf("time received=%9.9lu.%9.9lu\n",
mast_time.tv_sec,mast_time.tv_nsec);
}
reportThreshold = (double)syncReportThreshold/1000.0;
unixReportThreshold = (double)syncUnixReportThreshold/1000.0;
mytime = TSdata.event_table[TSdata.sync_event];
/* verify the sync event with this one */
if( TSdata.event_table[TSdata.sync_event].tv_sec!=mast_time.tv_sec
|| TSdata.event_table[TSdata.sync_event].tv_nsec!=mast_time.tv_nsec)
if(mytime.tv_sec!=mast_time.tv_sec || mytime.tv_nsec!=mast_time.tv_nsec)
{
TSprintf("sync Slave not in sync: %lu,%lu != %lu,%lu\n",
TSdata.event_table[TSdata.sync_event].tv_sec,
TSdata.event_table[TSdata.sync_event].tv_nsec,
mast_time.tv_sec, mast_time.tv_nsec);
int dir;
struct timespec diffFromMaster;
double timeDiff;
dir = TScalcDiff(&mytime, &mast_time,&diffFromMaster);
timeDiff = diffFromMaster.tv_sec;
timeDiff += diffFromMaster.tv_nsec/(double)TS_BILLION;
if(dir<0) timeDiff = -timeDiff;
key=intLock();
TSdata.event_table[TSdata.sync_event].tv_sec=mast_time.tv_sec;
TSdata.event_table[TSdata.sync_event].tv_nsec=mast_time.tv_nsec;
intUnlock(key);
if(mask&TS_STAMP_FROM_UNIX) {
if(fabs(timeDiff) >= unixReportThreshold) {
TSprintf("TSasynClient: Time checked with NTP via master, "
"adjusted by %f seconds.\n",timeDiff);
}
} else {
if(fabs(timeDiff) >= reportThreshold) {
TSprintf("TSasynClient: Time checked with master, "
"adjusted by %f seconds\n",timeDiff);
}
}
}
}
close(soc);
@@ -1605,12 +1593,16 @@ long TScurrentTimeStamp(struct timespec* sp)
}
/* get the current time from time stamp support software */
/* can be called from interrupt level !!*/
long TSaccurateTimeStamp(struct timespec* sp)
{
struct timespec ts;
unsigned long ticks;
if(!TSinitialized) TSinit();
if(!TSinitialized) {
logMsg("TSaccurateTimeStamp called but !TSinitialized\n",0,0,0,0,0,0);
return -1;
}
if(TSdata.has_direct_time==1)
{
TSgetTime(sp);
@@ -1619,7 +1611,6 @@ long TSaccurateTimeStamp(struct timespec* sp)
TSgetTicks(0,&ticks); /* add in the board time */
*sp = TSdata.event_table[TSdata.sync_event];
/* calculate a time stamp from the tick count */
ts.tv_sec = ticks / TSdata.clock_hz;
ts.tv_nsec=(ticks-(ts.tv_sec*TSdata.clock_hz))*TSdata.clock_conv;
@@ -1703,9 +1694,83 @@ static long TScalcDiff(struct timespec* a,
return dir;
}
/**************************************************************************/
/* more routines for managing sockets */
/**************************************************************************/
/* network utilities*/
/*
TSgetBroadcastAddr() - Determine the broadcast address, this is
directly from the Sun Network Programmer's guide.
*/
static long TSgetBroadcastAddr(int soc, struct sockaddr* sin)
{
struct ifconf ifc;
struct ifreq* ifr;
struct ifreq* save;
char buf[BUFSIZ];
int tot,i;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if(ioctl(soc,SIOCGIFCONF,(int)&ifc) < 0)
{ perror("ioctl SIOCGIFCONF failed"); return -1; }
ifr = ifc.ifc_req;
tot = ifc.ifc_len/sizeof(struct ifreq);
save=(struct ifreq*)NULL;
i=0;
do
{
if(ifr->ifr_addr.sa_family==AF_INET)
{
if(ioctl(soc,SIOCGIFFLAGS,(int)ifr)<0)
{ perror("ioctl SIOCGIFFLAGS failed"); return -1; }
if( (ifr->ifr_flags&IFF_UP) &&
!(ifr->ifr_flags&IFF_LOOPBACK) &&
(ifr->ifr_flags&IFF_BROADCAST))
{ save=ifr; }
}
/*ifreq_size is defined in osiSock.h*/
ifr = (struct ifreq*)((char *)ifr + ifreq_size(ifr));
} while( !save && ++i<tot );
if(save)
{
if(ioctl(soc,SIOCGIFBRDADDR,(int)save)<0)
{ perror("ioctl SIOCGIFBRDADDR failed"); return -1; }
memcpy((char*)sin,(char*)&save->ifr_broadaddr,
sizeof(save->ifr_broadaddr));
}
else
{ Debug0(1,"no broadcast address found\n"); return -1; }
return 0;
}
static int TSgetNtpSocketAddr(struct sockaddr_in *sin)
{
char host_addr[BOOT_ADDR_LEN];
BOOT_PARAMS bootParms;
int status;
int soc;
if(envGetConfigParam(&EPICS_TS_NTP_INET,BOOT_ADDR_LEN,host_addr)==NULL
|| strlen(host_addr)==0) {
/* use boot host if the environment variable not set */
bootStringToStruct(sysBootLine,&bootParms);
/* bootParms.had = host IP address */
strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN);
}
if( (soc=TSgetSocket(0,sin)) <0) {
TSprintf("TSgetNtpSocketAddrn TSgetsocket failed\n");
return -1;
}
/* well known registered NTP port - or whatever port they specify */
status = aToIPAddr (host_addr, UDP_NTP_PORT, sin);
if (status) {
TSprintf("TSgetNtpSocketAddr aToIPAddr failed\n");
close(soc);
return -1;
}
return soc;
}
/* get a UDP socket for a port, return a sockaddr for it. */
static int TSgetSocket(int port, struct sockaddr_in* sin)
@@ -1724,6 +1789,30 @@ static int TSgetSocket(int port, struct sockaddr_in* sin)
return soc;
}
/*
TSgetBroadcastSocket() - return a broadcast socket for a port, return
a sockaddr also.
*/
static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin)
{
int on=1;
int soc;
sin->sin_port=htons(port);
sin->sin_family=AF_INET;
sin->sin_addr.s_addr=htonl(INADDR_ANY);
if( (soc=socket(AF_INET,SOCK_DGRAM,0)) < 0 )
{ perror("socket create failed"); return -1; }
setsockopt(soc,SOL_SOCKET,SO_BROADCAST,(char*)&on,sizeof(on));
if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 )
{ perror("socket bind failed"); close(soc); return -1; }
if( TSgetBroadcastAddr(soc,(struct sockaddr*)sin) < 0 ) return -1;
return soc;
}
/* attempt to get data from a socket after sending a request to it.
0ptionally return round trip time and the sockaddr of the responsedent.
*/
@@ -1813,6 +1902,7 @@ void TSprintRealTime()
{
struct timespec tp;
if(!TSinitialized) TSinit();
TSgetTime(&tp);
printf("real time clock = %lu,%lu\n",tp.tv_sec,tp.tv_nsec);
printf("EPICS clock = %lu,%lu\n",
@@ -1826,6 +1916,7 @@ void TSprintTimeStamp(int num)
{
struct timespec tp;
if(!TSinitialized) TSinit();
TSgetTimeStamp(num,&tp);
printf("event %d occurred: %lu.%lu\n",num,tp.tv_sec,tp.tv_nsec);
return;
@@ -1836,6 +1927,7 @@ void TSprintCurrentTime()
{
struct timespec tp;
if(!TSinitialized) TSinit();
TScurrentTimeStamp(&tp);
printf("Current Event System time: %lu.%lu\n",tp.tv_sec,tp.tv_nsec);
TSaccurateTimeStamp(&tp);
@@ -1848,6 +1940,7 @@ void TSprintUnixTime()
{
struct timespec ts;
if(!TSinitialized) TSinit();
if(TSgetUnixTime(&ts)!=0)
{
printf("Could not get Unix time\n");
@@ -1862,6 +1955,7 @@ void TSprintMasterTime()
{
struct timespec ts;
if(!TSinitialized) TSinit();
if(TSgetMasterTime(&ts)!=0)
{
printf("Could not get Unix time\n");

View File

@@ -39,6 +39,10 @@
#define TS_TIME_OUT_MS 250
#define TS_SECS_ASYNC_TRY_MASTER (60*5) /* every five minutes */
#define TS_SECS_SYNC_TRY_MASTER (60*1) /* every one minute */
#define TS_MAX_TICKS_GET_NTP 10
/*mask values for TSstampTrans.mask and TSinfo.mask */
#define TS_STAMP_FROM_UNIX 0x0001
#define UDP_TIME_PORT 37
#define UDP_NTP_PORT 123
@@ -78,6 +82,9 @@ struct TSstampTransStruct {
struct timespec unix_time; /* time using 1900 epoch */
unsigned long sync_rate; /* master sends sync at this rate */
unsigned long clock_hz; /* master clock this frequency (tick rate) */
unsigned long mask; /*extra info*/
unsigned long syncReportThreshold; /*for sync errors*/
unsigned long syncUnixReportThreshold; /*for TS_STAMP_FROM_UNIXerrors*/
};
typedef struct TSstampTransStruct TSstampTrans;
@@ -106,6 +113,9 @@ struct TSinfoStruct {
struct sockaddr hunt; /* broadcast address info */
struct sockaddr master; /* socket info for contacting master */
unsigned long mask; /*extra info*/
unsigned long syncReportThreshold; /*for sync errors*/
unsigned long syncUnixReportThreshold; /*for TS_STAMP_FROM_UNIXerrors*/
};
typedef struct TSinfoStruct TSinfo;
@@ -127,6 +137,8 @@ TS_EXTERN void TSconfigure(int master, int sync_rate_sec, int clock_rate_hz,
int master_port, int slave_port,
unsigned long millisecond_request_time_out, int type);
TS_EXTERN long TSsetClockFromUnix(void);
TS_EXTERN long TSsetSyncReportThreshold(
unsigned long syncMilliseconds,unsigned long syncUnixMilliseconds);
#ifndef TS_DRIVER
TS_EXTERN TSinfo TSdata;