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