bsnmpd: Return the correct uptime.
Do not assume that the kernel boot time is invariant. It is not. FreeBSD uses the formula: wall_time = boot_time + uptime where uptime is monotinically increasing and boot_time is adjusted to get the proper time of day. FreeBSD offers a way to retrieve the uptime directly, so use that instead of trying to compute it by subtracting boot_time from wall_time. Sponsored by: Netflix Reviewed by: cy@ Differential Revision: https://reviews.freebsd.org/D30114
This commit is contained in:
parent
6c34dde83e
commit
f009aedae4
@ -47,9 +47,6 @@
|
|||||||
#include "hostres_oid.h"
|
#include "hostres_oid.h"
|
||||||
#include "hostres_tree.h"
|
#include "hostres_tree.h"
|
||||||
|
|
||||||
/* boot timestamp in centi-seconds */
|
|
||||||
static uint64_t kernel_boot;
|
|
||||||
|
|
||||||
/* physical memory size in Kb */
|
/* physical memory size in Kb */
|
||||||
static uint64_t phys_mem_size;
|
static uint64_t phys_mem_size;
|
||||||
|
|
||||||
@ -76,39 +73,19 @@ fini_scalars(void)
|
|||||||
static int
|
static int
|
||||||
OS_getSystemUptime(uint32_t *ut)
|
OS_getSystemUptime(uint32_t *ut)
|
||||||
{
|
{
|
||||||
struct timeval right_now;
|
uint64_t uptime;
|
||||||
uint64_t now;
|
struct timespec ts;
|
||||||
|
|
||||||
if (kernel_boot == 0) {
|
if (clock_gettime(CLOCK_UPTIME, &ts)) {
|
||||||
/* first time, do the sysctl */
|
syslog(LOG_ERR, "clock_gettime failed: %m");
|
||||||
struct timeval kernel_boot_timestamp;
|
|
||||||
int mib[2] = { CTL_KERN, KERN_BOOTTIME };
|
|
||||||
size_t len = sizeof(kernel_boot_timestamp);
|
|
||||||
|
|
||||||
if (sysctl(mib, nitems(mib), &kernel_boot_timestamp,
|
|
||||||
&len, NULL, 0) == -1) {
|
|
||||||
syslog(LOG_ERR, "sysctl KERN_BOOTTIME failed: %m");
|
|
||||||
return (SNMP_ERR_GENERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRDBG("boot timestamp from kernel: {%lld, %ld}",
|
|
||||||
(long long)kernel_boot_timestamp.tv_sec,
|
|
||||||
(long)kernel_boot_timestamp.tv_usec);
|
|
||||||
|
|
||||||
kernel_boot = ((uint64_t)kernel_boot_timestamp.tv_sec * 100) +
|
|
||||||
(kernel_boot_timestamp.tv_usec / 10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gettimeofday(&right_now, NULL) < 0) {
|
|
||||||
syslog(LOG_ERR, "gettimeofday failed: %m");
|
|
||||||
return (SNMP_ERR_GENERR);
|
return (SNMP_ERR_GENERR);
|
||||||
}
|
}
|
||||||
now = ((uint64_t)right_now.tv_sec * 100) + (right_now.tv_usec / 10000);
|
|
||||||
|
|
||||||
if (now - kernel_boot > UINT32_MAX)
|
uptime = ts.tv_sec * 100 + ts.tv_nsec / 1000000;
|
||||||
|
if (uptime > UINT32_MAX)
|
||||||
*ut = UINT32_MAX;
|
*ut = UINT32_MAX;
|
||||||
else
|
else
|
||||||
*ut = now - kernel_boot;
|
*ut = (uint32_t)uptime;
|
||||||
|
|
||||||
return (SNMP_ERR_NOERROR);
|
return (SNMP_ERR_NOERROR);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user