|
|
|
@ -374,8 +374,7 @@ int send_ping(HOST_ENTRY* h, int index);
|
|
|
|
|
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 timespec_add(struct timespec* a, int64_t ns);
|
|
|
|
|
void usage(int);
|
|
|
|
|
int wait_for_reply(long);
|
|
|
|
|
void print_per_system_stats(void);
|
|
|
|
@ -398,21 +397,6 @@ void host_add_timeout_event(HOST_ENTRY *h, int index, struct timespec *ts);
|
|
|
|
|
struct event *host_get_timeout_event(HOST_ENTRY *h, int index);
|
|
|
|
|
void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency);
|
|
|
|
|
|
|
|
|
|
/*** 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
|
|
|
|
@ -1116,7 +1100,7 @@ int main(int argc, char** argv)
|
|
|
|
|
|
|
|
|
|
if (report_interval) {
|
|
|
|
|
next_report_time = start_time;
|
|
|
|
|
timespec_add_10us(&next_report_time, report_interval);
|
|
|
|
|
timespec_add(&next_report_time, (int64_t)report_interval*10000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
last_send_time.tv_sec = current_time.tv_sec - 10000;
|
|
|
|
@ -1262,7 +1246,7 @@ void add_range(char* start, char* end)
|
|
|
|
|
void main_loop()
|
|
|
|
|
{
|
|
|
|
|
long lt;
|
|
|
|
|
long wait_time;
|
|
|
|
|
int64_t wait_time_ns;
|
|
|
|
|
struct event *event;
|
|
|
|
|
struct host_entry *h;
|
|
|
|
|
|
|
|
|
@ -1271,7 +1255,7 @@ void main_loop()
|
|
|
|
|
|
|
|
|
|
/* timeout event ? */
|
|
|
|
|
if (event_queue_timeout.first &&
|
|
|
|
|
timespec_diff_10us(&event_queue_timeout.first->ev_time, ¤t_time) <= 0)
|
|
|
|
|
timespec_diff(&event_queue_timeout.first->ev_time, ¤t_time) <= 0)
|
|
|
|
|
{
|
|
|
|
|
event = ev_dequeue(&event_queue_timeout);
|
|
|
|
|
h = event->host;
|
|
|
|
@ -1299,11 +1283,11 @@ void main_loop()
|
|
|
|
|
|
|
|
|
|
/* ping event ? */
|
|
|
|
|
if (event_queue_ping.first &&
|
|
|
|
|
timespec_diff_10us(&event_queue_ping.first->ev_time, ¤t_time) <= 0)
|
|
|
|
|
timespec_diff(&event_queue_ping.first->ev_time, ¤t_time) <= 0)
|
|
|
|
|
{
|
|
|
|
|
/* Make sure that we don't ping more than once every "interval" */
|
|
|
|
|
lt = timespec_diff_10us(¤t_time, &last_send_time);
|
|
|
|
|
if (lt < interval)
|
|
|
|
|
lt = timespec_diff(¤t_time, &last_send_time);
|
|
|
|
|
if (lt < interval*10000)
|
|
|
|
|
goto wait_for_reply;
|
|
|
|
|
|
|
|
|
|
/* Dequeue the event */
|
|
|
|
@ -1319,7 +1303,7 @@ void main_loop()
|
|
|
|
|
if (loop_flag || (count_flag && event->ping_index+1 < count)) {
|
|
|
|
|
struct timespec next_ping_time;
|
|
|
|
|
next_ping_time = event->ev_time;
|
|
|
|
|
timespec_add_10us(&next_ping_time, perhost_interval);
|
|
|
|
|
timespec_add(&next_ping_time, (int64_t)perhost_interval*10000);
|
|
|
|
|
host_add_ping_event(h, event->ping_index+1, &next_ping_time);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1327,58 +1311,58 @@ void main_loop()
|
|
|
|
|
wait_for_reply:
|
|
|
|
|
|
|
|
|
|
/* When is the next ping next event? */
|
|
|
|
|
wait_time = -1;
|
|
|
|
|
wait_time_ns = -1;
|
|
|
|
|
if (event_queue_ping.first) {
|
|
|
|
|
wait_time = timespec_diff_10us(&event_queue_ping.first->ev_time, ¤t_time);
|
|
|
|
|
if (wait_time < 0)
|
|
|
|
|
wait_time = 0;
|
|
|
|
|
wait_time_ns = timespec_diff(&event_queue_ping.first->ev_time, ¤t_time);
|
|
|
|
|
if (wait_time_ns < 0)
|
|
|
|
|
wait_time_ns = 0;
|
|
|
|
|
/* make sure that we wait enough, so that the inter-ping delay is
|
|
|
|
|
* bigger than 'interval' */
|
|
|
|
|
if (wait_time < interval) {
|
|
|
|
|
lt = timespec_diff_10us(¤t_time, &last_send_time);
|
|
|
|
|
if (lt < interval) {
|
|
|
|
|
wait_time = interval - lt;
|
|
|
|
|
if (wait_time_ns < interval*10000) {
|
|
|
|
|
lt = timespec_diff(¤t_time, &last_send_time);
|
|
|
|
|
if (lt < interval*10000) {
|
|
|
|
|
wait_time_ns = interval*10000 - lt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbg_printf("next ping event in %ld ms (%s)\n", wait_time / 100, event_queue_ping.first->host->host);
|
|
|
|
|
dbg_printf("next ping event in %ld ms (%s)\n", wait_time_ns / 1000000, event_queue_ping.first->host->host);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* When is the next timeout event? */
|
|
|
|
|
if (event_queue_timeout.first) {
|
|
|
|
|
long wait_time_timeout = timespec_diff_10us(&event_queue_timeout.first->ev_time, ¤t_time);
|
|
|
|
|
if(wait_time < 0 || wait_time_timeout < wait_time) {
|
|
|
|
|
wait_time = wait_time_timeout;
|
|
|
|
|
if (wait_time < 0) {
|
|
|
|
|
wait_time = 0;
|
|
|
|
|
long wait_time_timeout = timespec_diff(&event_queue_timeout.first->ev_time, ¤t_time);
|
|
|
|
|
if(wait_time_ns < 0 || wait_time_timeout < wait_time_ns) {
|
|
|
|
|
wait_time_ns = wait_time_timeout;
|
|
|
|
|
if (wait_time_ns < 0) {
|
|
|
|
|
wait_time_ns = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbg_printf("next timeout event in %ld ms (%s)\n", wait_time / 100, event_queue_timeout.first->host->host);
|
|
|
|
|
dbg_printf("next timeout event in %ld ms (%s)\n", wait_time_timeout / 1000000, event_queue_timeout.first->host->host);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* When is the next report due? */
|
|
|
|
|
if (report_interval && (loop_flag || count_flag)) {
|
|
|
|
|
long wait_time_next_report = timespec_diff_10us(&next_report_time, ¤t_time);
|
|
|
|
|
if (wait_time_next_report < wait_time) {
|
|
|
|
|
wait_time = wait_time_next_report;
|
|
|
|
|
if (wait_time < 0) {
|
|
|
|
|
wait_time = 0;
|
|
|
|
|
long wait_time_next_report = timespec_diff(&next_report_time, ¤t_time);
|
|
|
|
|
if (wait_time_next_report < wait_time_ns) {
|
|
|
|
|
wait_time_ns = wait_time_next_report;
|
|
|
|
|
if (wait_time_ns < 0) {
|
|
|
|
|
wait_time_ns = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbg_printf("next report event in %ld ms\n", wait_time_next_report / 100);
|
|
|
|
|
dbg_printf("next report event in %ld ms\n", wait_time_next_report / 1000000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if wait_time is still -1, it means that we are waiting for nothing... */
|
|
|
|
|
if(wait_time == -1) {
|
|
|
|
|
if(wait_time_ns == -1) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Receive replies */
|
|
|
|
|
/* (this is what sleeps during each loop iteration) */
|
|
|
|
|
dbg_printf("waiting up to %ld ms\n", wait_time/100);
|
|
|
|
|
if (wait_for_reply(wait_time)) {
|
|
|
|
|
dbg_printf("waiting up to %ld ms\n", wait_time_ns / 1000000);
|
|
|
|
|
if (wait_for_reply(wait_time_ns)) {
|
|
|
|
|
while (wait_for_reply(0))
|
|
|
|
|
; /* process other replies in the queue */
|
|
|
|
|
}
|
|
|
|
@ -1391,14 +1375,14 @@ void main_loop()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print report */
|
|
|
|
|
if (report_interval && (loop_flag || count_flag) && (timespec_diff_10us(¤t_time, &next_report_time) >= 0)) {
|
|
|
|
|
if (report_interval && (loop_flag || count_flag) && (timespec_diff(¤t_time, &next_report_time) >= 0)) {
|
|
|
|
|
if (netdata_flag)
|
|
|
|
|
print_netdata();
|
|
|
|
|
else
|
|
|
|
|
print_per_system_splits();
|
|
|
|
|
|
|
|
|
|
while (timespec_diff_10us(¤t_time, &next_report_time) >= 0)
|
|
|
|
|
timespec_add_10us(&next_report_time, report_interval);
|
|
|
|
|
while (timespec_diff(¤t_time, &next_report_time) >= 0)
|
|
|
|
|
timespec_add(&next_report_time, (int64_t)report_interval*10000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1807,7 +1791,7 @@ int send_ping(HOST_ENTRY* h, int index)
|
|
|
|
|
else {
|
|
|
|
|
/* schedule timeout */
|
|
|
|
|
struct timespec timeout_time = current_time;
|
|
|
|
|
timespec_add_10us(&timeout_time, h->timeout);
|
|
|
|
|
timespec_add(&timeout_time, (int64_t)(h->timeout)*10000);
|
|
|
|
|
host_add_timeout_event(h, index, &timeout_time);
|
|
|
|
|
|
|
|
|
|
/* mark this trial as outstanding */
|
|
|
|
@ -1871,13 +1855,15 @@ select_again:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int receive_packet(int socket,
|
|
|
|
|
int receive_packet(int64_t wait_time,
|
|
|
|
|
struct timespec* reply_timestamp,
|
|
|
|
|
struct sockaddr* reply_src_addr,
|
|
|
|
|
size_t reply_src_addr_len,
|
|
|
|
|
char* reply_buf,
|
|
|
|
|
size_t reply_buf_len)
|
|
|
|
|
{
|
|
|
|
|
struct timeval to;
|
|
|
|
|
int s = 0;
|
|
|
|
|
int recv_len;
|
|
|
|
|
static unsigned char msg_control[40];
|
|
|
|
|
struct iovec msg_iov = {
|
|
|
|
@ -1898,7 +1884,24 @@ int receive_packet(int socket,
|
|
|
|
|
struct cmsghdr* cmsg;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
recv_len = recvmsg(socket, &recv_msghdr, 0);
|
|
|
|
|
/* Wait for a socket to become ready */
|
|
|
|
|
if (wait_time) {
|
|
|
|
|
to.tv_sec = wait_time / UINT64_C(1000000000);
|
|
|
|
|
to.tv_usec = (wait_time % UINT64_C(1000000000)) / 1000 + 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
to.tv_sec = 0;
|
|
|
|
|
to.tv_usec = 0;
|
|
|
|
|
}
|
|
|
|
|
dbg_printf("wait time: %ld\n", wait_time);
|
|
|
|
|
s = socket_can_read(&to);
|
|
|
|
|
if (s == -1) {
|
|
|
|
|
return 0; /* timeout */
|
|
|
|
|
}
|
|
|
|
|
dbg_printf("socket ready: %d\n", s);
|
|
|
|
|
|
|
|
|
|
recv_len = recvmsg(s, &recv_msghdr, 0);
|
|
|
|
|
if (recv_len <= 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -2193,7 +2196,7 @@ int decode_icmp_ipv6(
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int wait_for_reply(long wait_time)
|
|
|
|
|
int wait_for_reply(int64_t wait_time)
|
|
|
|
|
{
|
|
|
|
|
int result;
|
|
|
|
|
static char buffer[4096];
|
|
|
|
@ -2207,31 +2210,9 @@ int wait_for_reply(long wait_time)
|
|
|
|
|
SEQMAP_VALUE* seqmap_value;
|
|
|
|
|
unsigned short id;
|
|
|
|
|
unsigned short seq;
|
|
|
|
|
struct timeval to;
|
|
|
|
|
int s = 0;
|
|
|
|
|
|
|
|
|
|
/* Wait for a socket to become ready */
|
|
|
|
|
if (wait_time) {
|
|
|
|
|
if (wait_time < 100000) {
|
|
|
|
|
to.tv_sec = 0;
|
|
|
|
|
to.tv_usec = wait_time * 10;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
to.tv_sec = wait_time / 100000;
|
|
|
|
|
to.tv_usec = (wait_time % 100000) * 10;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
to.tv_sec = 0;
|
|
|
|
|
to.tv_usec = 0;
|
|
|
|
|
}
|
|
|
|
|
s = socket_can_read(&to);
|
|
|
|
|
if (s == -1) {
|
|
|
|
|
return 0; /* timeout */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Receive packet */
|
|
|
|
|
result = receive_packet(s, /* socket */
|
|
|
|
|
result = receive_packet(wait_time, /* max. wait time, in ns */
|
|
|
|
|
&recv_time, /* reply_timestamp */
|
|
|
|
|
(struct sockaddr*)&response_addr, /* reply_src_addr */
|
|
|
|
|
sizeof(response_addr), /* reply_src_addr_len */
|
|
|
|
@ -2240,7 +2221,7 @@ int wait_for_reply(long wait_time)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (result <= 0) {
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clock_gettime(CLOCKID, ¤t_time);
|
|
|
|
@ -2320,7 +2301,7 @@ int wait_for_reply(long wait_time)
|
|
|
|
|
|
|
|
|
|
/* discard reply if delay is larger than timeout
|
|
|
|
|
* (see also: github #32) */
|
|
|
|
|
if (ns_to_tick(this_reply) > h->timeout) {
|
|
|
|
|
if (this_reply > (int64_t)(h->timeout)*10000) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2663,39 +2644,28 @@ void print_warning(char* format, ...)
|
|
|
|
|
|
|
|
|
|
int64_t timespec_ns(struct timespec* a)
|
|
|
|
|
{
|
|
|
|
|
return (a->tv_sec * 1000000000LL) + a->tv_nsec;
|
|
|
|
|
}
|
|
|
|
|
int64_t timespec_10us(struct timespec* a)
|
|
|
|
|
{
|
|
|
|
|
return (a->tv_sec * 100000) + a->tv_nsec / 10000;
|
|
|
|
|
return ((int64_t) a->tv_sec * UINT64_C(1000000000)) + a->tv_nsec;
|
|
|
|
|
}
|
|
|
|
|
void timespec_from_ns(struct timespec* a, uint64_t ns)
|
|
|
|
|
{
|
|
|
|
|
a->tv_sec = ns / 1000000000ULL;
|
|
|
|
|
a->tv_nsec = ns % 1000000000ULL;
|
|
|
|
|
a->tv_sec = ns / UINT64_C(1000000000);
|
|
|
|
|
a->tv_nsec = ns % UINT64_C(1000000000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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: timespec_add
|
|
|
|
|
|
|
|
|
|
*************************************************************/
|
|
|
|
|
void timespec_add_10us(struct timespec* a, long t_10u)
|
|
|
|
|
void timespec_add(struct timespec* a, int64_t ns)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
a->tv_sec += (ns + a->tv_nsec) / UINT64_C(1000000000);
|
|
|
|
|
a->tv_nsec = (ns + a->tv_nsec) % UINT64_C(1000000000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************
|
|
|
|
@ -2780,7 +2750,7 @@ void host_add_ping_event(HOST_ENTRY *h, int index, struct timespec *ts)
|
|
|
|
|
ev_enqueue(&event_queue_ping, event);
|
|
|
|
|
|
|
|
|
|
dbg_printf("%s [%d]: add ping event in %ld ms\n",
|
|
|
|
|
event->host->host, index, timespec_diff_10us(&event->ev_time, ¤t_time) / 100);
|
|
|
|
|
event->host->host, index, timespec_diff(&event->ev_time, ¤t_time) / 1000000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void host_add_timeout_event(HOST_ENTRY *h, int index, struct timespec *ts)
|
|
|
|
@ -2792,7 +2762,7 @@ void host_add_timeout_event(HOST_ENTRY *h, int index, struct timespec *ts)
|
|
|
|
|
ev_enqueue(&event_queue_timeout, event);
|
|
|
|
|
|
|
|
|
|
dbg_printf("%s [%d]: add timeout event in %ld ms\n",
|
|
|
|
|
event->host->host, index, timespec_diff_10us(&event->ev_time, ¤t_time) / 100);
|
|
|
|
|
event->host->host, index, timespec_diff(&event->ev_time, ¤t_time) / 1000000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct event *host_get_timeout_event(HOST_ENTRY *h, int index)
|
|
|
|
|