|
|
|
@@ -74,16 +74,17 @@ static const char * pidfile_name = NULL;
|
|
|
|
|
// Flags
|
|
|
|
|
static unsigned int flag_rewind = 0;
|
|
|
|
|
static unsigned int flag_syslog = 0;
|
|
|
|
|
static unsigned int flag_priority = 0;
|
|
|
|
|
|
|
|
|
|
// String representation of target
|
|
|
|
|
#define ADDR_STR_MAX (INET6_ADDRSTRLEN + IF_NAMESIZE + 1)
|
|
|
|
|
static char dest_str[ADDR_STR_MAX];
|
|
|
|
|
|
|
|
|
|
// Time period over which we are averaging results in ms
|
|
|
|
|
static unsigned long time_period_msec = 30000;
|
|
|
|
|
static unsigned long time_period_msec = 60000;
|
|
|
|
|
|
|
|
|
|
// Interval between sends in ms
|
|
|
|
|
static unsigned long send_interval_msec = 250;
|
|
|
|
|
static unsigned long send_interval_msec = 500;
|
|
|
|
|
|
|
|
|
|
// Interval before a sequence is initially treated as lost
|
|
|
|
|
// Input from command line in ms and used in us
|
|
|
|
@@ -286,7 +287,7 @@ llsqrt(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
return (unsigned long) s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -352,14 +353,14 @@ send_thread(
|
|
|
|
|
|
|
|
|
|
array[next_slot].status = PACKET_STATUS_EMPTY;
|
|
|
|
|
sched_yield();
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &array[next_slot].time_sent);
|
|
|
|
|
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &array[next_slot].time_sent);
|
|
|
|
|
array[next_slot].status = PACKET_STATUS_SENT;
|
|
|
|
|
len = sendto(send_sock, echo_request, echo_request_len, 0, (struct sockaddr *) &dest_addr, dest_addr_len);
|
|
|
|
|
if (len == -1)
|
|
|
|
|
{
|
|
|
|
|
logger("%s%s: sendto error: %d\n", identifier, dest_str, errno);
|
|
|
|
|
}
|
|
|
|
|
array[next_slot].status = PACKET_STATUS_SENT;
|
|
|
|
|
|
|
|
|
|
next_slot = (next_slot + 1) % array_size;
|
|
|
|
|
next_sequence = (next_sequence + 1) % sequence_limit;
|
|
|
|
@@ -471,7 +472,7 @@ report(
|
|
|
|
|
packets_received++;
|
|
|
|
|
latency_usec = array[slot].latency_usec;
|
|
|
|
|
total_latency_usec += latency_usec;
|
|
|
|
|
total_latency_usec2 += latency_usec * latency_usec;
|
|
|
|
|
total_latency_usec2 += (unsigned long long) latency_usec * latency_usec;
|
|
|
|
|
}
|
|
|
|
|
else if (array[slot].status == PACKET_STATUS_SENT &&
|
|
|
|
|
ts_elapsed_usec(&array[slot].time_sent, &now) > loss_interval_usec)
|
|
|
|
@@ -489,7 +490,7 @@ report(
|
|
|
|
|
|
|
|
|
|
// stddev = sqrt((sum(rtt^2) / packets) - (sum(rtt) / packets)^2)
|
|
|
|
|
*average_latency_usec = avg;
|
|
|
|
|
*latency_deviation = llsqrt(avg2 - (avg * avg));
|
|
|
|
|
*latency_deviation = llsqrt(avg2 - ((unsigned long long) avg * avg));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@@ -824,15 +825,16 @@ static void
|
|
|
|
|
usage(void)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Usage:\n");
|
|
|
|
|
fprintf(stderr, " %s [-f] [-R] [-S] [-B bind_addr] [-s send_interval] [-l loss_interval] [-t time_period] [-r report_interval] [-d data_length] [-o output_file] [-A alert_interval] [-D latency_alarm] [-L loss_alarm] [-C alert_cmd] [-i identifier] [-u usocket] [-p pidfile] dest_addr\n\n", progname);
|
|
|
|
|
fprintf(stderr, " %s [-f] [-R] [-S] [-P] [-B bind_addr] [-s send_interval] [-l loss_interval] [-t time_period] [-r report_interval] [-d data_length] [-o output_file] [-A alert_interval] [-D latency_alarm] [-L loss_alarm] [-C alert_cmd] [-i identifier] [-u usocket] [-p pidfile] dest_addr\n\n", progname);
|
|
|
|
|
fprintf(stderr, " options:\n");
|
|
|
|
|
fprintf(stderr, " -f run in foreground\n");
|
|
|
|
|
fprintf(stderr, " -R rewind output file between reports\n");
|
|
|
|
|
fprintf(stderr, " -S log warnings via syslog\n");
|
|
|
|
|
fprintf(stderr, " -P priority scheduling for receive thread (requires root)\n");
|
|
|
|
|
fprintf(stderr, " -B bind (source) address\n");
|
|
|
|
|
fprintf(stderr, " -s time interval between echo requests (default 250ms)\n");
|
|
|
|
|
fprintf(stderr, " -l time interval before packets are treated as lost (default 5x send interval)\n");
|
|
|
|
|
fprintf(stderr, " -t time period over which results are averaged (default 30s)\n");
|
|
|
|
|
fprintf(stderr, " -s time interval between echo requests (default 500ms)\n");
|
|
|
|
|
fprintf(stderr, " -l time interval before packets are treated as lost (default 4x send interval)\n");
|
|
|
|
|
fprintf(stderr, " -t time period over which results are averaged (default 60s)\n");
|
|
|
|
|
fprintf(stderr, " -r time interval between reports (default 1s)\n");
|
|
|
|
|
fprintf(stderr, " -d data length (default 0)\n");
|
|
|
|
|
fprintf(stderr, " -o output file for reports (default stdout)\n");
|
|
|
|
@@ -866,14 +868,11 @@ fatal(
|
|
|
|
|
const char * format,
|
|
|
|
|
...)
|
|
|
|
|
{
|
|
|
|
|
if (format)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
|
vfprintf(stderr, format, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
}
|
|
|
|
|
va_start(args, format);
|
|
|
|
|
vfprintf(stderr, format, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
@@ -897,7 +896,7 @@ parse_args(
|
|
|
|
|
|
|
|
|
|
progname = argv[0];
|
|
|
|
|
|
|
|
|
|
while((opt = getopt(argc, argv, "fRSB:s:l:t:r:d:o:A:D:L:C:i:u:p:")) != -1)
|
|
|
|
|
while((opt = getopt(argc, argv, "fRSPB:s:l:t:r:d:o:A:D:L:C:i:u:p:")) != -1)
|
|
|
|
|
{
|
|
|
|
|
switch (opt)
|
|
|
|
|
{
|
|
|
|
@@ -913,6 +912,10 @@ parse_args(
|
|
|
|
|
flag_syslog = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'P':
|
|
|
|
|
flag_priority = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'B':
|
|
|
|
|
bind_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
@@ -1018,7 +1021,7 @@ parse_args(
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
usage();
|
|
|
|
|
fatal(NULL);
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1026,7 +1029,7 @@ parse_args(
|
|
|
|
|
if (argc != optind + 1)
|
|
|
|
|
{
|
|
|
|
|
usage();
|
|
|
|
|
fatal(NULL);
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
dest_arg = argv[optind];
|
|
|
|
|
|
|
|
|
@@ -1036,17 +1039,17 @@ parse_args(
|
|
|
|
|
fatal("no activity enabled\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ensure we have something to average over
|
|
|
|
|
if (time_period_msec < send_interval_msec)
|
|
|
|
|
// Ensure there is a minimum of one resolved slot at all times
|
|
|
|
|
if (time_period_msec <= send_interval_msec * 2 + loss_interval_msec)
|
|
|
|
|
{
|
|
|
|
|
fatal("time period cannot be less than send interval\n");
|
|
|
|
|
fatal("the time period must be greater than twice the send interval plus the loss interval\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ensure we don't have sequence space issues. This really should only be hit by
|
|
|
|
|
// complete accident. Even a ratio of 16384:1 would be excessive.
|
|
|
|
|
if (time_period_msec / send_interval_msec > 65536)
|
|
|
|
|
{
|
|
|
|
|
fatal("ratio of time period to send interval cannot exceed 65536:1\n");
|
|
|
|
|
fatal("the ratio of time period to send interval cannot exceed 65536:1\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check destination address
|
|
|
|
@@ -1320,7 +1323,7 @@ main(
|
|
|
|
|
// Set the default loss interval
|
|
|
|
|
if (loss_interval_msec == 0)
|
|
|
|
|
{
|
|
|
|
|
loss_interval_msec = send_interval_msec * 5;
|
|
|
|
|
loss_interval_msec = send_interval_msec * 4;
|
|
|
|
|
}
|
|
|
|
|
loss_interval_usec = loss_interval_msec * 1000;
|
|
|
|
|
|
|
|
|
@@ -1363,6 +1366,27 @@ main(
|
|
|
|
|
fatal("cannot create recv thread\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set priority on recv thread if requested
|
|
|
|
|
if (flag_priority)
|
|
|
|
|
{
|
|
|
|
|
struct sched_param thread_sched_param;
|
|
|
|
|
|
|
|
|
|
r = sched_get_priority_min(SCHED_RR);
|
|
|
|
|
if (r == -1)
|
|
|
|
|
{
|
|
|
|
|
perror("sched_get_priority_min");
|
|
|
|
|
fatal("cannot determin minimum shceduling priority for SCHED_RR\n");
|
|
|
|
|
}
|
|
|
|
|
thread_sched_param.sched_priority = r;
|
|
|
|
|
|
|
|
|
|
r = pthread_setschedparam(thread, SCHED_RR, &thread_sched_param);
|
|
|
|
|
if (r != 0)
|
|
|
|
|
{
|
|
|
|
|
perror("pthread_setschedparam");
|
|
|
|
|
fatal("cannot set receive thread priority\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create send thread
|
|
|
|
|
r = pthread_create(&thread, NULL, &send_thread, NULL);
|
|
|
|
|
if (r != 0)
|
|
|
|
|