timesync.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <ip.h>
  5. #include <mp.h>
  6. /* nanosecond times */
  7. #define SEC 1000000000LL
  8. #define MIN (60LL*SEC)
  9. #define HOUR (60LL*MIN)
  10. #define DAY (24LL*HOUR)
  11. enum {
  12. Fs,
  13. Rtc,
  14. Ntp,
  15. Utc,
  16. Gps,
  17. HZAvgSecs= 3*60, /* target averaging period for the frequency in seconds */
  18. MinSampleSecs= 60, /* minimum sampling time in seconds */
  19. };
  20. char *dir = "/tmp"; // directory sample files live in
  21. char *logfile = "timesync";
  22. char *timeserver;
  23. char *Rootid;
  24. int utcfil;
  25. int gpsfil;
  26. int debug;
  27. int impotent;
  28. int logging;
  29. int type;
  30. int gmtdelta; // rtc+gmtdelta = gmt
  31. uvlong avgerr;
  32. // ntp server info
  33. int stratum = 14;
  34. vlong mydisp, rootdisp;
  35. vlong mydelay, rootdelay;
  36. vlong avgdelay;
  37. vlong lastutc;
  38. uchar rootid[4];
  39. char *sysid;
  40. int myprec;
  41. // list of time samples
  42. typedef struct Sample Sample;
  43. struct Sample
  44. {
  45. Sample *next;
  46. uvlong ticks;
  47. vlong ltime;
  48. vlong stime;
  49. };
  50. // ntp packet
  51. typedef struct NTPpkt NTPpkt;
  52. struct NTPpkt
  53. {
  54. uchar mode;
  55. uchar stratum;
  56. uchar poll;
  57. uchar precision;
  58. uchar rootdelay[4];
  59. uchar rootdisp[4];
  60. uchar rootid[4];
  61. uchar refts[8];
  62. uchar origts[8]; // departed client
  63. uchar recvts[8]; // arrived at server
  64. uchar xmitts[8]; // departed server
  65. uchar keyid[4];
  66. uchar digest[16];
  67. };
  68. // ntp server
  69. typedef struct NTPserver NTPserver;
  70. struct NTPserver
  71. {
  72. NTPserver *next;
  73. char *name;
  74. uchar stratum;
  75. uchar precision;
  76. vlong rootdelay;
  77. vlong rootdisp;
  78. vlong rtt;
  79. vlong dt;
  80. };
  81. NTPserver *ntpservers;
  82. enum
  83. {
  84. NTPSIZE= 48, // basic ntp packet
  85. NTPDIGESTSIZE= 20, // key and digest
  86. };
  87. // error bound of last sample
  88. ulong ε;
  89. static void addntpserver(char *name);
  90. static int adjustperiod(vlong diff, vlong accuracy, int secs);
  91. static void background(void);
  92. static int caperror(vlong dhz, int tsecs, vlong taccuracy);
  93. static long fstime(void);
  94. static int gettime(vlong *nsec, uvlong *ticks, uvlong *hz); // returns time, ticks, hz
  95. static int getclockprecision(vlong);
  96. static vlong gpssample(void);
  97. static void hnputts(void *p, vlong nsec);
  98. static void hnputts(void *p, vlong nsec);
  99. static void inittime(void);
  100. static vlong nhgetts(void *p);
  101. static vlong nhgetts(void *p);
  102. static void ntpserver(char*);
  103. static vlong ntpsample(void);
  104. static int ntptimediff(NTPserver *ns);
  105. static int openfreqfile(void);
  106. static vlong readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz);
  107. static long rtctime(void);
  108. static vlong sample(long (*get)(void));
  109. static void setpriority(void);
  110. static void setrootid(char *d);
  111. static void settime(vlong now, uvlong hz, vlong delta, int n); // set time, hz, delta, period
  112. static vlong utcsample(void);
  113. static uvlong vabs(vlong);
  114. static uvlong whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz, vlong dt, vlong ticks, vlong period);
  115. static void writefreqfile(int fd, vlong hz, int secs, vlong diff);
  116. // ((1970-1900)*365 + 17/*leap days*/)*24*60*60
  117. #define EPOCHDIFF 2208988800UL
  118. void
  119. main(int argc, char **argv)
  120. {
  121. int i;
  122. int secs; // sampling period
  123. int tsecs; // temporary sampling period
  124. int t, fd;
  125. Sample *s, *x, *first, **l;
  126. vlong diff, accuracy, taccuracy;
  127. uvlong hz, minhz, maxhz, period, nhz;
  128. char *servenet[4];
  129. int nservenet;
  130. char *a;
  131. Tm tl, tg;
  132. type = Fs; // by default, sync with the file system
  133. debug = 0;
  134. accuracy = 1000000LL; // default accuracy is 1 millisecond
  135. nservenet = 0;
  136. tsecs = secs = MinSampleSecs;
  137. timeserver = "";
  138. ARGBEGIN{
  139. case 'a':
  140. a = ARGF();
  141. if(a == nil)
  142. sysfatal("bad accuracy specified");
  143. accuracy = strtoll(a, 0, 0); // accuracy specified in ns
  144. if(accuracy <= 1LL)
  145. sysfatal("bad accuracy specified");
  146. break;
  147. case 'f':
  148. type = Fs;
  149. stratum = 2;
  150. break;
  151. case 'r':
  152. type = Rtc;
  153. stratum = 0;
  154. break;
  155. case 'U':
  156. type = Utc;
  157. stratum = 1;
  158. break;
  159. case 'G':
  160. type = Gps;
  161. stratum = 1;
  162. break;
  163. case 'n':
  164. type = Ntp;
  165. break;
  166. case 'D':
  167. debug = 1;
  168. break;
  169. case 'd':
  170. dir = ARGF();
  171. break;
  172. case 'L':
  173. //
  174. // Assume time source in local time rather than GMT.
  175. // Calculate difference so that rtctime can return GMT.
  176. // This is useful with the rtc on PC's that run Windows
  177. // since Windows keeps the local time in the rtc.
  178. //
  179. t = time(0);
  180. tl = *localtime(t);
  181. tg = *gmtime(t);
  182. // if the years are different, we're at most a day off, so just rewrite
  183. if(tl.year < tg.year){
  184. tg.year--;
  185. tg.yday = tl.yday + 1;
  186. }else if(tl.year > tg.year){
  187. tl.year--;
  188. tl.yday = tg.yday+1;
  189. }
  190. assert(tl.year == tg.year);
  191. tg.sec -= tl.sec;
  192. tg.min -= tl.min;
  193. tg.hour -= tl.hour;
  194. tg.yday -= tl.yday;
  195. gmtdelta = tg.sec+60*(tg.min+60*(tg.hour+tg.yday*24));
  196. assert(abs(gmtdelta) <= 24*60*60);
  197. break;
  198. case 'i':
  199. impotent = 1;
  200. break;
  201. case 'I':
  202. Rootid = ARGF();
  203. break;
  204. case 's':
  205. if(nservenet >= nelem(servenet))
  206. sysfatal("too many networks to serve on");
  207. a = ARGF();
  208. if(a == nil)
  209. sysfatal("must specify network to serve on");
  210. servenet[nservenet++] = a;
  211. break;
  212. case 'l':
  213. logging = 1;
  214. break;
  215. case 'S':
  216. a = ARGF();
  217. if(a == nil)
  218. sysfatal("bad stratum specified");
  219. stratum = strtoll(a, 0, 0);
  220. break;
  221. }ARGEND;
  222. fmtinstall('E', eipfmt);
  223. fmtinstall('I', eipfmt);
  224. fmtinstall('V', eipfmt);
  225. sysid = getenv("sysname");
  226. // detach from the current namespace
  227. if(debug)
  228. rfork(RFNAMEG);
  229. switch(type){
  230. case Utc:
  231. if(argc > 0)
  232. timeserver = argv[0];
  233. else
  234. sysfatal("bad time source");
  235. break;
  236. case Gps:
  237. if(argc > 0)
  238. timeserver = argv[0];
  239. else
  240. timeserver = "/mnt/gps/time";
  241. break;
  242. case Fs:
  243. if(argc > 0)
  244. timeserver = argv[0];
  245. else
  246. timeserver = "/srv/boot";
  247. break;
  248. case Ntp:
  249. if(argc > 0){
  250. for(i = 0; i <argc; i++)
  251. addntpserver(argv[i]);
  252. } else {
  253. addntpserver("$ntp");
  254. }
  255. break;
  256. }
  257. setpriority();
  258. // figure out our time interface and initial frequency
  259. inittime();
  260. gettime(0, 0, &hz);
  261. minhz = hz/10;
  262. maxhz = hz*10;
  263. myprec = getclockprecision(hz);
  264. // convert the accuracy from nanoseconds to ticks
  265. taccuracy = hz*accuracy/SEC;
  266. //
  267. // bind in clocks
  268. //
  269. switch(type){
  270. case Fs:
  271. fd = open(timeserver, ORDWR);
  272. if(fd < 0)
  273. sysfatal("opening %s: %r\n", timeserver);
  274. if(amount(fd, "/n/boot", MREPL, "") < 0)
  275. sysfatal("mounting %s: %r\n", timeserver);
  276. close(fd);
  277. break;
  278. case Rtc:
  279. bind("#r", "/dev", MAFTER);
  280. if(access("/dev/rtc", AREAD) < 0)
  281. sysfatal("accessing /dev/rtc: %r\n");
  282. break;
  283. case Utc:
  284. fd = open(timeserver, OREAD);
  285. if(fd < 0)
  286. sysfatal("opening %s: %r\n", timeserver);
  287. utcfil = fd;
  288. break;
  289. case Gps:
  290. fd = open(timeserver, OREAD);
  291. if(fd < 0)
  292. sysfatal("opening %s: %r\n", timeserver);
  293. gpsfil = fd;
  294. break;
  295. }
  296. //
  297. // start a local ntp server(s)
  298. //
  299. for(i = 0; i < nservenet; i++){
  300. switch(rfork(RFPROC|RFFDG|RFMEM|RFNOWAIT)){
  301. case -1:
  302. sysfatal("forking: %r");
  303. break;
  304. case 0:
  305. ntpserver(servenet[i]);
  306. _exits(0);
  307. break;
  308. default:
  309. break;
  310. }
  311. }
  312. // get the last known frequency from the file
  313. fd = openfreqfile();
  314. hz = readfreqfile(fd, hz, minhz, maxhz);
  315. // this is the main loop. it gets a sample, adjusts the
  316. // clock and computes a sleep period until the next loop.
  317. // we balance frequency drift against the length of the
  318. // period to avoid blowing the accuracy limit.
  319. first = nil;
  320. l = &first;
  321. avgerr = accuracy>>1;
  322. for(;; background(),sleep(tsecs*(1000))){
  323. s = mallocz(sizeof(*s), 1);
  324. diff = 0;
  325. // get times for this sample
  326. ε = ~0;
  327. switch(type){
  328. case Fs:
  329. s->stime = sample(fstime);
  330. break;
  331. case Rtc:
  332. s->stime = sample(rtctime);
  333. break;
  334. case Utc:
  335. s->stime = utcsample();
  336. if(s->stime == 0LL){
  337. if(logging)
  338. syslog(0, logfile, "no sample");
  339. free(s);
  340. if (secs > 60 * 15)
  341. tsecs = 60*15;
  342. continue;
  343. }
  344. break;
  345. case Ntp:
  346. diff = ntpsample();
  347. if(diff == 0LL){
  348. if(logging)
  349. syslog(0, logfile, "no sample");
  350. free(s);
  351. if(secs > 60*15)
  352. tsecs = 60*15;
  353. continue;
  354. }
  355. break;
  356. case Gps:
  357. diff = gpssample();
  358. if(diff == 0LL){
  359. if(logging)
  360. syslog(0, logfile, "no sample");
  361. free(s);
  362. if(secs > 60*15)
  363. tsecs = 60*15;
  364. continue;
  365. }
  366. }
  367. // use fastest method to read local clock and ticks
  368. gettime(&s->ltime, &s->ticks, 0);
  369. if(type == Ntp || type == Gps)
  370. s->stime = s->ltime + diff;
  371. // if the sample was bad, ignore it
  372. if(s->stime < 0){
  373. free(s);
  374. continue;
  375. }
  376. // reset local time
  377. diff = s->stime - s->ltime;
  378. if(diff > 10*SEC || diff < -10*SEC){
  379. // we're way off, just set the time
  380. secs = MinSampleSecs;
  381. settime(s->stime, 0, 0, 0);
  382. } else {
  383. // keep a running average of the error.
  384. avgerr = (avgerr>>1) + (vabs(diff)>>1);
  385. // the time to next sample depends on how good or
  386. // bad we're doing.
  387. tsecs = secs = adjustperiod(diff, accuracy, secs);
  388. // work off the fixed difference. This is done
  389. // by adding a ramp to the clock. Each 100th of a
  390. // second (or so) the kernel will add diff/(4*secs*100)
  391. // to the clock. we only do 1/4 of the difference per
  392. // period to dampen any measurement noise.
  393. //
  394. // any difference greater than ε we work off during the
  395. // sampling period.
  396. if(abs(diff) > ε){
  397. if(diff > 0)
  398. settime(-1, 0, diff-((3*ε)/4), secs);
  399. else
  400. settime(-1, 0, diff+((3*ε)/4), secs);
  401. } else
  402. settime(-1, 0, diff, 4*secs);
  403. }
  404. if(debug)
  405. fprint(2, "δ %lld avgδ %lld f %lld\n", diff, avgerr, hz);
  406. // dump old samples (keep at least one)
  407. while(first != nil){
  408. if(first->next == nil)
  409. break;
  410. if(s->stime - first->next->stime < DAY)
  411. break;
  412. x = first;
  413. first = first->next;
  414. free(x);
  415. }
  416. // The sampling error is limited by the total error. If
  417. // we make sure the sampling period is at least 16 million
  418. // times the average error, we should calculate a frequency
  419. // with on average a 1e-7 error.
  420. //
  421. // So that big hz changes don't blow our accuracy requirement,
  422. // we shorten the period to make sure that δhz*secs will be
  423. // greater than the accuracy limit.
  424. period = avgerr<<24;
  425. for(x = first; x != nil; x = x->next){
  426. if(s->stime - x->stime < period)
  427. break;
  428. if(x->next == nil || s->stime - x->next->stime < period)
  429. break;
  430. }
  431. if(x != nil){
  432. nhz = whatisthefrequencykenneth(
  433. hz, minhz, maxhz,
  434. s->stime - x->stime,
  435. s->ticks - x->ticks,
  436. period);
  437. tsecs = caperror(vabs(nhz-hz), tsecs, taccuracy);
  438. hz = nhz;
  439. writefreqfile(fd, hz, (s->stime - x->stime)/SEC, diff);
  440. }
  441. // add current sample to list.
  442. *l = s;
  443. l = &s->next;
  444. if(logging)
  445. syslog(0, logfile, "δ %lld avgδ %lld hz %lld",
  446. diff, avgerr, hz);
  447. }
  448. }
  449. //
  450. // adjust the sampling period with some histeresis
  451. //
  452. static int
  453. adjustperiod(vlong diff, vlong accuracy, int secs)
  454. {
  455. uvlong absdiff;
  456. absdiff = vabs(diff);
  457. if(absdiff < (accuracy>>1))
  458. secs += 60;
  459. else if(absdiff > accuracy)
  460. secs >>= 1;
  461. else
  462. secs -= 60;
  463. if(secs < MinSampleSecs)
  464. secs = MinSampleSecs;
  465. return secs;
  466. }
  467. //
  468. // adjust the frequency
  469. //
  470. static uvlong
  471. whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz, vlong dt, vlong ticks, vlong period)
  472. {
  473. static mpint *mpdt;
  474. static mpint *mpticks;
  475. static mpint *mphz;
  476. static mpint *mpbillion;
  477. uvlong ohz = hz;
  478. // sanity check
  479. if(dt <= 0 || ticks <= 0)
  480. return hz;
  481. if(mphz == nil){
  482. mphz = mpnew(0);
  483. mpbillion = uvtomp(SEC, nil);
  484. }
  485. // hz = (ticks*SEC)/dt
  486. mpdt = vtomp(dt, mpdt);
  487. mpticks = vtomp(ticks, mpticks);
  488. mpmul(mpticks, mpbillion, mpticks);
  489. mpdiv(mpticks, mpdt, mphz, nil);
  490. hz = mptoui(mphz);
  491. // sanity
  492. if(hz < minhz || hz > maxhz)
  493. return ohz;
  494. // damp the change if we're shorter than the target period
  495. if(period > dt)
  496. hz = (12ULL*ohz + 4ULL*hz)/16ULL;
  497. settime(-1, hz, 0, 0);
  498. return hz;
  499. }
  500. // We may be changing the frequency to match a bad measurement
  501. // or to match a condition no longer in effet. To make sure
  502. // that this doesn't blow our error budget over the next measurement
  503. // period, shorten the period to make sure that δhz*secs will be
  504. // less than the accuracy limit. Here taccuracy is accuracy converted
  505. // from nanoseconds to ticks.
  506. static int
  507. caperror(vlong dhz, int tsecs, vlong taccuracy)
  508. {
  509. if(dhz*tsecs <= taccuracy)
  510. return tsecs;
  511. if(debug)
  512. fprint(2, "δhz %lld tsecs %d tacc %lld\n", dhz, tsecs, taccuracy);
  513. tsecs = taccuracy/dhz;
  514. if(tsecs < MinSampleSecs)
  515. tsecs = MinSampleSecs;
  516. return tsecs;
  517. }
  518. //
  519. // kernel interface
  520. //
  521. enum
  522. {
  523. Ibintime,
  524. Insec,
  525. Itiming,
  526. };
  527. int ifc;
  528. int bintimefd = -1;
  529. int timingfd = -1;
  530. int nsecfd = -1;
  531. int fastclockfd = -1;
  532. static void
  533. inittime(void)
  534. {
  535. int mode;
  536. if(impotent)
  537. mode = OREAD;
  538. else
  539. mode = ORDWR;
  540. // bind in clocks
  541. if(access("/dev/time", 0) < 0)
  542. bind("#c", "/dev", MAFTER);
  543. if(access("/dev/rtc", 0) < 0)
  544. bind("#r", "/dev", MAFTER);
  545. // figure out what interface we have
  546. ifc = Ibintime;
  547. bintimefd = open("/dev/bintime", mode);
  548. if(bintimefd >= 0)
  549. return;
  550. ifc = Insec;
  551. nsecfd = open("/dev/nsec", mode);
  552. if(nsecfd < 0)
  553. sysfatal("opening /dev/nsec");
  554. fastclockfd = open("/dev/fastclock", mode);
  555. if(fastclockfd < 0)
  556. sysfatal("opening /dev/fastclock");
  557. timingfd = open("/dev/timing", OREAD);
  558. if(timingfd < 0)
  559. return;
  560. ifc = Itiming;
  561. }
  562. //
  563. // convert binary numbers from/to kernel
  564. //
  565. static uvlong uvorder = 0x0001020304050607ULL;
  566. static uchar*
  567. be2vlong(vlong *to, uchar *f)
  568. {
  569. uchar *t, *o;
  570. int i;
  571. t = (uchar*)to;
  572. o = (uchar*)&uvorder;
  573. for(i = 0; i < sizeof(vlong); i++)
  574. t[o[i]] = f[i];
  575. return f+sizeof(vlong);
  576. }
  577. static uchar*
  578. vlong2be(uchar *t, vlong from)
  579. {
  580. uchar *f, *o;
  581. int i;
  582. f = (uchar*)&from;
  583. o = (uchar*)&uvorder;
  584. for(i = 0; i < sizeof(vlong); i++)
  585. t[i] = f[o[i]];
  586. return t+sizeof(vlong);
  587. }
  588. static long order = 0x00010203;
  589. static uchar*
  590. be2long(long *to, uchar *f)
  591. {
  592. uchar *t, *o;
  593. int i;
  594. t = (uchar*)to;
  595. o = (uchar*)&order;
  596. for(i = 0; i < sizeof(long); i++)
  597. t[o[i]] = f[i];
  598. return f+sizeof(long);
  599. }
  600. static uchar*
  601. long2be(uchar *t, long from)
  602. {
  603. uchar *f, *o;
  604. int i;
  605. f = (uchar*)&from;
  606. o = (uchar*)&order;
  607. for(i = 0; i < sizeof(long); i++)
  608. t[i] = f[o[i]];
  609. return t+sizeof(long);
  610. }
  611. //
  612. // read ticks and local time in nanoseconds
  613. //
  614. static int
  615. gettime(vlong *nsec, uvlong *ticks, uvlong *hz)
  616. {
  617. int i, n;
  618. uchar ub[3*8], *p;
  619. char b[2*24+1];
  620. switch(ifc){
  621. case Ibintime:
  622. n = sizeof(vlong);
  623. if(hz != nil)
  624. n = 3*sizeof(vlong);
  625. if(ticks != nil)
  626. n = 2*sizeof(vlong);
  627. i = read(bintimefd, ub, n);
  628. if(i != n)
  629. break;
  630. p = ub;
  631. if(nsec != nil)
  632. be2vlong(nsec, ub);
  633. p += sizeof(vlong);
  634. if(ticks != nil)
  635. be2vlong((vlong*)ticks, p);
  636. p += sizeof(vlong);
  637. if(hz != nil)
  638. be2vlong((vlong*)hz, p);
  639. return 0;
  640. case Itiming:
  641. n = sizeof(vlong);
  642. if(ticks != nil)
  643. n = 2*sizeof(vlong);
  644. i = read(timingfd, ub, n);
  645. if(i != n)
  646. break;
  647. p = ub;
  648. if(nsec != nil)
  649. be2vlong(nsec, ub);
  650. p += sizeof(vlong);
  651. if(ticks != nil)
  652. be2vlong((vlong*)ticks, p);
  653. if(hz != nil){
  654. seek(fastclockfd, 0, 0);
  655. n = read(fastclockfd, b, sizeof(b)-1);
  656. if(n <= 0)
  657. break;
  658. b[n] = 0;
  659. *hz = strtoll(b+24, 0, 0);
  660. }
  661. return 0;
  662. case Insec:
  663. if(nsec != nil){
  664. seek(nsecfd, 0, 0);
  665. n = read(nsecfd, b, sizeof(b)-1);
  666. if(n <= 0)
  667. break;
  668. b[n] = 0;
  669. *nsec = strtoll(b, 0, 0);
  670. }
  671. if(ticks != nil){
  672. seek(fastclockfd, 0, 0);
  673. n = read(fastclockfd, b, sizeof(b)-1);
  674. if(n <= 0)
  675. break;
  676. b[n] = 0;
  677. *ticks = strtoll(b, 0, 0);
  678. }
  679. if(hz != nil){
  680. seek(fastclockfd, 0, 0);
  681. n = read(fastclockfd, b, sizeof(b)-1);
  682. if(n <= 24)
  683. break;
  684. b[n] = 0;
  685. *hz = strtoll(b+24, 0, 0);
  686. }
  687. return 0;
  688. }
  689. return -1;
  690. }
  691. static void
  692. settime(vlong now, uvlong hz, vlong delta, int n)
  693. {
  694. uchar b[1+sizeof(vlong)+sizeof(long)], *p;
  695. if(debug)
  696. fprint(2, "settime(now=%lld, hz=%llud, delta=%lld, period=%d)\n", now, hz, delta, n);
  697. if(impotent)
  698. return;
  699. switch(ifc){
  700. case Ibintime:
  701. if(now >= 0){
  702. p = b;
  703. *p++ = 'n';
  704. p = vlong2be(p, now);
  705. if(write(bintimefd, b, p-b) < 0)
  706. sysfatal("writing /dev/bintime: %r");
  707. }
  708. if(delta != 0){
  709. p = b;
  710. *p++ = 'd';
  711. p = vlong2be(p, delta);
  712. p = long2be(p, n);
  713. if(write(bintimefd, b, p-b) < 0)
  714. sysfatal("writing /dev/bintime: %r");
  715. }
  716. if(hz != 0){
  717. p = b;
  718. *p++ = 'f';
  719. p = vlong2be(p, hz);
  720. if(write(bintimefd, b, p-b) < 0)
  721. sysfatal("writing /dev/bintime: %r");
  722. }
  723. break;
  724. case Itiming:
  725. case Insec:
  726. seek(nsecfd, 0, 0);
  727. if(now >= 0 || delta != 0){
  728. if(fprint(nsecfd, "%lld %lld %d", now, delta, n) < 0)
  729. sysfatal("writing /dev/nsec: %r");
  730. }
  731. if(hz > 0){
  732. seek(fastclockfd, 0, 0);
  733. if(fprint(fastclockfd, "%lld", hz) < 0)
  734. sysfatal("writing /dev/fastclock: %r");
  735. }
  736. }
  737. }
  738. //
  739. // set priority high and wire process to a processor
  740. //
  741. static void
  742. setpriority(void)
  743. {
  744. int fd;
  745. char buf[32];
  746. sprint(buf, "/proc/%d/ctl", getpid());
  747. fd = open(buf, ORDWR);
  748. if(fd < 0){
  749. fprint(2, "can't set priority\n");
  750. return;
  751. }
  752. if(fprint(fd, "pri 100") < 0)
  753. fprint(2, "can't set priority\n");
  754. if(fprint(fd, "wired 2") < 0)
  755. fprint(2, "can't wire process\n");
  756. close(fd);
  757. }
  758. // convert to ntp timestamps
  759. static void
  760. hnputts(void *p, vlong nsec)
  761. {
  762. uchar *a;
  763. ulong tsh;
  764. ulong tsl;
  765. a = p;
  766. // zero is a special case
  767. if(nsec == 0)
  768. return;
  769. tsh = (nsec/SEC);
  770. nsec -= tsh*SEC;
  771. tsl = (nsec<<32)/SEC;
  772. hnputl(a, tsh+EPOCHDIFF);
  773. hnputl(a+4, tsl);
  774. }
  775. // convert from ntp timestamps
  776. static vlong
  777. nhgetts(void *p)
  778. {
  779. uchar *a;
  780. ulong tsh, tsl;
  781. vlong nsec;
  782. a = p;
  783. tsh = nhgetl(a);
  784. tsl = nhgetl(a+4);
  785. nsec = tsl*SEC;
  786. nsec >>= 32;
  787. nsec += (tsh - EPOCHDIFF)*SEC;
  788. return nsec;
  789. }
  790. // convert to ntp 32 bit fixed point
  791. static void
  792. hnputfp(void *p, vlong nsec)
  793. {
  794. uchar *a;
  795. ulong fp;
  796. a = p;
  797. fp = nsec/(SEC/((vlong)(1<<16)));
  798. hnputl(a, fp);
  799. }
  800. // convert from ntp fixed point to nanosecs
  801. static vlong
  802. nhgetfp(void *p)
  803. {
  804. uchar *a;
  805. ulong fp;
  806. vlong nsec;
  807. a = p;
  808. fp = nhgetl(a);
  809. nsec = ((vlong)fp)*(SEC/((vlong)(1<<16)));
  810. return nsec;
  811. }
  812. // get network address of the server
  813. static void
  814. setrootid(char *d)
  815. {
  816. char buf[128];
  817. int fd, n;
  818. char *p;
  819. snprint(buf, sizeof(buf), "%s/remote", d);
  820. fd = open(buf, OREAD);
  821. if(fd < 0)
  822. return;
  823. n = read(fd, buf, sizeof buf);
  824. close(fd);
  825. if(n <= 0)
  826. return;
  827. p = strchr(buf, '!');
  828. if(p != nil)
  829. *p = 0;
  830. v4parseip(rootid, buf);
  831. }
  832. static void
  833. ding(void*, char *s)
  834. {
  835. if(strstr(s, "alarm") != nil)
  836. noted(NCONT);
  837. noted(NDFLT);
  838. }
  839. static void
  840. addntpserver(char *name)
  841. {
  842. NTPserver *ns, **l;
  843. ns = mallocz(sizeof(NTPserver), 1);
  844. if(ns == nil)
  845. sysfatal("addntpserver: %r");
  846. timeserver = strdup(name);
  847. ns->name = name;
  848. for(l = &ntpservers; *l != nil; l = &(*l)->next)
  849. ;
  850. *l = ns;
  851. }
  852. //
  853. // sntp client, we keep calling if the delay seems
  854. // unusually high, i.e., 30% longer than avg.
  855. //
  856. static int
  857. ntptimediff(NTPserver *ns)
  858. {
  859. int fd, tries, n;
  860. NTPpkt ntpin, ntpout;
  861. vlong dt, recvts, origts, xmitts, destts, x;
  862. char dir[64];
  863. fd = dial(netmkaddr(ns->name, "udp", "ntp"), 0, dir, 0);
  864. if(fd < 0){
  865. syslog(0, logfile, "can't reach %s: %r", ns->name);
  866. return -1;
  867. }
  868. setrootid(dir);
  869. notify(ding);
  870. memset(&ntpout, 0, sizeof(ntpout));
  871. ntpout.mode = 3 | (3 << 3);
  872. for(tries = 0; tries < 3; tries++){
  873. alarm(2*1000);
  874. gettime(&x, 0, 0);
  875. hnputts(ntpout.xmitts, x);
  876. if(write(fd, &ntpout, NTPSIZE) < 0){
  877. alarm(0);
  878. continue;
  879. }
  880. n = read(fd, &ntpin, sizeof(ntpin));
  881. alarm(0);
  882. gettime(&destts, 0, 0);
  883. if(n >= NTPSIZE){
  884. close(fd);
  885. // we got one, use it
  886. recvts = nhgetts(ntpin.recvts);
  887. origts = nhgetts(ntpin.origts);
  888. xmitts = nhgetts(ntpin.xmitts);
  889. dt = ((recvts - origts) + (xmitts - destts))/2;
  890. // save results
  891. ns->rtt = ((destts - origts) - (xmitts - recvts))/2;
  892. ns->dt = dt;
  893. ns->stratum = ntpin.stratum;
  894. ns->precision = ntpin.precision;
  895. ns->rootdelay = nhgetfp(ntpin.rootdelay);
  896. ns->rootdisp = nhgetfp(ntpin.rootdisp);
  897. if(debug)
  898. fprint(2, "ntp %s stratum %d ntpdelay(%lld)\n",
  899. ns->name, ntpin.stratum, ns->rtt);
  900. return 0;
  901. }
  902. // try again
  903. sleep(250);
  904. }
  905. close(fd);
  906. return -1;
  907. }
  908. static vlong
  909. gpssample(void)
  910. {
  911. vlong l, g, d;
  912. int i, n;
  913. char *v[4], buf[128];
  914. d = -1000000000000000000LL;
  915. for(i = 0; i < 5; i++){
  916. sleep(1100);
  917. seek(gpsfil, 0, 0);
  918. n = read(gpsfil, buf, sizeof buf - 1);
  919. if (n <= 0)
  920. return(0LL);
  921. buf[n] = 0;
  922. n = tokenize(buf, v, nelem(v));
  923. if(n != 4)
  924. return(0LL);
  925. if(strcmp(v[3], "A") != 0)
  926. return(0LL);
  927. g = atoll(v[1]);
  928. l = atoll(v[2]);
  929. if(g-l > d)
  930. d = g-l;
  931. }
  932. return(d);
  933. }
  934. static vlong
  935. ntpsample(void)
  936. {
  937. NTPserver *tns, *ns;
  938. vlong metric, x;
  939. metric = 1000LL*SEC;
  940. ns = nil;
  941. for(tns = ntpservers; tns != nil; tns = tns->next){
  942. if(ntptimediff(tns) < 0)
  943. continue;
  944. x = vabs(tns->rootdisp) + (vabs(tns->rtt+tns->rootdelay)>>1);
  945. if(debug)
  946. fprint(2, "ntp %s rootdelay %lld rootdisp %lld metric %lld\n",
  947. tns->name, tns->rootdelay, tns->rootdisp, x);
  948. if(x < metric){
  949. metric = x;
  950. ns = tns;
  951. }
  952. }
  953. if(ns == nil)
  954. return 0LL;
  955. // save data for our server
  956. rootdisp = ns->rootdisp;
  957. rootdelay = ns->rootdelay;
  958. mydelay = ns->rtt;
  959. mydisp = avgerr;
  960. if(ns->stratum == 0)
  961. stratum = 0;
  962. else
  963. stratum = ns->stratum + 1;
  964. ε = abs(ns->rtt/2);
  965. return ns->dt;
  966. }
  967. //
  968. // sample the utc file
  969. //
  970. static vlong
  971. utcsample(void)
  972. {
  973. vlong s;
  974. int n;
  975. char *v[2], buf[128];
  976. s = 0;
  977. seek(utcfil, 0, 0);
  978. n = read(utcfil, buf, sizeof buf - 1);
  979. if (n <= 0)
  980. return(0LL);
  981. buf[n] = 0;
  982. n = tokenize(buf, v, nelem(v));
  983. if (strcmp(v[0], "0") == 0)
  984. return(0LL);
  985. if (n == 2) {
  986. gettime(&s, nil, nil);
  987. s -= atoll(v[1]);
  988. }
  989. lastutc = atoll(v[0]) + s;
  990. return(lastutc);
  991. }
  992. //
  993. // sntp server
  994. //
  995. static int
  996. openlisten(char *net)
  997. {
  998. int fd, cfd;
  999. char data[128];
  1000. char devdir[40];
  1001. sprint(data, "%s/udp!*!ntp", net);
  1002. cfd = announce(data, devdir);
  1003. if(cfd < 0)
  1004. sysfatal("can't announce");
  1005. if(fprint(cfd, "headers") < 0)
  1006. sysfatal("can't set header mode");
  1007. fprint(cfd, "oldheaders");
  1008. sprint(data, "%s/data", devdir);
  1009. fd = open(data, ORDWR);
  1010. if(fd < 0)
  1011. sysfatal("open udp data");
  1012. return fd;
  1013. }
  1014. static void
  1015. ntpserver(char *servenet)
  1016. {
  1017. int fd, n;
  1018. NTPpkt *ntp;
  1019. char buf[512];
  1020. int vers, mode;
  1021. vlong recvts, x;
  1022. fd = openlisten(servenet);
  1023. if (Rootid == nil)
  1024. switch(type){
  1025. case Fs:
  1026. Rootid = "WWV";
  1027. break;
  1028. case Rtc:
  1029. Rootid = "LOCL";
  1030. break;
  1031. case Utc:
  1032. Rootid = "UTC";
  1033. break;
  1034. case Ntp:
  1035. /* set by the ntp client */
  1036. break;
  1037. }
  1038. if (Rootid != nil)
  1039. memmove(rootid, Rootid, strlen(Rootid) > 4 ? 4 : strlen(Rootid));
  1040. for(;;){
  1041. n = read(fd, buf, sizeof(buf));
  1042. gettime(&recvts, 0, 0);
  1043. if(n < 0)
  1044. return;
  1045. if(n < OUdphdrsize + NTPSIZE)
  1046. continue;
  1047. ntp = (NTPpkt*)(buf+OUdphdrsize);
  1048. mode = ntp->mode & 7;
  1049. vers = (ntp->mode>>3) & 7;
  1050. if(mode != 3)
  1051. continue;
  1052. ntp->mode = (vers<<3)|4;
  1053. ntp->stratum = stratum;
  1054. ntp->precision = myprec;
  1055. hnputfp(ntp->rootdelay, rootdelay + mydelay);
  1056. hnputfp(ntp->rootdisp, rootdisp + mydisp);
  1057. hnputts(ntp->refts, lastutc);
  1058. memmove(ntp->origts, ntp->xmitts, sizeof(ntp->origts));
  1059. hnputts(ntp->recvts, recvts);
  1060. memmove(ntp->rootid, rootid, sizeof(ntp->rootid));
  1061. gettime(&x, 0, 0);
  1062. hnputts(ntp->xmitts, x);
  1063. write(fd, buf, NTPSIZE+OUdphdrsize);
  1064. }
  1065. }
  1066. //
  1067. // get the current time from the file system
  1068. //
  1069. static long
  1070. fstime(void)
  1071. {
  1072. Dir *d;
  1073. ulong t;
  1074. d = dirstat("/n/boot");
  1075. if(d != nil){
  1076. t = d->atime;
  1077. free(d);
  1078. } else
  1079. t = 0;
  1080. return t;
  1081. }
  1082. //
  1083. // get the current time from the real time clock
  1084. //
  1085. static long
  1086. rtctime(void)
  1087. {
  1088. char b[20];
  1089. static int f = -1;
  1090. int i, retries;
  1091. memset(b, 0, sizeof(b));
  1092. for(retries = 0; retries < 100; retries++){
  1093. if(f < 0)
  1094. f = open("/dev/rtc", OREAD|OCEXEC);
  1095. if(f < 0)
  1096. break;
  1097. if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof(b))) < 0){
  1098. close(f);
  1099. f = -1;
  1100. } else {
  1101. if(i != 0)
  1102. break;
  1103. }
  1104. }
  1105. return strtoul(b, 0, 10)+gmtdelta;
  1106. }
  1107. //
  1108. // Sample a clock. We wait for the clock to always
  1109. // be at the leading edge of a clock period.
  1110. //
  1111. static vlong
  1112. sample(long (*get)(void))
  1113. {
  1114. long this, last;
  1115. vlong start, end;
  1116. /*
  1117. * wait for the second to change
  1118. */
  1119. last = (*get)();
  1120. for(;;){
  1121. gettime(&start, 0, 0);
  1122. this = (*get)();
  1123. gettime(&end, 0, 0);
  1124. if(this != last)
  1125. break;
  1126. last = this;
  1127. }
  1128. return SEC*this - (end-start)/2;
  1129. }
  1130. //
  1131. // the name of the frequency file has the method and possibly the
  1132. // server name encoded in it.
  1133. //
  1134. static int
  1135. openfreqfile(void)
  1136. {
  1137. char *p;
  1138. int fd;
  1139. if(sysid == nil)
  1140. return -1;
  1141. switch(type){
  1142. case Ntp:
  1143. p = smprint("%s/ts.%s.%d.%s", dir, sysid, type, timeserver);
  1144. break;
  1145. default:
  1146. p = smprint("%s/ts.%s.%d", dir, sysid, type);
  1147. break;
  1148. }
  1149. fd = open(p, ORDWR);
  1150. if(fd < 0)
  1151. fd = create(p, ORDWR, 0666);
  1152. free(p);
  1153. if(fd < 0)
  1154. return -1;
  1155. return fd;
  1156. }
  1157. //
  1158. // the file contains the last known frequency and the
  1159. // number of seconds it was sampled over
  1160. //
  1161. static vlong
  1162. readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz)
  1163. {
  1164. int n;
  1165. char buf[128];
  1166. vlong hz;
  1167. n = read(fd, buf, sizeof(buf)-1);
  1168. if(n <= 0)
  1169. return ohz;
  1170. buf[n] = 0;
  1171. hz = strtoll(buf, nil, 0);
  1172. if(hz > maxhz || hz < minhz)
  1173. return ohz;
  1174. settime(-1, hz, 0, 0);
  1175. return hz;
  1176. }
  1177. //
  1178. // remember hz and averaging period
  1179. //
  1180. static void
  1181. writefreqfile(int fd, vlong hz, int secs, vlong diff)
  1182. {
  1183. long now;
  1184. static long last;
  1185. if(fd < 0)
  1186. return;
  1187. now = time(0);
  1188. if(now - last < 10*60)
  1189. return;
  1190. last = now;
  1191. if(seek(fd, 0, 0) < 0)
  1192. return;
  1193. fprint(fd, "%lld %d %d %lld\n", hz, secs, type, diff);
  1194. }
  1195. static uvlong
  1196. vabs(vlong x)
  1197. {
  1198. if(x < 0LL)
  1199. return (uvlong)-x;
  1200. else
  1201. return (uvlong)x;
  1202. }
  1203. static void
  1204. background(void)
  1205. {
  1206. static int inbackground;
  1207. if(inbackground)
  1208. return;
  1209. if(!debug) {
  1210. switch(rfork(RFPROC|RFFDG|RFNAMEG|RFNOTEG|RFNOWAIT)){
  1211. case -1:
  1212. sysfatal("forking: %r");
  1213. break;
  1214. case 0:
  1215. break;
  1216. default:
  1217. exits(0);
  1218. }
  1219. }
  1220. inbackground = 1;
  1221. }
  1222. static int
  1223. getclockprecision(vlong hz)
  1224. {
  1225. int i;
  1226. i = 8;
  1227. while(hz > 0){
  1228. i--;
  1229. hz >>= 1;
  1230. }
  1231. return i;
  1232. }