On Wed, Nov 07, 2018 at 06:40:20PM +0000, Gareth Ansell scribbled: # Hi, I can confirm that this is also happening on my VM, also hosted at # openbsd.amsterdam. # Gareth
Same here, and none of the tricks I was finding worked. I was also unsatisfied with the idea of running rdate or restarting ntpd often enough to keep things in sync. Making use of the vmmci(4) timedelta sensor, I found and modified a piece of existing code by Ted U. to work around this problem until someone far smarter than I figures out a proper solution. Attached, but linked as well in case the attachment doesn't make it. https://slite.zenbsd.net/~jontow/vmtimed.c Neither perfect nor desirable, but workable! It makes a lot of adjustments and has been doing an ok job so far. Doesn't seem to perfectly keep the clock in a synced state according to "ntpctl -sa". Here's what it looks like running, and these are the sorts of deltas it regularly sees and applies. Nov 6 00:54:43 frea vmtimed: fixing time! -1.152683 Nov 6 00:56:11 frea vmtimed: fixing time! -1.045395 Nov 6 00:58:08 frea vmtimed: fixing time! -1.236222 Here's "ntpctl -sa" as of right now: 4/4 peers valid, 1/1 sensors valid, constraint offset -198s (16 errors), clock synced, stratum 1 peer wt tl st next poll offset delay jitter 80.127.152.30 from pool pool.ntp.org 1 10 2 332s 3126s 705.111ms 5.394ms 0.974ms 195.242.98.57 from pool pool.ntp.org 1 10 2 245s 3183s 657.527ms 2.126ms 0.410ms 93.94.224.67 from pool pool.ntp.org 1 10 2 53s 3147s 687.997ms 1.931ms 0.532ms 95.211.212.5 from pool pool.ntp.org 1 10 2 2657s 3118s 73.136ms 2.432ms 0.829ms sensor wt gd st next poll offset correction vmmci0 * 1 1 0 8s 15s 689.722ms 0.000ms -- Jonathan Towne
/* * Original code by Ted Unangst <t...@tedunangst.com> * https://https.www.google.com.tedunangst.com/flak/post/vmtimed * * Lightly modified by Jonathan Towne <jon...@mototowne.com> * For use in vmd(8) hosted VMs using vmmci(4) timedelta sensor. * Still probably works with VMware vmt(4), but untested. * Works best in concert with ntpd(8) running normally. */ /* If time drifts more than +/- SENSITIVITY seconds, hard adjust */ #define SENSITIVITY 1 /* Check timedelta sensor value every SLEEPFOR seconds */ #define SLEEPFOR 15 #undef DEBUG #include <sys/param.h> #include <sys/sysctl.h> #include <sys/sensors.h> #include <sys/time.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <unistd.h> #include <err.h> void error(const char *msg) { syslog(LOG_DAEMON | LOG_ERR, "%s", msg); exit(1); } int findvmt0(void) { struct sensordev sdev; size_t slen; int mib[5]; int i; mib[0] = CTL_HW; mib[1] = HW_SENSORS; for (i = 0; i < 20; i++) { mib[2] = i; slen = sizeof(sdev); if (sysctl(mib, 3, &sdev, &slen, NULL, 0) == -1) break; if (strcmp(sdev.xname, "vmmci0") == 0) return i; if (strcmp(sdev.xname, "vmt0") == 0) return i; } return -1; } void timeloop(int vmt0) { struct sensor sensor; size_t slen; int mib[5]; struct timeval tv; double delta; mib[0] = CTL_HW; mib[1] = HW_SENSORS; mib[2] = vmt0; mib[3] = SENSOR_TIMEDELTA; mib[4] = 0; while (1) { slen = sizeof(sensor); if (sysctl(mib, 5, &sensor, &slen, NULL, 0) == -1) err(1, "sysctl"); delta = sensor.value / 1000000000.0; #ifdef DEBUG printf("%f: timeloop()\n", delta); #endif if (delta < (-1 * SENSITIVITY) || delta > SENSITIVITY) { syslog(LOG_DAEMON | LOG_NOTICE, "fixing time! %f\n", delta); if (gettimeofday(&tv, NULL) == -1) error("gettimeofday"); tv.tv_sec -= delta; if (settimeofday(&tv, NULL) == -1) error("settimeofday"); } sleep(SLEEPFOR); } } int main(int argc, char **argv) { int vmt0; vmt0 = findvmt0(); if (vmt0 == -1) error("can't find vmt0"); timeloop(vmt0); }