Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package chrony for openSUSE:Factory checked in at 2022-09-09 18:22:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/chrony (Old) and /work/SRC/openSUSE:Factory/.chrony.new.2083 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "chrony" Fri Sep 9 18:22:51 2022 rev:37 rq:1002167 version:4.3 Changes: -------- --- /work/SRC/openSUSE:Factory/chrony/chrony.changes 2022-05-24 20:30:58.746898642 +0200 +++ /work/SRC/openSUSE:Factory/.chrony.new.2083/chrony.changes 2022-09-09 18:22:55.180159612 +0200 @@ -1,0 +2,26 @@ +Thu Sep 1 14:40:46 UTC 2022 - Reinhard Max <m...@suse.com> + +- Update to 4.3: + * Add local option to refclock directive to stabilise system + clock with more stable free-running clock (e.g. TCXO, OCXO). + * Add maxdelayquant option to server/pool/peer directive to + replace maxdelaydevratio filter with long-term quantile-based + filtering. + * Add selection option to log directive. + * Allow external PPS in PHC refclock without configurable pin. + * Don't accept first interleaved response to minimise error in + delay. + * Don't use arc4random on Linux to avoid server performance loss. + * Improve filter option to better handle missing NTP samples. + * Improve stability with hardware timestamping and PHC refclock. + * Update seccomp filter +- Update clknetsim to snapshot f00531b. +- Use a more specific conditional for the /usr/etc stuff. + +------------------------------------------------------------------- +Wed Jun 15 14:41:05 UTC 2022 - Stefan Schubert <sch...@suse.com> + +- Moved logrotate files from user specific directory /etc/logrotate.d + to vendor specific directory /usr/etc/logrotate.d. + +------------------------------------------------------------------- Old: ---- chrony-4.2.tar.gz chrony-4.2.tar.gz.sig clknetsim-470b5e9.tar.gz New: ---- chrony-4.3.tar.gz chrony-4.3.tar.gz.sig clknetsim-f00531b.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ chrony.spec ++++++ --- /var/tmp/diff_new_pack.8XXpyQ/_old 2022-09-09 18:22:55.816161296 +0200 +++ /var/tmp/diff_new_pack.8XXpyQ/_new 2022-09-09 18:22:55.820161306 +0200 @@ -26,11 +26,14 @@ %bcond_without sysusers %bcond_without pps %endif +%if 0%{?suse_version} > 1500 +%bcond_without usr_etc +%endif %bcond_without testsuite %define _systemdutildir %(pkg-config --variable systemdutildir systemd) -%global clknetsim_ver 470b5e9 +%global clknetsim_ver f00531b #Compat macro for new _fillupdir macro introduced in Nov 2017 %if ! %{defined _fillupdir} %define _fillupdir %{_localstatedir}/adm/fillup-templates @@ -38,7 +41,7 @@ %define chrony_helper %{_libexecdir}/chrony/helper %define chrony_rundir %{_rundir}/%{name} Name: chrony -Version: 4.2 +Version: 4.3 Release: 0 Summary: System Clock Synchronization Client and Server License: GPL-2.0-only @@ -231,8 +234,14 @@ %{buildroot}%{_prefix}/lib/NetworkManager/dispatcher.d/20-chrony install -Dpm 0755 %{SOURCE3} \ %{buildroot}%{_sysconfdir}/dhcp/dhclient.d/chrony.sh +%if %{with usr_etc} +mkdir -p %{buildroot}%{_distconfdir}/logrotate.d +install -Dpm 0644 examples/chrony.logrotate \ + %{buildroot}%{_distconfdir}/logrotate.d/chrony +%else install -Dpm 0644 examples/chrony.logrotate \ %{buildroot}%{_sysconfdir}/logrotate.d/chrony +%endif install -Dpm 0644 examples/chronyd.service \ %{buildroot}%{_unitdir}/chronyd.service install -Dpm 0644 examples/chrony-wait.service \ @@ -286,6 +295,20 @@ %pre -f chrony.pre %service_add_pre chronyd.service chrony-wait.service +%if %{with usr_etc} +# Prepare for migration to /usr/etc; save any old .rpmsave +for i in logrotate.d/chrony ; do + test -f %{_sysconfdir}/${i}.rpmsave && mv -v %{_sysconfdir}/${i}.rpmsave %{_sysconfdir}/${i}.rpmsave.old ||: +done +%endif + +%if %{with usr_etc} +%posttrans +# Migration to /usr/etc, restore just created .rpmsave +for i in logrotate.d/chrony ; do + test -f %{_sysconfdir}/${i}.rpmsave && mv -v %{_sysconfdir}/${i}.rpmsave %{_sysconfdir}/${i} ||: +done +%endif %preun %service_del_preun chronyd.service chrony-wait.service @@ -309,7 +332,11 @@ %doc examples %config(noreplace) %attr(0640,root,%{name}) %{_sysconfdir}/chrony.conf %config(noreplace) %attr(0640,root,%{name}) %verify(not md5 size mtime) %{_sysconfdir}/chrony.keys +%if 0%{?suse_version} > 1500 +%{_distconfdir}/logrotate.d/chrony +%else %config(noreplace) %{_sysconfdir}/logrotate.d/chrony +%endif %attr(0755,root,root) %{_prefix}/lib/NetworkManager/dispatcher.d/20-chrony %dir %{_sysconfdir}/chrony.d/ %dir %{_sysconfdir}/dhcp/ ++++++ chrony-4.2.tar.gz -> chrony-4.3.tar.gz ++++++ ++++ 5924 lines of diff (skipped) ++++++ clknetsim-470b5e9.tar.gz -> clknetsim-f00531b.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/README new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/README --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/README 2021-11-25 15:33:02.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/README 2022-05-26 18:30:00.000000000 +0200 @@ -129,6 +129,8 @@ the reference clock time error in seconds, the clock can be accessed by the client via shared memory (NTP SHM protocol) or as a PTP hardware clock (PHC) via the clock_gettime() function, there is no default (the clock is disabled) +- nodeX_refclock_base = nodeX + the base of the reference clock, the default is the network time - nodeX_step = expr the extra time step applied once per second (or at the rate specified with the -R option) in seconds, there is no default (no extra steps are applied) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/client.c new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/client.c --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/client.c 2021-11-25 15:33:02.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/client.c 2022-05-26 18:30:00.000000000 +0200 @@ -55,6 +55,7 @@ #include <ifaddrs.h> #include <linux/types.h> #include <linux/ethtool.h> +#include <linux/limits.h> #include <linux/pps.h> #include <linux/sockios.h> #ifdef SO_TIMESTAMPING @@ -115,6 +116,7 @@ static int (*_fxstat)(int ver, int fd, struct stat *statbuf); static int (*_xstat)(int ver, const char *pathname, struct stat *statbuf); #endif +static char *(*_realpath)(const char *path, char *resolved_path); static int (*_open)(const char *pathname, int flags, ...); static ssize_t (*_read)(int fd, void *buf, size_t count); static int (*_close)(int fd); @@ -136,6 +138,11 @@ static int recv_multiply = 1; static int timestamping = 1; +static double phc_delay = 0.0; +static double phc_jitter = 0.0; +static double phc_jitter_asym = 0.0; +static int phc_swap = 0; + enum { IFACE_UNIX, IFACE_LO, @@ -175,6 +182,7 @@ static double real_time = 0.0; static double monotonic_time = 0.0; static double network_time = 0.0; +static double freq_error = 0.0; static int local_time_valid = 0; static time_t system_time_offset = 1262304000; /* 2010-01-01 0:00 UTC */ @@ -217,7 +225,7 @@ static int shm_refclocks = 0; static double shm_refclock_time = 0.0; static struct Reply_getrefoffsets refclock_offsets; -static int refclock_offsets_used = REPLY_GETREFOFFSETS_SIZE; +static int refclock_offsets_used = 0; static int pps_fds = 0; static void make_request(int request_id, const void *request_data, int reqlen, void *reply, int replylen); @@ -239,6 +247,7 @@ _fxstat = (int (*)(int ver, int fd, struct stat *statbuf))dlsym(RTLD_NEXT, "__fxstat"); _xstat = (int (*)(int ver, const char *pathname, struct stat *statbuf))dlsym(RTLD_NEXT, "__xstat"); #endif + _realpath = (char *(*)(const char *path, char *resolved_path))dlsym(RTLD_NEXT, "realpath"); _open = (int (*)(const char *pathname, int flags, ...))dlsym(RTLD_NEXT, "open"); _read = (ssize_t (*)(int fd, void *buf, size_t count))dlsym(RTLD_NEXT, "read"); _close = (int (*)(int fd))dlsym(RTLD_NEXT, "close"); @@ -285,6 +294,22 @@ if (env) timestamping = atoi(env); + env = getenv("CLKNETSIM_PHC_DELAY"); + if (env) + phc_delay = atof(env); + + env = getenv("CLKNETSIM_PHC_JITTER"); + if (env) + phc_jitter = atof(env); + + env = getenv("CLKNETSIM_PHC_JITTER_ASYM"); + if (env) + phc_jitter_asym = atof(env); + + env = getenv("CLKNETSIM_PHC_SWAP"); + if (env) + phc_swap = atoi(env); + f = _fopen("/proc/self/comm", "r"); if (f) { command[0] = '\0'; @@ -396,6 +421,13 @@ assert(offsetof(struct Reply_recv, data) + ((struct Reply_recv *)reply)->len <= received); break; + case REQ_GETREFOFFSETS: + /* reply with variable length */ + assert(received >= offsetof(struct Reply_getrefoffsets, offsets)); + assert(offsetof(struct Reply_getrefoffsets, offsets) + + (sizeof ((struct Reply_getrefoffsets *)reply)->offsets[0]) * + ((struct Reply_getrefoffsets *)reply)->size == received); + break; default: assert(received == replylen); } @@ -409,6 +441,7 @@ real_time = r.real_time; monotonic_time = r.monotonic_time; network_time = r.network_time; + freq_error = r.freq_error; local_time_valid = 1; } } @@ -424,8 +457,9 @@ } static double get_refclock_offset(void) { - if (refclock_offsets_used >= REPLY_GETREFOFFSETS_SIZE) { + if (refclock_offsets_used >= refclock_offsets.size) { make_request(REQ_GETREFOFFSETS, NULL, 0, &refclock_offsets, sizeof (refclock_offsets)); + assert(refclock_offsets.size > 0); refclock_offsets_used = 0; } return refclock_offsets.offsets[refclock_offsets_used++]; @@ -507,6 +541,9 @@ *node = -1; /* multicast as broadcast */ } else { *subnet = SUBNET_FROM_ADDR(addr); + if (fuzz_mode && (*subnet >= subnets || *subnet == unix_subnet)) + *subnet = 0; + assert(*subnet >= 0 && *subnet < subnets); assert(socket_in_subnet(socket, *subnet)); @@ -558,8 +595,8 @@ if (!socket_in_subnet(i, rep->subnet) || (rep->dst_port && sockets[i].port != rep->dst_port) || - (sockets[i].remote_node != -1 && sockets[i].remote_node != rep->from) || - (sockets[i].remote_port && sockets[i].remote_port != rep->src_port)) + (sockets[i].remote_node >= 0 && sockets[i].remote_node != rep->from) || + (sockets[i].remote_port >= 0 && sockets[i].remote_port != rep->src_port)) continue; switch (rep->type) { @@ -707,6 +744,25 @@ normalize_timespec(tp); } +static double get_random_double(void) { + return (double)random() / ((1U << 31) - 1); +} + +static double get_phc_delay(int dir) { + double L, p, delay = 0.0; + int k, lambda = 5; + + /* Poisson with uniform steps */ + if (phc_jitter > 0.0) { + for (L = exp(-lambda), p = 1.0, k = 0; k < 100 && p > L; k++) + p *= get_random_double(); + delay += (k + get_random_double()) / (lambda + 0.5) * + phc_jitter * (0.5 + dir * phc_jitter_asym); + } + + return (delay + phc_delay / 2.0) * (freq_error + 1.0); +} + int gettimeofday(struct timeval *tv, #if !defined(__GLIBC_PREREQ) || __GLIBC_PREREQ(2, 31) || defined(GETTIMEOFDAY_VOID) void *tz @@ -784,13 +840,22 @@ } int settimeofday(const struct timeval *tv, const struct timezone *tz) { + struct timespec ts; + assert(tv); - settime(timeval_to_time(tv, -system_time_offset)); - return 0; + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = 1000 * tv->tv_usec; + return clock_settime(CLOCK_REALTIME, &ts); } int clock_settime(clockid_t which_clock, const struct timespec *tp) { assert(tp && which_clock == CLOCK_REALTIME); + + if (tp->tv_sec < 0 || tp->tv_sec > ((1LLU << 63) / 1000000000)) { + errno = EINVAL; + return -1; + } + settime(timespec_to_time(tp, -system_time_offset)); return 0; } @@ -983,6 +1048,7 @@ real_time = rep.time.real_time; monotonic_time = rep.time.monotonic_time; network_time = rep.time.network_time; + freq_error = rep.time.freq_error; local_time_valid = 1; fill_refclock_sample(); @@ -1234,6 +1300,15 @@ return _fclose(fp); } +char *realpath(const char *path, char *resolved_path) { + if (!strncmp(path, "/dev/ptp", 8)) { + snprintf(resolved_path, PATH_MAX, "%s", path); + return resolved_path; + } + + return _realpath(path, resolved_path); +} + int open(const char *pathname, int flags, ...) { int r, mode_arg = 0; mode_t mode = 0; @@ -1249,9 +1324,9 @@ assert(REFCLK_PHC_INDEX == 0 && SYSCLK_PHC_INDEX == 1); if (!strcmp(pathname, "/dev/ptp0")) - return REFCLK_FD; + return phc_swap ? SYSCLK_FD : REFCLK_FD; else if (!strcmp(pathname, "/dev/ptp1")) - return SYSCLK_FD; + return phc_swap ? REFCLK_FD : SYSCLK_FD; else if (!strcmp(pathname, "/dev/pps0")) return pps_fds++, PPS_FD; else if (!strcmp(pathname, "/dev/urandom")) @@ -1320,7 +1395,6 @@ s = get_free_socket(); if (s < 0) { - assert(0); errno = ENOMEM; return -1; } @@ -1332,6 +1406,7 @@ sockets[s].port = BASE_SOCKET_DEFAULT_PORT + s; sockets[s].iface = domain == AF_UNIX ? IFACE_UNIX : IFACE_ALL; sockets[s].remote_node = -1; + sockets[s].remote_port = -1; return get_socket_fd(s); } @@ -1422,6 +1497,10 @@ sin = (struct sockaddr_in *)addr; assert(addrlen >= sizeof (*sin)); get_target(s, ntohl(sin->sin_addr.s_addr), &subnet, &node); + if (node == -1) { + errno = EINVAL; + return -1; + } sockets[s].iface = IFACE_ETH0 + subnet; sockets[s].remote_node = node; @@ -1563,7 +1642,7 @@ else if (level == IPPROTO_IP && optname == IP_PKTINFO && optlen == sizeof (int)) sockets[s].pkt_info = !!(int *)optval; #ifdef SO_TIMESTAMPING - else if (level == SOL_SOCKET && optname == SO_TIMESTAMPING && optlen == sizeof (int)) { + else if (level == SOL_SOCKET && optname == SO_TIMESTAMPING && optlen >= sizeof (int)) { if (!timestamping) { errno = EINVAL; return -1; @@ -1639,6 +1718,8 @@ return 0; } + init_symbols(); + #ifdef HAVE_STAT assert(_stat); return _stat(pathname, statbuf); @@ -1760,22 +1841,54 @@ #ifdef PTP_SYS_OFFSET } else if (request == PTP_SYS_OFFSET && fd == REFCLK_FD) { struct ptp_sys_offset *sys_off = va_arg(ap, struct ptp_sys_offset *); - struct timespec ts; + struct timespec ts, ts1, ts2; + double delay; + int i; + + if (sys_off->n_samples > PTP_MAX_SAMPLES) + sys_off->n_samples = PTP_MAX_SAMPLES; + + clock_gettime(CLOCK_REALTIME, &ts); + sys_off->ts[sys_off->n_samples * 2].sec = ts.tv_sec; + sys_off->ts[sys_off->n_samples * 2].nsec = ts.tv_nsec; + + for (delay = 0.0, i = sys_off->n_samples - 1; i >= 0; i--) { + delay += get_phc_delay(1); + clock_gettime(REFCLK_ID, &ts1); + add_to_timespec(&ts1, -delay); + ts2 = ts; + delay += get_phc_delay(-1); + add_to_timespec(&ts2, -delay); + sys_off->ts[2 * i + 1].sec = ts1.tv_sec; + sys_off->ts[2 * i + 1].nsec = ts1.tv_nsec; + sys_off->ts[2 * i + 0].sec = ts2.tv_sec; + sys_off->ts[2 * i + 0].nsec = ts2.tv_nsec; + } +#endif +#ifdef PTP_SYS_OFFSET_EXTENDED + } else if (request == PTP_SYS_OFFSET_EXTENDED && fd == REFCLK_FD) { + struct ptp_sys_offset_extended *sys_off = va_arg(ap, struct ptp_sys_offset_extended *); + struct timespec ts, ts1, ts2; int i; if (sys_off->n_samples > PTP_MAX_SAMPLES) sys_off->n_samples = PTP_MAX_SAMPLES; - clock_gettime(REFCLK_ID, &ts); for (i = 0; i < sys_off->n_samples; i++) { - sys_off->ts[2 * i + 1].sec = ts.tv_sec; - sys_off->ts[2 * i + 1].nsec = ts.tv_nsec; + clock_gettime(REFCLK_ID, &ts); + sys_off->ts[i][1].sec = ts.tv_sec; + sys_off->ts[i][1].nsec = ts.tv_nsec; } clock_gettime(CLOCK_REALTIME, &ts); - for (i = 0; i < sys_off->n_samples + 1; i++) { - sys_off->ts[2 * i].sec = ts.tv_sec; - sys_off->ts[2 * i].nsec = ts.tv_nsec; + for (i = 0; i < sys_off->n_samples; i++) { + ts1 = ts, ts2 = ts; + add_to_timespec(&ts1, -get_phc_delay(-1)); + add_to_timespec(&ts2, get_phc_delay(1)); + sys_off->ts[i][0].sec = ts1.tv_sec; + sys_off->ts[i][0].nsec = ts1.tv_nsec; + sys_off->ts[i][2].sec = ts2.tv_sec; + sys_off->ts[i][2].nsec = ts2.tv_nsec; } #endif #ifdef PTP_SYS_OFFSET_PRECISE @@ -1817,6 +1930,7 @@ if (params->mode != (PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC)) ret = -1, errno = EINVAL; } else if (request == PPS_FETCH && fd == PPS_FD) { + static double last_refclock_time = 0.0; static unsigned long seq = 0; struct pps_fdata *data = va_arg(ap, struct pps_fdata *); memset(&data->info, 0, sizeof (data->info)); @@ -1829,7 +1943,10 @@ } } if (shm_refclock_time > 0.0) { - data->info.assert_sequence = ++seq; + if (shm_refclock_time != last_refclock_time) + seq++; + last_refclock_time = shm_refclock_time; + data->info.assert_sequence = seq; data->info.assert_tu.sec = shm_refclock_time; data->info.assert_tu.nsec = (shm_refclock_time - data->info.assert_tu.sec) * 1e9; data->info.assert_tu.sec += system_time_offset; @@ -1919,6 +2036,7 @@ } req.subnet = sockets[s].iface >= IFACE_ETH0 ? sockets[s].iface - IFACE_ETH0 : unix_subnet; req.to = sockets[s].remote_node; + assert(sockets[s].remote_port >= 0); req.dst_port = sockets[s].remote_port; } else { switch (sockets[s].domain) { @@ -1958,10 +2076,10 @@ assert(0); } + assert(req.src_port >= 0); req.src_port = sockets[s].port; assert(socket_in_subnet(s, req.subnet)); - assert(req.src_port && req.dst_port); for (req.len = 0, i = 0; i < msg->msg_iovlen; i++) { assert(req.len + msg->msg_iov[i].iov_len <= sizeof (req.data)); @@ -2126,7 +2244,8 @@ case MSG_TYPE_TCP_DATA: case MSG_TYPE_TCP_DISCONNECT: assert(sockets[s].type == SOCK_STREAM); - assert(sockets[s].remote_port && sockets[s].remote_node != -1); + assert(sockets[s].remote_node >= 0); + assert(sockets[s].remote_port >= 0); if (!sockets[s].connected) { errno = ENOTCONN; @@ -2144,7 +2263,7 @@ assert(socket_in_subnet(s, rep.subnet)); assert(sockets[s].port == rep.dst_port); - assert(!sockets[s].remote_port || sockets[s].remote_port == rep.src_port); + assert(sockets[s].remote_port == -1 || sockets[s].remote_port == rep.src_port); if (msg->msg_name) { switch (sockets[s].domain) { @@ -2294,6 +2413,10 @@ return recvfrom(sockfd, buf, len, flags, (struct sockaddr *)&sa, &addrlen); } +ssize_t __recv_chk(int fd, void *buf, size_t len, size_t buflen, int flags) { + return recv(fd, buf, len, flags); +} + int timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t *created_timer_id) { int t; @@ -2497,6 +2620,15 @@ fprintf(stderr, "\n"); } +void __syslog_chkieee128(int priority, int flag, const char *format, ...) { + va_list ap; + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + void syslog(int priority, const char *format, ...) { va_list ap; @@ -2715,29 +2847,43 @@ return EAI_NONAME; assert(!(flags & NI_NOFQDN)); - assert(!(flags & NI_NUMERICHOST)); - assert(!(flags & NI_NUMERICSERV)); if (host && hostlen > 0) { - node = NODE_FROM_ADDR(ntohl(sin->sin_addr.s_addr)); - subnet = SUBNET_FROM_ADDR(ntohl(sin->sin_addr.s_addr)); - if (subnet < 0 || subnet > 100) { - assert(flags & NI_NAMEREQD); - return EAI_NONAME; + if (flags & NI_NUMERICHOST) { + assert(addr->sa_family == AF_INET); + if (!inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr, + host, hostlen)) + return EAI_OVERFLOW; + } else { + node = NODE_FROM_ADDR(ntohl(sin->sin_addr.s_addr)); + subnet = SUBNET_FROM_ADDR(ntohl(sin->sin_addr.s_addr)); + if (subnet < 0 || subnet > 100) { + assert(flags & NI_NAMEREQD); + return EAI_NONAME; + } + if (snprintf(host, hostlen, "node%d.net%d.clk", + node + 1, subnet + 1) >= hostlen) + return EAI_OVERFLOW; } - if (snprintf(host, hostlen, "node%d.net%d.clk", node + 1, subnet + 1) >= hostlen) - return EAI_OVERFLOW; } if (serv && servlen > 0) { - switch (ntohs(sin->sin_port)) { - case 123: - if (snprintf(serv, servlen, "ntp") >= servlen) - return EAI_OVERFLOW; - break; - default: - if (snprintf(serv, servlen, "%u", ntohs(sin->sin_port)) >= servlen) - return EAI_OVERFLOW; + if (flags & NI_NUMERICSERV) { + assert(addr->sa_family == AF_INET); + if (snprintf(serv, servlen, "%d", + ntohs(((struct sockaddr_in *)addr)->sin_port)) >= servlen) + return EAI_OVERFLOW; + } else { + switch (ntohs(sin->sin_port)) { + case 123: + if (snprintf(serv, servlen, "ntp") >= servlen) + return EAI_OVERFLOW; + break; + default: + if (snprintf(serv, servlen, "%u", + ntohs(sin->sin_port)) >= servlen) + return EAI_OVERFLOW; + } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/client_fuzz.c new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/client_fuzz.c --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/client_fuzz.c 2021-11-25 15:33:02.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/client_fuzz.c 2022-05-26 18:30:00.000000000 +0200 @@ -179,7 +179,11 @@ break; case REQ_SELECT: if (fuzz_mode == FUZZ_MODE_NONE) { + network_time += request->select.timeout; reply->select.ret = REPLY_SELECT_TIMEOUT; + reply->select.time.real_time = network_time; + reply->select.time.monotonic_time = network_time; + reply->select.time.network_time = network_time; return; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/clknetsim.bash new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/clknetsim.bash --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/clknetsim.bash 2021-11-25 15:33:02.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/clknetsim.bash 2022-05-26 18:30:00.000000000 +0200 @@ -82,7 +82,7 @@ args+=($opts) ;; phc2sys) - args=(-s /dev/ptp0 -O 0 $opts $config) + args=($opts $config) ;; nsm) args=($opts) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/examples/ptp4l-phc2sys.test new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/examples/ptp4l-phc2sys.test --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/examples/ptp4l-phc2sys.test 1970-01-01 01:00:00.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/examples/ptp4l-phc2sys.test 2022-05-26 18:30:00.000000000 +0200 @@ -0,0 +1,22 @@ +#!/bin/bash + +CLKNETSIM_PATH=.. +. ../clknetsim.bash + +export CLKNETSIM_UNIX_SUBNET=2 + +generate_config4 "1" "1 2 | 2 3" 0.01 "(sum (* 1e-9 (normal)))" "(* 1e-8 (exponential))" + +start_client 1 ptp4l "clockClass 6" "" "-i eth0" +start_client 2 ptp4l " +first_step_threshold 0.0 +max_frequency 10000" "" "-i eth0" +CLKNETSIM_PHC_SWAP=1 \ +start_client 3 phc2sys "-a -r -z /clknetsim/unix/2:1" + +echo "node3_refclock = (+ -37 (* 1e-6 (normal)))" >> tmp/conf +echo "node3_refclock_base = node2" >> tmp/conf + +start_server 3 -v 2 -n 2 -o log.offset -f log.freq -g log.rawfreq -p log.packets -r 1000 -l 4000 + +cat tmp/stats diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/node.cc new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/node.cc --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/node.cc 2021-11-25 15:33:02.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/node.cc 2022-05-26 18:30:00.000000000 +0200 @@ -21,6 +21,7 @@ #include "sysheaders.h" Node::Node(int index, Network *network) { + this->refclock_base = NULL; this->network = network; this->index = index; fd = -1; @@ -148,6 +149,7 @@ r.real_time = clock.get_real_time(); r.monotonic_time = clock.get_monotonic_time(); r.network_time = network->get_time(); + r.freq_error = clock.get_total_freq() - 1.0; reply(&r, sizeof (r), REQ_GETTIME); } @@ -206,6 +208,7 @@ rep.time.real_time = clock.get_real_time(); rep.time.monotonic_time = clock.get_monotonic_time(); rep.time.network_time = network->get_time(); + rep.time.freq_error = clock.get_total_freq() - 1.0; reply(&rep, sizeof (rep), REQ_SELECT); } } @@ -297,6 +300,7 @@ refclock.set_generation(true); r.valid = refclock.get_sample(&r.time, &r.offset); + assert(!refclock_base); r._pad = 0; reply(&r, sizeof (r), REQ_GETREFSAMPLE); } @@ -304,8 +308,17 @@ void Node::process_getrefoffsets() { Reply_getrefoffsets r; - refclock.get_offsets(r.offsets, REPLY_GETREFOFFSETS_SIZE); - reply(&r, sizeof (r), REQ_GETREFOFFSETS); + if (refclock_base) { + r.size = 1; + refclock.get_offsets(r.offsets, r.size); + r.offsets[0] += network->get_time() - refclock_base->get_real_time(); + } else { + r.size = MAX_GETREFOFFSETS_SIZE; + refclock.get_offsets(r.offsets, r.size); + } + r._pad = 0; + reply(&r, offsetof(Reply_getrefoffsets, offsets) + + sizeof (r.offsets[0]) * r.size, REQ_GETREFOFFSETS); } void Node::resume() { @@ -361,3 +374,7 @@ Refclock *Node::get_refclock() { return &refclock; } + +void Node::set_refclock_base(Clock *clock) { + refclock_base = clock; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/node.h new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/node.h --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/node.h 2021-11-25 15:33:02.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/node.h 2022-05-26 18:30:00.000000000 +0200 @@ -30,6 +30,7 @@ class Node { Clock clock; Refclock refclock; + Clock *refclock_base; Network *network; int index; int fd; @@ -68,6 +69,7 @@ double get_timeout() const; Clock *get_clock(); Refclock *get_refclock(); + void set_refclock_base(Clock *clock); }; #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/protocol.h new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/protocol.h --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/protocol.h 2021-11-25 15:33:02.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/protocol.h 2022-05-26 18:30:00.000000000 +0200 @@ -49,6 +49,7 @@ double real_time; double monotonic_time; double network_time; + double freq_error; }; struct Request_settime { @@ -129,10 +130,12 @@ int _pad; }; -#define REPLY_GETREFOFFSETS_SIZE 1024 +#define MAX_GETREFOFFSETS_SIZE 1024 struct Reply_getrefoffsets { - double offsets[REPLY_GETREFOFFSETS_SIZE]; + unsigned int size; + int _pad; + double offsets[MAX_GETREFOFFSETS_SIZE]; }; union Request_data { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/server.cc new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/server.cc --- old/clknetsim-470b5e9d1b801fa21e24dbea89ff7eb1365431fc/server.cc 2021-11-25 15:33:02.000000000 +0100 +++ new/clknetsim-f00531bc9f652a6eb6ecfe0ad73da511c08c9936/server.cc 2022-05-26 18:30:00.000000000 +0200 @@ -81,6 +81,13 @@ if (node2 >= nodes) continue; network->set_link_delay_generator(node, node2, generator.generate(arg)); + } else if (strncmp(var, "refclock_base", 13) == 0) { + if (strncmp(arg, "node", 4) != 0) + return false; + node2 = atoi(arg + 4) - 1; + if (node2 >= nodes) + return false; + network->get_node(node)->set_refclock_base(network->get_node(node2)->get_clock()); } else if (strncmp(var, "refclock", 8) == 0) network->get_node(node)->get_refclock()->set_offset_generator(generator.generate(arg)); else