move to 1us resolution for latency measurement

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
pull/136/head
Steven Noonan 6 years ago
parent 8aa4361118
commit 754a21e2bd
No known key found for this signature in database
GPG Key ID: 408EEB508ED0CD4D

@ -22,13 +22,13 @@ BEGIN fping\.127_0_0_1_quality
SET returned = 100
END
CHART fping\.127_0_0_1_latency '' 'FPing Latency for host 127\.0\.0\.1' ms '127_0_0_1' fping\.latency area 110000 1
DIMENSION min minimum absolute 10 1000
DIMENSION max maximum absolute 10 1000
DIMENSION avg average absolute 10 1000
DIMENSION min minimum absolute 1 1000000
DIMENSION max maximum absolute 1 1000000
DIMENSION avg average absolute 1 1000000
BEGIN fping\.127_0_0_1_latency
SET min = \d{1,2}
SET avg = \d{1,2}
SET max = \d{1,2}
SET min = \d+
SET avg = \d+
SET max = \d+
END}
);
$cmd->stderr_like(qr{127.0.0.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+});

@ -34,9 +34,9 @@ AM_CONDITIONAL([IPV6], [test "x$have_ipv6" = "xyes"])
AM_COND_IF([IPV6], [AC_DEFINE([IPV6], [1], [IPv6 enabled])])
AC_ARG_ENABLE([timestamp],
AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMP)]))
AS_HELP_STRING([--disable-timestamp], [Disable kernel-based packet timestaping (SO_TIMESTAMPNS)]))
AS_IF([test "x$enable_timestamp" != "xno"], [
AC_CHECK_DECL([SO_TIMESTAMP], [AC_DEFINE(HAVE_SO_TIMESTAMP, [1], [SO_TIMESTAMP is defined])], [have_so_timestamp="no"], [#include <sys/types.h>
AC_CHECK_DECL([SO_TIMESTAMPNS], [AC_DEFINE(HAVE_SO_TIMESTAMPNS, [1], [SO_TIMESTAMPNS is defined])], [have_so_timestamp="no"], [#include <sys/types.h>
#include <sys/socket.h>])
])
dnl Test if --enable-timestamp is explicitely enabled and make an error if this platform doesn't support it

@ -39,10 +39,12 @@ extern "C" {
#include "options.h"
#include "optparse.h"
#include <inttypes.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include "seqmap.h"
@ -58,6 +60,8 @@ extern "C" {
#include <stddef.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
@ -107,6 +111,18 @@ extern int h_errno;
#define EMAIL "david@schweikert.ch"
#if HAVE_SO_TIMESTAMPNS
#define CLOCKID CLOCK_REALTIME
#endif
#if !defined(CLOCKID)
#if defined(CLOCK_MONOTONIC)
#define CLOCKID CLOCK_MONOTONIC
#else
#define CLOCKID CLOCK_REALTIME
#endif
#endif
/*** Ping packet defines ***/
#define MAX_IP_PACKET 65536 /* (theoretical) max IP packet size */
@ -198,7 +214,7 @@ typedef struct host_entry {
* to be sent, or the timeout, if the last ping was sent */
struct host_entry* ev_prev; /* double linked list for the event-queue */
struct host_entry* ev_next; /* double linked list for the event-queue */
struct timeval ev_time; /* time, after which this event should happen */
struct timespec ev_time; /* time, after which this event should happen */
int ev_type; /* event type */
int i; /* index into array */
@ -210,7 +226,7 @@ typedef struct host_entry {
int timeout; /* time to wait for response */
unsigned char running; /* unset when through sending */
unsigned char waiting; /* waiting for response */
struct timeval last_send_time; /* time of last packet sent */
struct timespec last_send_time; /* time of last packet sent */
int num_sent; /* number of ping packets sent */
int num_recv; /* number of pings received (duplicates ignored) */
int num_recv_total; /* number of pings received, including duplicates */
@ -224,9 +240,9 @@ typedef struct host_entry {
int min_reply_i; /* shortest response time */
int total_time_i; /* sum of response times */
int discard_next_recv_i; /* don't count next received reply for split reporting */
int* resp_times; /* individual response times */
int64_t* resp_times; /* individual response times */
#if defined(DEBUG) || defined(_DEBUG)
int* sent_times; /* per-sent-ping timestamp */
int64_t* sent_times; /* per-sent-ping timestamp */
#endif /* DEBUG || _DEBUG */
} HOST_ENTRY;
@ -288,11 +304,11 @@ int num_timeout = 0, /* number of times select timed out */
num_pingreceived = 0, /* total pings received */
num_othericmprcvd = 0; /* total non-echo-reply ICMP received */
struct timeval current_time; /* current time (pseudo) */
struct timeval start_time;
struct timeval end_time;
struct timeval last_send_time; /* time last ping was sent */
struct timeval next_report_time; /* time next -Q report is expected */
struct timespec current_time; /* current time (pseudo) */
struct timespec start_time;
struct timespec end_time;
struct timespec last_send_time; /* time last ping was sent */
struct timespec next_report_time; /* time next -Q report is expected */
/* switches */
int generate_flag = 0; /* flag for IP list generation */
@ -320,8 +336,11 @@ void errno_crash_and_burn(char* message);
char* get_host_by_address(struct in_addr in);
void remove_job(HOST_ENTRY* h);
int send_ping(HOST_ENTRY* h);
long timeval_diff(struct timeval* a, struct timeval* b);
void timeval_add(struct timeval* a, long t_10u);
void timespec_from_ns(struct timespec* a, uint64_t ns);
int64_t timespec_ns(struct timespec* a);
int64_t timespec_diff(struct timespec* a, struct timespec* b);
long timespec_diff_10us(struct timespec* a, struct timespec* b);
void timespec_add_10us(struct timespec* a, long t_10u);
void usage(int);
int wait_for_reply(long);
void print_per_system_stats(void);
@ -330,7 +349,7 @@ void print_netdata(void);
void print_global_stats(void);
void main_loop();
void finish();
char* sprint_tm(int t);
const char* sprint_tm(int64_t t);
void ev_enqueue(HOST_ENTRY* h);
HOST_ENTRY* ev_dequeue();
void ev_remove(HOST_ENTRY* h);
@ -341,6 +360,19 @@ int addr_cmp(struct sockaddr* a, struct sockaddr* b);
/*** function definitions ***/
static inline void copy_timespec(struct timespec *dst, const struct timespec *src)
{
dst->tv_sec = src->tv_sec;
dst->tv_nsec = src->tv_nsec;
}
static inline long ns_to_tick(int64_t ns)
{
ns /= 1000; // ns -> us
ns /= 10; // us -> 10us ticks
return (long)ns;
}
/************************************************************
Function: main
@ -900,18 +932,18 @@ int main(int argc, char** argv)
#endif
}
#if HAVE_SO_TIMESTAMP
#if HAVE_SO_TIMESTAMPNS
{
int opt = 1;
if (socket4 >= 0) {
if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
perror("setting SO_TIMESTAMP option");
if (setsockopt(socket4, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) {
perror("setting SO_TIMESTAMPNS option");
}
}
#ifdef IPV6
if (socket6 >= 0) {
if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) {
perror("setting SO_TIMESTAMP option (IPv6)");
if (setsockopt(socket6, SOL_SOCKET, SO_TIMESTAMPNS, &opt, sizeof(opt))) {
perror("setting SO_TIMESTAMPNS option (IPv6)");
}
}
#endif
@ -1032,19 +1064,19 @@ int main(int argc, char** argv)
signal(SIGINT, finish);
gettimeofday(&start_time, NULL);
clock_gettime(CLOCKID, &start_time);
current_time = start_time;
if (report_interval) {
next_report_time = start_time;
timeval_add(&next_report_time, report_interval);
timespec_add_10us(&next_report_time, report_interval);
}
last_send_time.tv_sec = current_time.tv_sec - 10000;
#if defined(DEBUG) || defined(_DEBUG)
if (randomly_lose_flag)
srandom(start_time.tv_usec);
srandom(start_time.tv_nsec);
#endif /* DEBUG || _DEBUG */
seqmap_init();
@ -1189,11 +1221,11 @@ void main_loop()
while (ev_first) {
/* Any event that can be processed now ? */
if (ev_first->ev_time.tv_sec < current_time.tv_sec || (ev_first->ev_time.tv_sec == current_time.tv_sec && ev_first->ev_time.tv_usec < current_time.tv_usec)) {
if (timespec_diff_10us(&ev_first->ev_time, &current_time) < 0) {
/* Event type: ping */
if (ev_first->ev_type == EV_TYPE_PING) {
/* Make sure that we don't ping more than once every "interval" */
lt = timeval_diff(&current_time, &last_send_time);
lt = timespec_diff_10us(&current_time, &last_send_time);
if (lt < interval)
goto wait_for_reply;
@ -1208,9 +1240,8 @@ void main_loop()
/* Normal mode: schedule retry */
if (h->waiting < retry + 1) {
h->ev_type = EV_TYPE_PING;
h->ev_time.tv_sec = last_send_time.tv_sec;
h->ev_time.tv_usec = last_send_time.tv_usec;
timeval_add(&h->ev_time, h->timeout);
copy_timespec(&h->ev_time, &last_send_time);
timespec_add_10us(&h->ev_time, h->timeout);
ev_enqueue(h);
if (backoff_flag) {
@ -1220,26 +1251,23 @@ void main_loop()
/* Normal mode: schedule timeout for last retry */
else {
h->ev_type = EV_TYPE_TIMEOUT;
h->ev_time.tv_sec = last_send_time.tv_sec;
h->ev_time.tv_usec = last_send_time.tv_usec;
timeval_add(&h->ev_time, h->timeout);
copy_timespec(&h->ev_time, &last_send_time);
timespec_add_10us(&h->ev_time, h->timeout);
ev_enqueue(h);
}
}
/* Loop and count mode: schedule next ping */
else if (loop_flag || (count_flag && h->num_sent < count)) {
h->ev_type = EV_TYPE_PING;
h->ev_time.tv_sec = last_send_time.tv_sec;
h->ev_time.tv_usec = last_send_time.tv_usec;
timeval_add(&h->ev_time, perhost_interval);
copy_timespec(&h->ev_time, &last_send_time);
timespec_add_10us(&h->ev_time, perhost_interval);
ev_enqueue(h);
}
/* Count mode: schedule timeout after last ping */
else if (count_flag && h->num_sent >= count) {
h->ev_type = EV_TYPE_TIMEOUT;
h->ev_time.tv_sec = last_send_time.tv_sec;
h->ev_time.tv_usec = last_send_time.tv_usec;
timeval_add(&h->ev_time, h->timeout);
copy_timespec(&h->ev_time, &last_send_time);
timespec_add_10us(&h->ev_time, h->timeout);
ev_enqueue(h);
}
}
@ -1258,7 +1286,7 @@ void main_loop()
wait_time = 0;
}
else {
wait_time = timeval_diff(&ev_first->ev_time, &current_time);
wait_time = timespec_diff_10us(&ev_first->ev_time, &current_time);
if (wait_time < 0)
wait_time = 0;
}
@ -1266,7 +1294,7 @@ void main_loop()
/* make sure that we wait enough, so that the inter-ping delay is
* bigger than 'interval' */
if (wait_time < interval) {
lt = timeval_diff(&current_time, &last_send_time);
lt = timespec_diff_10us(&current_time, &last_send_time);
if (lt < interval) {
wait_time = interval - lt;
}
@ -1278,7 +1306,7 @@ void main_loop()
#if defined(DEBUG) || defined(_DEBUG)
if (trace_flag) {
fprintf(stderr, "next event in %d ms (%s)\n", wait_time / 100, ev_first->host);
fprintf(stderr, "next event in %ld ms (%s)\n", wait_time / 100, ev_first->host);
}
#endif
}
@ -1288,7 +1316,7 @@ void main_loop()
/* Make sure we don't wait too long, in case a report is expected */
if (report_interval && (loop_flag || count_flag)) {
wait_time_next_report = timeval_diff(&next_report_time, &current_time);
wait_time_next_report = timespec_diff_10us(&next_report_time, &current_time);
if (wait_time_next_report < wait_time) {
wait_time = wait_time_next_report;
if (wait_time < 0) {
@ -1304,17 +1332,17 @@ void main_loop()
; /* process other replies in the queue */
}
gettimeofday(&current_time, NULL);
clock_gettime(CLOCKID, &current_time);
/* Print report */
if (report_interval && (loop_flag || count_flag) && (timeval_diff(&current_time, &next_report_time) >= 0)) {
if (report_interval && (loop_flag || count_flag) && (timespec_diff_10us(&current_time, &next_report_time) >= 0)) {
if (netdata_flag)
print_netdata();
else
print_per_system_splits();
while (timeval_diff(&current_time, &next_report_time) >= 0)
timeval_add(&next_report_time, report_interval);
while (timespec_diff_10us(&current_time, &next_report_time) >= 0)
timespec_add_10us(&next_report_time, report_interval);
}
}
}
@ -1338,7 +1366,7 @@ void finish()
int i;
HOST_ENTRY* h;
gettimeofday(&end_time, NULL);
clock_gettime(CLOCKID, &end_time);
/* tot up unreachables */
for (i = 0; i < num_hosts; i++) {
@ -1403,7 +1431,7 @@ void print_per_system_stats(void)
{
int i, j, avg, outage_ms;
HOST_ENTRY* h;
int resp;
int64_t resp;
fflush(stdout);
@ -1417,7 +1445,7 @@ void print_per_system_stats(void)
if (report_all_rtts_flag) {
for (j = 0; j < h->num_sent; j++) {
if ((resp = h->resp_times[j]) >= 0)
fprintf(stderr, " %d.%02d", resp / 100, resp % 100);
fprintf(stderr, " %s", sprint_tm(resp));
else
fprintf(stderr, " -");
}
@ -1493,7 +1521,7 @@ void print_netdata(void)
/* if we just sent the probe and didn't receive a reply, we shouldn't count it */
h->discard_next_recv_i = 0;
if (h->waiting && timeval_diff(&current_time, &h->last_send_time) < h->timeout) {
if (h->waiting && timespec_diff_10us(&current_time, &h->last_send_time) < h->timeout) {
if (h->num_sent_i) {
h->num_sent_i--;
h->discard_next_recv_i = 1;
@ -1530,9 +1558,9 @@ void print_netdata(void)
if (!sent_charts) {
printf("CHART fping.%s_latency '' 'FPing Latency for host %s' ms '%s' fping.latency area 110000 %d\n", h->name, h->host, h->name, report_interval / 100000);
printf("DIMENSION min minimum absolute 10 1000\n");
printf("DIMENSION max maximum absolute 10 1000\n");
printf("DIMENSION avg average absolute 10 1000\n");
printf("DIMENSION min minimum absolute 1 1000000\n");
printf("DIMENSION max maximum absolute 1 1000000\n");
printf("DIMENSION avg average absolute 1 1000000\n");
}
printf("BEGIN fping.%s_latency\n", h->name);
@ -1574,7 +1602,7 @@ void print_per_system_splits(void)
if (verbose_flag || per_recv_flag)
fprintf(stderr, "\n");
gettimeofday(&current_time, NULL);
clock_gettime(CLOCKID, &current_time);
curr_tm = localtime((time_t*)&current_time.tv_sec);
fprintf(stderr, "[%2.2d:%2.2d:%2.2d]\n", curr_tm->tm_hour,
curr_tm->tm_min, curr_tm->tm_sec);
@ -1585,7 +1613,7 @@ void print_per_system_splits(void)
/* if we just sent the probe and didn't receive a reply, we shouldn't count it */
h->discard_next_recv_i = 0;
if (h->waiting && timeval_diff(&current_time, &h->last_send_time) < h->timeout) {
if (h->waiting && timespec_diff_10us(&current_time, &h->last_send_time) < h->timeout) {
if (h->num_sent_i) {
h->num_sent_i--;
h->discard_next_recv_i = 1;
@ -1659,7 +1687,7 @@ void print_global_stats(void)
sprint_tm((int)(sum_replies / total_replies)));
fprintf(stderr, " %s ms (max round trip time)\n", sprint_tm(max_reply));
fprintf(stderr, " %12.3f sec (elapsed real time)\n",
timeval_diff(&end_time, &start_time) / 100000.0);
timespec_diff(&end_time, &start_time) / 1e9);
fprintf(stderr, "\n");
}
@ -1687,7 +1715,7 @@ int send_ping(HOST_ENTRY* h)
int myseq;
int ret = 1;
gettimeofday(&h->last_send_time, NULL);
clock_gettime(CLOCKID, &h->last_send_time);
myseq = seqmap_add(h->i, h->num_sent, &h->last_send_time);
#if defined(DEBUG) || defined(_DEBUG)
@ -1729,7 +1757,7 @@ int send_ping(HOST_ENTRY* h)
#if defined(DEBUG) || defined(_DEBUG)
if (sent_times_flag)
h->sent_times[h->num_sent] = timeval_diff(&h->last_send_time, &start_time);
h->sent_times[h->num_sent] = timespec_diff(&h->last_send_time, &start_time);
#endif
}
@ -1746,7 +1774,7 @@ int send_ping(HOST_ENTRY* h)
int socket_can_read(struct timeval* timeout)
{
int nfound;
fd_set readset, writeset;
fd_set readset;
int socketmax;
#ifndef IPV6
@ -1757,13 +1785,12 @@ int socket_can_read(struct timeval* timeout)
select_again:
FD_ZERO(&readset);
FD_ZERO(&writeset);
if(socket4 >= 0) FD_SET(socket4, &readset);
#ifdef IPV6
if(socket6 >= 0) FD_SET(socket6, &readset);
#endif
nfound = select(socketmax + 1, &readset, &writeset, NULL, timeout);
nfound = select(socketmax + 1, &readset, NULL, NULL, timeout);
if (nfound < 0) {
if (errno == EINTR) {
/* interrupted system call: redo the select */
@ -1789,7 +1816,7 @@ select_again:
}
int receive_packet(int socket,
struct timeval* reply_timestamp,
struct timespec* reply_timestamp,
struct sockaddr* reply_src_addr,
size_t reply_src_addr_len,
char* reply_buf,
@ -1811,19 +1838,21 @@ int receive_packet(int socket,
0
};
int timestamp_set = 0;
#if HAVE_SO_TIMESTAMPNS
struct cmsghdr* cmsg;
#endif
recv_len = recvmsg(socket, &recv_msghdr, 0);
if (recv_len <= 0) {
return 0;
}
#if HAVE_SO_TIMESTAMP
#if HAVE_SO_TIMESTAMPNS
/* ancilliary data */
for (cmsg = CMSG_FIRSTHDR(&recv_msghdr);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPNS) {
memcpy(reply_timestamp, CMSG_DATA(cmsg), sizeof(*reply_timestamp));
timestamp_set = 1;
}
@ -1831,7 +1860,7 @@ int receive_packet(int socket,
#endif
if (!timestamp_set) {
gettimeofday(reply_timestamp, NULL);
clock_gettime(CLOCKID, reply_timestamp);
}
#if defined(DEBUG) || defined(_DEBUG)
@ -2053,8 +2082,8 @@ int wait_for_reply(long wait_time)
HOST_ENTRY* h;
long this_reply;
int this_count;
struct timeval* sent_time;
struct timeval recv_time;
struct timespec* sent_time;
struct timespec recv_time = {0};
SEQMAP_VALUE* seqmap_value;
unsigned short id;
unsigned short seq;
@ -2094,7 +2123,7 @@ int wait_for_reply(long wait_time)
return 1;
}
gettimeofday(&current_time, NULL);
clock_gettime(CLOCKID, &current_time);
/* Process ICMP packet and retrieve id/seq */
if (response_addr.ss_family == AF_INET) {
@ -2146,11 +2175,11 @@ int wait_for_reply(long wait_time)
h = table[n];
sent_time = &seqmap_value->ping_ts;
this_count = seqmap_value->ping_count;
this_reply = timeval_diff(&recv_time, sent_time);
this_reply = timespec_diff(&recv_time, sent_time);
/* discard reply if delay is larger than timeout
* (see also: github #32) */
if (this_reply > h->timeout) {
if (ns_to_tick(this_reply) > h->timeout) {
return 1;
}
@ -2242,9 +2271,9 @@ int wait_for_reply(long wait_time)
if (per_recv_flag) {
if (timestamp_flag) {
printf("[%lu.%06lu] ",
printf("[%lu.%09lu] ",
(unsigned long)recv_time.tv_sec,
(unsigned long)recv_time.tv_usec);
(unsigned long)recv_time.tv_nsec);
}
avg = h->total_time / h->num_recv;
printf("%s%s : [%d], %d bytes, %s ms",
@ -2406,7 +2435,8 @@ void add_name(char* name)
void add_addr(char* name, char* host, struct sockaddr* ipaddr, socklen_t ipaddr_len)
{
HOST_ENTRY* p;
int n, *i;
int n;
int64_t *i;
p = (HOST_ENTRY*)malloc(sizeof(HOST_ENTRY));
if (!p)
@ -2436,7 +2466,7 @@ void add_addr(char* name, char* host, struct sockaddr* ipaddr, socklen_t ipaddr_
/* array for response time results */
if (!loop_flag) {
i = (int*)malloc(trials * sizeof(int));
i = (int64_t*)malloc(trials * sizeof(int64_t));
if (!i)
crash_and_burn("can't allocate resp_times array");
@ -2449,7 +2479,7 @@ void add_addr(char* name, char* host, struct sockaddr* ipaddr, socklen_t ipaddr_
#if defined(DEBUG) || defined(_DEBUG)
/* likewise for sent times */
if (sent_times_flag) {
i = (int*)malloc(trials * sizeof(int));
i = (int64_t*)malloc(trials * sizeof(int64_t));
if (!i)
crash_and_burn("can't allocate sent_times array");
@ -2463,7 +2493,7 @@ void add_addr(char* name, char* host, struct sockaddr* ipaddr, socklen_t ipaddr_
/* schedule first ping */
p->ev_type = EV_TYPE_PING;
p->ev_time.tv_sec = 0;
p->ev_time.tv_usec = 0;
p->ev_time.tv_nsec = 0;
ev_enqueue(p);
num_hosts++;
@ -2553,46 +2583,55 @@ void print_warning(char* format, ...)
/************************************************************
Function: timeval_diff
Function: timespec_diff
*************************************************************
Inputs: struct timeval *a, struct timeval *b
Inputs: struct timespec *a, struct timespec *b
Returns: long
Returns: int64_t
Description:
timeval_diff now returns result in hundredths of milliseconds
ie, tens of microseconds
timespec_diff now returns result in nanoseconds
************************************************************/
long timeval_diff(struct timeval* a, struct timeval* b)
int64_t timespec_ns(struct timespec* a)
{
long sec_diff = a->tv_sec - b->tv_sec;
if (sec_diff == 0) {
return (a->tv_usec - b->tv_usec) / 10;
}
else if (sec_diff < 100) {
return (sec_diff * 1000000 + a->tv_usec - b->tv_usec) / 10;
}
else {
/* For such large differences, we don't really care about the microseconds... */
return sec_diff * 100000;
}
return (a->tv_sec * 1000000000LL) + a->tv_nsec;
}
int64_t timespec_10us(struct timespec* a)
{
return (a->tv_sec * 100000) + a->tv_nsec / 10000;
}
void timespec_from_ns(struct timespec* a, uint64_t ns)
{
a->tv_sec = ns / 1000000000ULL;
a->tv_nsec = ns % 1000000000ULL;
}
int64_t timespec_diff(struct timespec* a, struct timespec* b)
{
return timespec_ns(a) - timespec_ns(b);
}
long timespec_diff_10us(struct timespec* a, struct timespec* b)
{
return (long)(timespec_10us(a) - timespec_10us(b));
}
/************************************************************
Function: timeval_add
Function: timespec_add
*************************************************************/
void timeval_add(struct timeval* a, long t_10u)
void timespec_add_10us(struct timespec* a, long t_10u)
{
t_10u *= 10;
a->tv_sec += (t_10u + a->tv_usec) / 1000000;
a->tv_usec = (t_10u + a->tv_usec) % 1000000;
uint64_t ns = t_10u;
ns *= 10; // tick -> us
ns *= 1000; // us -> ns
a->tv_sec += (ns + a->tv_nsec) / 1000000000ULL;
a->tv_nsec = (ns + a->tv_nsec) % 1000000000ULL;
}
/************************************************************
@ -2612,32 +2651,33 @@ void timeval_add(struct timeval* a, long t_10u)
************************************************************/
char* sprint_tm(int t)
const char* sprint_tm(int64_t ns)
{
static char buf[12];
static char buf[10];
double t = (double)ns / 1e6;
if (t < 0) {
if (t < 0.0) {
/* negative (unexpected) */
sprintf(buf, "%.2g", (double)t / 100);
sprintf(buf, "%.2g", (double)t / 1e9);
}
else if (t < 100) {
else if (t < 1.0) {
/* <= 0.99 ms */
sprintf(buf, "0.%02d", t);
sprintf(buf, "%.6f", t);
}
else if (t < 1000) {
else if (t < 10.0) {
/* 1.00 - 9.99 ms */
sprintf(buf, "%d.%02d", t / 100, t % 100);
sprintf(buf, "%.2f", t);
}
else if (t < 10000) {
else if (t < 100.0) {
/* 10.0 - 99.9 ms */
sprintf(buf, "%d.%d", t / 100, (t % 100) / 10);
sprintf(buf, "%.1f", t);
}
else if (t < 100000000) {
else if (t < 1000000.0) {
/* 100 - 1'000'000 ms */
sprintf(buf, "%d", t / 100);
sprintf(buf, "%d", (int)t);
}
else {
sprintf(buf, "%.2e", (double)(t / 100));
sprintf(buf, "%.2e", t);
}
return (buf);
@ -2689,8 +2729,8 @@ void ev_enqueue(HOST_ENTRY* h)
#if defined(DEBUG) || defined(_DEBUG)
if (trace_flag) {
long st = timeval_diff(&h->ev_time, &current_time);
fprintf(stderr, "Enqueue: host=%s, when=%d ms (%d, %d)\n", h->host, st / 100, h->ev_time.tv_sec, h->ev_time.tv_usec);
long st = timespec_diff_10us(&h->ev_time, &current_time);
fprintf(stderr, "Enqueue: host=%s, when=%ld ms (%ld, %ld)\n", h->host, st / 100, h->ev_time.tv_sec, h->ev_time.tv_nsec);
}
#endif
@ -2704,7 +2744,7 @@ void ev_enqueue(HOST_ENTRY* h)
}
/* Insert on tail? */
if (h->ev_time.tv_sec > ev_last->ev_time.tv_sec || (h->ev_time.tv_sec == ev_last->ev_time.tv_sec && h->ev_time.tv_usec >= ev_last->ev_time.tv_usec)) {
if (timespec_diff(&h->ev_time, &ev_last->ev_time) >= 0) {
h->ev_next = NULL;
h->ev_prev = ev_last;
ev_last->ev_next = h;
@ -2716,7 +2756,7 @@ void ev_enqueue(HOST_ENTRY* h)
i = ev_last;
while (1) {
i_prev = i->ev_prev;
if (i_prev == NULL || h->ev_time.tv_sec > i_prev->ev_time.tv_sec || (h->ev_time.tv_sec == i_prev->ev_time.tv_sec && h->ev_time.tv_usec >= i_prev->ev_time.tv_usec)) {
if (i_prev == NULL || timespec_diff(&h->ev_time, &i_prev->ev_time) >= 0) {
h->ev_prev = i_prev;
h->ev_next = i;
i->ev_prev = h;

@ -66,7 +66,7 @@ void seqmap_init()
}
}
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval* now)
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timespec* now)
{
unsigned int current_id;
SEQMAP_VALUE* next_value;
@ -89,7 +89,7 @@ unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct ti
next_value->host_nr = host_nr;
next_value->ping_count = ping_count;
next_value->ping_ts.tv_sec = now->tv_sec;
next_value->ping_ts.tv_usec = now->tv_usec;
next_value->ping_ts.tv_nsec = now->tv_nsec;
/* increase next id */
current_id = seqmap_next_id;
@ -98,7 +98,7 @@ unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct ti
return current_id;
}
SEQMAP_VALUE* seqmap_fetch(unsigned int id, struct timeval* now)
SEQMAP_VALUE* seqmap_fetch(unsigned int id, struct timespec* now)
{
SEQMAP_VALUE* value;

@ -7,14 +7,14 @@ typedef struct seqmap_value
{
unsigned int host_nr;
unsigned int ping_count;
struct timeval ping_ts;
struct timespec ping_ts;
} SEQMAP_VALUE;
#define SEQMAP_MAXSEQ 65535
void seqmap_init();
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timeval *now);
SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timeval *now);
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, struct timespec *now);
SEQMAP_VALUE *seqmap_fetch(unsigned int id, struct timespec *now);
#endif

Loading…
Cancel
Save