struct sockaddr_storage saddr; /* internet address */
socklen_t saddr_len;
int timeout; /* time to wait for response */
- struct timespec last_send_time; /* time of last packet sent */
+ int64_t last_send_time; /* time of last packet sent */
int num_sent; /* number of ping packets sent (for statistics) */
int num_recv; /* number of pings received (duplicates ignored) */
int num_recv_total; /* number of pings received, including duplicates */
* this host. */
struct event *event_storage_ping;
struct event *event_storage_timeout;
-#if defined(DEBUG) || defined(_DEBUG)
- int64_t* sent_times; /* per-sent-ping timestamp */
-#endif /* DEBUG || _DEBUG */
} HOST_ENTRY;
int event_storage_count; /* how many events can be stored in host_entry->event_storage_xxx */
struct event {
struct event *ev_prev;
struct event *ev_next;
- struct timespec ev_time;
+ int64_t ev_time;
struct host_entry *host;
int ping_index;
};
num_othericmprcvd = 0; /* total non-echo-reply ICMP received */
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 */
+int64_t current_time_ns;
+int64_t start_time;
+int64_t end_time;
+int64_t last_send_time; /* time last ping was sent */
+int64_t next_report_time; /* time next -Q report is expected */
/* switches */
int generate_flag = 0; /* flag for IP list generation */
int timestamp_flag = 0;
int random_data_flag = 0;
#if defined(DEBUG) || defined(_DEBUG)
-int randomly_lose_flag, sent_times_flag, trace_flag, print_per_system_flag;
+int randomly_lose_flag, trace_flag, print_per_system_flag;
int lose_factor;
#endif /* DEBUG || _DEBUG */
void errno_crash_and_burn(char* message);
char* get_host_by_address(struct in_addr in);
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);
-void timespec_add(struct timespec* a, int64_t ns);
void usage(int);
int wait_for_reply(long);
void print_per_system_stats(void);
void add_range(char*, char*);
void print_warning(char* fmt, ...);
int addr_cmp(struct sockaddr* a, struct sockaddr* b);
-void host_add_ping_event(HOST_ENTRY *h, int index, struct timespec *ts);
-void host_add_timeout_event(HOST_ENTRY *h, int index, struct timespec *ts);
+void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time);
+void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time);
struct event *host_get_timeout_event(HOST_ENTRY *h, int index);
void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency);
+void update_current_time();
/************************************************************
if (debugging & DBG_TRACE)
trace_flag = 1;
- if ((debugging & DBG_SENT_TIMES) && !loop_flag)
- sent_times_flag = 1;
-
if (debugging & DBG_RANDOM_LOSE_FEW) {
randomly_lose_flag = 1;
lose_factor = 1; /* ie, 1/4 */
fprintf(stderr, " report_all_rtts_flag set\n");
if (randomly_lose_flag)
fprintf(stderr, " randomly_lose_flag set\n");
- if (sent_times_flag)
- fprintf(stderr, " sent_times_flag set\n");
if (print_per_system_flag)
fprintf(stderr, " print_per_system_flag set\n");
if (outage_flag)
}
#endif
- clock_gettime(CLOCKID, &start_time);
- current_time = start_time;
+ update_current_time();
+ start_time = current_time_ns;
/* handle host names supplied on command line or in a file */
/* if the generate_flag is on, then generate the IP list */
setlinebuf(stdout);
if (report_interval) {
- next_report_time = start_time;
- timespec_add(&next_report_time, (int64_t)report_interval*10000);
+ next_report_time = current_time_ns + (int64_t)report_interval*10000;
}
- last_send_time.tv_sec = current_time.tv_sec - 10000;
-
-#if defined(DEBUG) || defined(_DEBUG)
- if (randomly_lose_flag)
- srandom(start_time.tv_nsec);
-#endif /* DEBUG || _DEBUG */
+ last_send_time = 0;
seqmap_init();
return 0;
}
+static inline int64_t timespec_ns(struct timespec* a)
+{
+ return ((int64_t) a->tv_sec * 1000000000) + a->tv_nsec;
+}
+
void add_cidr(char* addr)
{
char* addr_end;
/* timeout event ? */
if (event_queue_timeout.first &&
- timespec_diff(&event_queue_timeout.first->ev_time, ¤t_time) <= 0)
+ event_queue_timeout.first->ev_time - current_time_ns <= 0)
{
event = ev_dequeue(&event_queue_timeout);
h = event->host;
/* ping event ? */
if (event_queue_ping.first &&
- timespec_diff(&event_queue_ping.first->ev_time, ¤t_time) <= 0)
+ event_queue_ping.first->ev_time - current_time_ns <= 0)
{
/* Make sure that we don't ping more than once every "interval" */
- lt = timespec_diff(¤t_time, &last_send_time);
+ lt = current_time_ns - last_send_time;
if (lt < interval*10000)
goto wait_for_reply;
/* Loop and count mode: schedule next ping */
if (loop_flag || (count_flag && event->ping_index+1 < count)) {
- struct timespec next_ping_time;
- next_ping_time = event->ev_time;
- timespec_add(&next_ping_time, (int64_t)perhost_interval*10000);
- host_add_ping_event(h, event->ping_index+1, &next_ping_time);
+ host_add_ping_event(h, event->ping_index+1, event->ev_time + (int64_t)perhost_interval*10000);
}
}
/* When is the next ping next event? */
wait_time_ns = -1;
if (event_queue_ping.first) {
- wait_time_ns = timespec_diff(&event_queue_ping.first->ev_time, ¤t_time);
+ wait_time_ns = event_queue_ping.first->ev_time - current_time_ns;
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_ns < interval*10000) {
- lt = timespec_diff(¤t_time, &last_send_time);
+ lt = current_time_ns - last_send_time;
if (lt < interval*10000) {
wait_time_ns = interval*10000 - lt;
}
/* When is the next timeout event? */
if (event_queue_timeout.first) {
- long wait_time_timeout = timespec_diff(&event_queue_timeout.first->ev_time, ¤t_time);
+ int64_t wait_time_timeout = event_queue_timeout.first->ev_time - current_time_ns;
if(wait_time_ns < 0 || wait_time_timeout < wait_time_ns) {
wait_time_ns = wait_time_timeout;
if (wait_time_ns < 0) {
/* When is the next report due? */
if (report_interval && (loop_flag || count_flag)) {
- long wait_time_next_report = timespec_diff(&next_report_time, ¤t_time);
+ int64_t wait_time_next_report = next_report_time - current_time_ns;
if (wait_time_next_report < wait_time_ns) {
wait_time_ns = wait_time_next_report;
if (wait_time_ns < 0) {
; /* process other replies in the queue */
}
- clock_gettime(CLOCKID, ¤t_time);
+ update_current_time();
if (status_snapshot) {
status_snapshot = 0;
}
/* Print report */
- if (report_interval && (loop_flag || count_flag) && (timespec_diff(¤t_time, &next_report_time) >= 0)) {
+ if (report_interval && (loop_flag || count_flag) && (current_time_ns >= next_report_time)) {
if (netdata_flag)
print_netdata();
else
print_per_system_splits();
- while (timespec_diff(¤t_time, &next_report_time) >= 0)
- timespec_add(&next_report_time, (int64_t)report_interval*10000);
+ while (current_time_ns >= next_report_time) {
+ next_report_time += (int64_t)report_interval*10000;
+ }
}
}
}
}
}
+/************************************************************
+
+ Function: update_current_time
+
+*************************************************************/
+
+void update_current_time()
+{
+ clock_gettime(CLOCKID, ¤t_time);
+ current_time_ns = timespec_ns(¤t_time);
+}
+
/************************************************************
int i;
HOST_ENTRY* h;
- clock_gettime(CLOCKID, &end_time);
+ update_current_time();
+ end_time = current_time_ns;
/* tot up unreachables */
for (i = 0; i < num_hosts; i++) {
fprintf(stderr, "\n");
}
-
-#if defined(DEBUG) || defined(_DEBUG)
- if (sent_times_flag) {
- for (j = 0; j < h->num_sent; j++) {
- if ((resp = h->sent_times[j]) >= 0)
- fprintf(stderr, " %s", sprint_tm(resp));
- else
- fprintf(stderr, " -");
-
- fprintf(stderr, "\n");
- }
- }
-#endif
}
}
if (verbose_flag || per_recv_flag)
fprintf(stderr, "\n");
- clock_gettime(CLOCKID, ¤t_time);
+ update_current_time();
curr_tm = localtime((time_t*)¤t_time.tv_sec);
fprintf(stderr, "[%2.2d:%2.2d:%2.2d]\n", curr_tm->tm_hour,
curr_tm->tm_min, curr_tm->tm_sec);
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",
- timespec_diff(&end_time, &start_time) / 1e9);
+ (end_time - start_time) / 1e9);
fprintf(stderr, "\n");
}
int myseq;
int ret = 1;
- clock_gettime(CLOCKID, &h->last_send_time);
- myseq = seqmap_add(h->i, index, &h->last_send_time);
+ update_current_time();
+ h->last_send_time = current_time_ns;
+ myseq = seqmap_add(h->i, index, current_time_ns);
dbg_printf("%s [%d]: send ping\n", h->host, index);
}
else {
/* schedule timeout */
- struct timespec timeout_time = current_time;
- timespec_add(&timeout_time, (int64_t)(h->timeout)*10000);
- host_add_timeout_event(h, index, &timeout_time);
+ host_add_timeout_event(h, index, current_time_ns + (int64_t)h->timeout*10000);
/* mark this trial as outstanding */
if (!loop_flag) {
h->resp_times[index] = RESP_WAITING;
}
-
-#if defined(DEBUG) || defined(_DEBUG)
- if (sent_times_flag)
- h->sent_times[index] = timespec_diff(&h->last_send_time, &start_time);
-#endif
}
num_pingsent++;
}
int receive_packet(int64_t wait_time,
- struct timespec* reply_timestamp,
+ int64_t* reply_timestamp,
struct sockaddr* reply_src_addr,
size_t reply_src_addr_len,
char* reply_buf,
sizeof(msg_control),
0
};
- int timestamp_set = 0;
#if HAVE_SO_TIMESTAMPNS
struct cmsghdr* cmsg;
#endif
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) {
#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_TIMESTAMPNS) {
- memcpy(reply_timestamp, CMSG_DATA(cmsg), sizeof(*reply_timestamp));
- timestamp_set = 1;
+ {
+ struct timespec reply_timestamp_ts;
+ for (cmsg = CMSG_FIRSTHDR(&recv_msghdr);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&recv_msghdr, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPNS) {
+ memcpy(&reply_timestamp_ts, CMSG_DATA(cmsg), sizeof(reply_timestamp_ts));
+ *reply_timestamp = timespec_ns(&reply_timestamp_ts);
+ }
}
}
#endif
- if (!timestamp_set) {
- clock_gettime(CLOCKID, reply_timestamp);
- }
-
#if defined(DEBUG) || defined(_DEBUG)
if (randomly_lose_flag) {
if ((random() & 0x07) <= lose_factor)
return 0;
}
- seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), ¤t_time);
+ seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), current_time_ns);
if (seqmap_value == NULL) {
return 0;
}
return 0;
}
- seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), ¤t_time);
+ seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), current_time_ns);
if (seqmap_value == NULL) {
return 0;
}
HOST_ENTRY* h;
long this_reply;
int this_count;
- struct timespec* sent_time;
- struct timespec recv_time = {0};
+ int64_t recv_time=0;
SEQMAP_VALUE* seqmap_value;
unsigned short id;
unsigned short seq;
return 0;
}
- clock_gettime(CLOCKID, ¤t_time);
+ update_current_time();
+ if(recv_time==0) recv_time = current_time_ns;
/* Process ICMP packet and retrieve id/seq */
if (response_addr.ss_family == AF_INET) {
return 1;
}
- seqmap_value = seqmap_fetch(seq, ¤t_time);
+ seqmap_value = seqmap_fetch(seq, current_time_ns);
if (seqmap_value == NULL) {
return 1;
}
/* find corresponding host_entry */
n = seqmap_value->host_nr;
h = table[n];
- sent_time = &seqmap_value->ping_ts;
this_count = seqmap_value->ping_count;
- this_reply = timespec_diff(&recv_time, sent_time);
+ this_reply = recv_time - seqmap_value->ping_ts;
/* update stats that include invalid replies */
h->num_recv_total++;
/* print received ping (unless --quiet) */
if (per_recv_flag) {
if (timestamp_flag) {
- printf("[%lu.%09lu] ",
- (unsigned long)recv_time.tv_sec,
- (unsigned long)recv_time.tv_nsec);
+ printf("[%10.5f] ", (double)(recv_time / 1000000)/1000);
}
avg = h->total_time / h->num_recv;
printf("%-*s : [%d], %d bytes, %s ms",
HOST_ENTRY* p;
int n;
int64_t *i;
- struct timespec ts;
p = (HOST_ENTRY*)calloc(1, sizeof(HOST_ENTRY));
if (!p)
p->resp_times = i;
}
-#if defined(DEBUG) || defined(_DEBUG)
- /* likewise for sent times */
- if (sent_times_flag) {
- i = (int64_t*)malloc(trials * sizeof(int64_t));
- if (!i)
- crash_and_burn("can't allocate sent_times array");
-
- for (n = 1; n < trials; n++)
- i[n] = RESP_UNUSED;
-
- p->sent_times = i;
- }
-#endif /* DEBUG || _DEBUG */
-
/* allocate event storage */
p->event_storage_ping = (struct event *) calloc(event_storage_count, sizeof(struct event));
p->event_storage_timeout = (struct event *) calloc(event_storage_count, sizeof(struct event));
/* schedule first ping */
- ts = current_time;
- host_add_ping_event(p, 0, &ts);
+ host_add_ping_event(p, 0, current_time_ns);
num_hosts++;
}
}
}
-/************************************************************
-
- Function: timespec_diff
-
-*************************************************************
-
- Inputs: struct timespec *a, struct timespec *b
-
- Returns: int64_t
-
- Description:
-
- timespec_diff now returns result in nanoseconds
-
-************************************************************/
-
-int64_t timespec_ns(struct timespec* a)
-{
- 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 / 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);
-}
-
-/************************************************************
-
- Function: timespec_add
-
-*************************************************************/
-void timespec_add(struct timespec* a, int64_t ns)
-{
- a->tv_sec += (ns + a->tv_nsec) / UINT64_C(1000000000);
- a->tv_nsec = (ns + a->tv_nsec) % UINT64_C(1000000000);
-}
-
/************************************************************
Function: sprint_tm
return 0;
}
-void host_add_ping_event(HOST_ENTRY *h, int index, struct timespec *ts)
+void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time)
{
struct event *event = &h->event_storage_ping[index % event_storage_count];
event->host = h;
event->ping_index = index;
- event->ev_time = *ts;
+ event->ev_time = ev_time;
ev_enqueue(&event_queue_ping, event);
dbg_printf("%s [%d]: add ping event in %ld ms\n",
- event->host->host, index, timespec_diff(&event->ev_time, ¤t_time) / 1000000);
+ event->host->host, index, (ev_time - current_time_ns) / 1000000);
}
-void host_add_timeout_event(HOST_ENTRY *h, int index, struct timespec *ts)
+void host_add_timeout_event(HOST_ENTRY *h, int index, int64_t ev_time)
{
struct event *event = &h->event_storage_timeout[index % event_storage_count];
event->host = h;
event->ping_index = index;
- event->ev_time = *ts;
+ event->ev_time = ev_time;
ev_enqueue(&event_queue_timeout, event);
dbg_printf("%s [%d]: add timeout event in %ld ms\n",
- event->host->host, index, timespec_diff(&event->ev_time, ¤t_time) / 1000000);
+ event->host->host, index, (ev_time - current_time_ns) / 1000000);
}
struct event *host_get_timeout_event(HOST_ENTRY *h, int index)
}
/* Insert on tail? */
- if (timespec_diff(&event->ev_time, &queue->last->ev_time) >= 0) {
+ if (event->ev_time - queue->last->ev_time >= 0) {
event->ev_next = NULL;
event->ev_prev = queue->last;
queue->last->ev_next = event;
i = queue->last;
while (1) {
i_prev = i->ev_prev;
- if (i_prev == NULL || timespec_diff(&event->ev_time, &i_prev->ev_time) >= 0) {
+ if (i_prev == NULL || event->ev_time - i_prev->ev_time >= 0) {
event->ev_prev = i_prev;
event->ev_next = i;
i->ev_prev = event;