- The -g, --generate option now also supports IPv6 addresses (#376,
thanks @auerswal)
+- New option --seqmap-timeout to control the time after which sequence numbers
+ can be used again (#388, thanks @auerswal)
+
## Bugfixes and other changes
- Fix OpenBSD warning sprintf() is often misused, please use snprintf() (#394, thanks @gsnw-sebast)
#!/usr/bin/perl -w
-use Test::Command tests => 36;
+use Test::Command tests => 39;
# fping -i 0
my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29");
$cmd10->stderr_is_eq("fping: backoff factor 5.1 not valid, must be between 1.0 and 5.0\n");
# non-negative only
-for my $arg (qw(i p Q t)) {
+for my $arg (qw(i p Q t -seqmap-timeout)) {
my $cmd = Test::Command->new(cmd => "fping -$arg -1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
#!/usr/bin/perl -w
-use Test::Command tests => 30;
+use Test::Command tests => 36;
use Test::More;
# -R random bytes
$cmd->stderr_is_eq("fping: can't parse source address: bla\n");
}
+# fping --seqmap-timeout N
+{
+my $cmd = Test::Command->new(cmd => "fping --seqmap-timeout 20000 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_is_eq("127.0.0.1 is alive\n");
+$cmd->stderr_is_eq("");
+}
+
+# fping --seqmap-timeout N
+{
+my $cmd = Test::Command->new(cmd => "fping --seqmap-timeout 0 127.0.0.1");
+$cmd->exit_is_num(1);
+$cmd->stdout_is_eq("127.0.0.1 is unreachable\n");
+$cmd->stderr_is_eq("");
+}
+
# (note: fping -t also tested in test-4-options-a-b.pl)
#!/usr/bin/perl -w
-use Test::Command tests => 84;
+use Test::Command tests => 90;
use Test::More;
# some options require a numeric argument
-for my $arg (qw(b B c C H i O p Q r t x X)) {
+for my $arg (qw(b B c C H i O p Q r t x X -seqmap-timeout)) {
for my $test_input (qw(xxx '')) {
my $cmd = Test::Command->new(cmd => "fping -$arg $test_input");
$cmd->exit_is_num(1);
Set source address.
+=item B<--seqmap-timeout>=I<MSEC>
+
+Timeout for sequence number mappings in milliseconds. Sequence numbers can
+be reused after the timeout. The default value is 10000ms.
+
=item B<-t>, B<--timeout>=I<MSEC>
Initial target timeout in milliseconds. In the default, non-loop mode, the
/* all time-related values are int64_t nanoseconds */
unsigned int retry = DEFAULT_RETRY;
int64_t timeout = (int64_t)DEFAULT_TIMEOUT * 1000000;
+int64_t seqmap_timeout = (int64_t)DEFAULT_SEQMAP_TIMEOUT * 1000000;
int64_t interval = (int64_t)DEFAULT_INTERVAL * 1000000;
int64_t perhost_interval = (int64_t)DEFAULT_PERHOST_INTERVAL * 1000000;
float backoff = DEFAULT_BACKOFF_FACTOR;
{ "check-source", '0', OPTPARSE_NONE },
{ "print-tos", '0', OPTPARSE_NONE },
{ "print-ttl", '0', OPTPARSE_NONE },
+ { "seqmap-timeout", '0', OPTPARSE_REQUIRED },
#if defined(DEBUG) || defined(_DEBUG)
{ NULL, 'z', OPTPARSE_REQUIRED },
#endif
}
}
#endif
+ } else if (strstr(optparse_state.optlongname, "seqmap-timeout") != NULL) {
+ if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
+ usage(1);
+ if (opt_value_float < 0)
+ usage(1);
+ seqmap_timeout = opt_value_float * 1000000;
} else {
usage(1);
}
prog, count, retry, interval / 1e6);
fprintf(stderr, " perhost_interval: %.0f ms, timeout: %.0f\n",
perhost_interval / 1e6, timeout / 1e6);
+ fprintf(stderr, " seqmap_timeout: %.0f\n", seqmap_timeout / 1e6);
fprintf(stderr, " ping_data_size = %u, trials = %u\n",
ping_data_size, trials);
last_send_time = 0;
- seqmap_init();
+ seqmap_init(seqmap_timeout);
/* main loop */
main_loop();
fprintf(out, " -r, --retry=N number of retries (default: %d)\n", DEFAULT_RETRY);
fprintf(out, " -R, --random random packet data (to foil link data compression)\n");
fprintf(out, " -S, --src=IP set source address\n");
+ fprintf(out, " --seqmap-timeout=MSEC sequence number mapping timeout (default: %.0f ms)\n", seqmap_timeout / 1e6);
fprintf(out, " -t, --timeout=MSEC individual target initial timeout (default: %.0f ms,\n", timeout / 1e6);
fprintf(out, " except with -l/-c/-C, where it's the -p period up to 2000 ms)\n");
fprintf(out, " --check-source discard replies not from target address\n");
#define AUTOTUNE_TIMEOUT_MAX 2000
#endif
+/* default time in milliseconds before a sequence number can be used again */
+#ifndef DEFAULT_SEQMAP_TIMEOUT
+#define DEFAULT_SEQMAP_TIMEOUT 10000
+#endif
#ifndef DEFAULT_RETRY
#define DEFAULT_RETRY 3 /* number of times to retry a host */
/* description of the data structure used:
*
* - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in
- * the timeout interval (SEQMAP_TIMEOUT_IN_NS)
+ * the timeout interval (seqmap_timeout_in_ns)
* - we store the values in an array with SEQMAP_MAXSEQ elements
* - current sequence number % SEQMAP_MAXSEQ gives the current index
* - when entering a value, we check that the current entry is expired
static SEQMAP_VALUE* seqmap_map = NULL;
static unsigned int seqmap_next_id = 0;
+static int64_t seqmap_timeout_in_ns;
-#define SEQMAP_TIMEOUT_IN_NS INT64_C(10000000000)
#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
-void seqmap_init()
+void seqmap_init(int64_t timeout)
{
+ seqmap_timeout_in_ns = timeout;
seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE));
if (seqmap_map == NULL) {
perror("malloc error (can't allocate seqmap_map)");
/* check if expired (note that unused seqmap values will have fields set to
* 0, so will be seen as expired */
next_value = &seqmap_map[seqmap_next_id];
- if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) {
+ if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < seqmap_timeout_in_ns) {
fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
- SEQMAP_TIMEOUT_IN_NS, host_nr, ping_count, seqmap_next_id);
+ seqmap_timeout_in_ns, host_nr, ping_count, seqmap_next_id);
exit(4);
}
value = &seqmap_map[id];
/* verify that value is not expired */
- if (now - value->ping_ts >= SEQMAP_TIMEOUT_IN_NS) {
+ if (now - value->ping_ts >= seqmap_timeout_in_ns) {
dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d -> DISCARDED %ld\n", id, value->host_nr, value->ping_count,
now - value->ping_ts);
return NULL;
#define SEQMAP_MAXSEQ 65535
-void seqmap_init();
+void seqmap_init(int64_t timeout);
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t now);
SEQMAP_VALUE *seqmap_fetch(unsigned int id, int64_t now);