Skip to content

Commit 1da5450

Browse files
committed
new option --seqmap-timeout=MSEC
This allows to control the time after which sequence numbers can be reused for new probe packets. This is intended to help using count or loop modes with tens of thousands of target hosts. See GH issue #385 for more information.
1 parent fb6f8b5 commit 1da5450

File tree

9 files changed

+52
-13
lines changed

9 files changed

+52
-13
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ Next
66
- The -g, --generate option now also supports IPv6 addresses (#376,
77
thanks @auerswal)
88

9+
- New option --seqmap-timeout to control the time after which sequence numbers
10+
can be used again (#388, thanks @auerswal)
11+
912
## Bugfixes and other changes
1013

1114
- Fix OpenBSD warning sprintf() is often misused, please use snprintf() (#394, thanks @gsnw-sebast)

ci/test-03-forbidden.pl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/perl -w
22

3-
use Test::Command tests => 36;
3+
use Test::Command tests => 39;
44

55
# fping -i 0
66
my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29");
@@ -57,7 +57,7 @@ END
5757
$cmd10->stderr_is_eq("fping: backoff factor 5.1 not valid, must be between 1.0 and 5.0\n");
5858

5959
# non-negative only
60-
for my $arg (qw(i p Q t)) {
60+
for my $arg (qw(i p Q t -seqmap-timeout)) {
6161
my $cmd = Test::Command->new(cmd => "fping -$arg -1");
6262
$cmd->exit_is_num(1);
6363
$cmd->stdout_is_eq("");

ci/test-09-option-r-t.pl

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/perl -w
22

3-
use Test::Command tests => 30;
3+
use Test::Command tests => 36;
44
use Test::More;
55

66
# -R random bytes
@@ -146,4 +146,20 @@
146146
$cmd->stderr_is_eq("fping: can't parse source address: bla\n");
147147
}
148148

149+
# fping --seqmap-timeout N
150+
{
151+
my $cmd = Test::Command->new(cmd => "fping --seqmap-timeout 20000 127.0.0.1");
152+
$cmd->exit_is_num(0);
153+
$cmd->stdout_is_eq("127.0.0.1 is alive\n");
154+
$cmd->stderr_is_eq("");
155+
}
156+
157+
# fping --seqmap-timeout N
158+
{
159+
my $cmd = Test::Command->new(cmd => "fping --seqmap-timeout 0 127.0.0.1");
160+
$cmd->exit_is_num(1);
161+
$cmd->stdout_is_eq("127.0.0.1 is unreachable\n");
162+
$cmd->stderr_is_eq("");
163+
}
164+
149165
# (note: fping -t also tested in test-4-options-a-b.pl)

ci/test-12-option-type.pl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#!/usr/bin/perl -w
22

3-
use Test::Command tests => 84;
3+
use Test::Command tests => 90;
44
use Test::More;
55

66
# some options require a numeric argument
7-
for my $arg (qw(b B c C H i O p Q r t x X)) {
7+
for my $arg (qw(b B c C H i O p Q r t x X -seqmap-timeout)) {
88
for my $test_input (qw(xxx '')) {
99
my $cmd = Test::Command->new(cmd => "fping -$arg $test_input");
1010
$cmd->exit_is_num(1);

doc/fping.pod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ Print cumulative statistics upon exit.
241241

242242
Set source address.
243243

244+
=item B<--seqmap-timeout>=I<MSEC>
245+
246+
Timeout for sequence number mappings in milliseconds. Sequence numbers can
247+
be reused after the timeout. The default value is 10000ms.
248+
244249
=item B<-t>, B<--timeout>=I<MSEC>
245250

246251
Initial target timeout in milliseconds. In the default, non-loop mode, the

src/fping.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ unsigned int debugging = 0;
317317
/* all time-related values are int64_t nanoseconds */
318318
unsigned int retry = DEFAULT_RETRY;
319319
int64_t timeout = (int64_t)DEFAULT_TIMEOUT * 1000000;
320+
int64_t seqmap_timeout = (int64_t)DEFAULT_SEQMAP_TIMEOUT * 1000000;
320321
int64_t interval = (int64_t)DEFAULT_INTERVAL * 1000000;
321322
int64_t perhost_interval = (int64_t)DEFAULT_PERHOST_INTERVAL * 1000000;
322323
float backoff = DEFAULT_BACKOFF_FACTOR;
@@ -578,6 +579,7 @@ int main(int argc, char **argv)
578579
{ "check-source", '0', OPTPARSE_NONE },
579580
{ "print-tos", '0', OPTPARSE_NONE },
580581
{ "print-ttl", '0', OPTPARSE_NONE },
582+
{ "seqmap-timeout", '0', OPTPARSE_REQUIRED },
581583
#if defined(DEBUG) || defined(_DEBUG)
582584
{ NULL, 'z', OPTPARSE_REQUIRED },
583585
#endif
@@ -638,6 +640,12 @@ int main(int argc, char **argv)
638640
}
639641
}
640642
#endif
643+
} else if (strstr(optparse_state.optlongname, "seqmap-timeout") != NULL) {
644+
if (sscanf(optparse_state.optarg, "%f", &opt_value_float) != 1)
645+
usage(1);
646+
if (opt_value_float < 0)
647+
usage(1);
648+
seqmap_timeout = opt_value_float * 1000000;
641649
} else {
642650
usage(1);
643651
}
@@ -1077,6 +1085,7 @@ int main(int argc, char **argv)
10771085
prog, count, retry, interval / 1e6);
10781086
fprintf(stderr, " perhost_interval: %.0f ms, timeout: %.0f\n",
10791087
perhost_interval / 1e6, timeout / 1e6);
1088+
fprintf(stderr, " seqmap_timeout: %.0f\n", seqmap_timeout / 1e6);
10801089
fprintf(stderr, " ping_data_size = %u, trials = %u\n",
10811090
ping_data_size, trials);
10821091

@@ -1355,7 +1364,7 @@ int main(int argc, char **argv)
13551364

13561365
last_send_time = 0;
13571366

1358-
seqmap_init();
1367+
seqmap_init(seqmap_timeout);
13591368

13601369
/* main loop */
13611370
main_loop();
@@ -3446,6 +3455,7 @@ void usage(int is_error)
34463455
fprintf(out, " -r, --retry=N number of retries (default: %d)\n", DEFAULT_RETRY);
34473456
fprintf(out, " -R, --random random packet data (to foil link data compression)\n");
34483457
fprintf(out, " -S, --src=IP set source address\n");
3458+
fprintf(out, " --seqmap-timeout=MSEC sequence number mapping timeout (default: %.0f ms)\n", seqmap_timeout / 1e6);
34493459
fprintf(out, " -t, --timeout=MSEC individual target initial timeout (default: %.0f ms,\n", timeout / 1e6);
34503460
fprintf(out, " except with -l/-c/-C, where it's the -p period up to 2000 ms)\n");
34513461
fprintf(out, " --check-source discard replies not from target address\n");

src/options.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
#define AUTOTUNE_TIMEOUT_MAX 2000
3333
#endif
3434

35+
/* default time in milliseconds before a sequence number can be used again */
36+
#ifndef DEFAULT_SEQMAP_TIMEOUT
37+
#define DEFAULT_SEQMAP_TIMEOUT 10000
38+
#endif
3539

3640
#ifndef DEFAULT_RETRY
3741
#define DEFAULT_RETRY 3 /* number of times to retry a host */

src/seqmap.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,21 @@
4848
/* description of the data structure used:
4949
*
5050
* - we assume that no more than SEQMAP_MAXSEQ (65535) pings are sent in
51-
* the timeout interval (SEQMAP_TIMEOUT_IN_NS)
51+
* the timeout interval (seqmap_timeout_in_ns)
5252
* - we store the values in an array with SEQMAP_MAXSEQ elements
5353
* - current sequence number % SEQMAP_MAXSEQ gives the current index
5454
* - when entering a value, we check that the current entry is expired
5555
*/
5656

5757
static SEQMAP_VALUE* seqmap_map = NULL;
5858
static unsigned int seqmap_next_id = 0;
59+
static int64_t seqmap_timeout_in_ns;
5960

60-
#define SEQMAP_TIMEOUT_IN_NS INT64_C(10000000000)
6161
#define SEQMAP_UNASSIGNED_HOST_NR UINT_MAX
6262

63-
void seqmap_init()
63+
void seqmap_init(int64_t timeout)
6464
{
65+
seqmap_timeout_in_ns = timeout;
6566
seqmap_map = calloc(SEQMAP_MAXSEQ, sizeof(SEQMAP_VALUE));
6667
if (seqmap_map == NULL) {
6768
perror("malloc error (can't allocate seqmap_map)");
@@ -81,9 +82,9 @@ unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t t
8182
/* check if expired (note that unused seqmap values will have fields set to
8283
* 0, so will be seen as expired */
8384
next_value = &seqmap_map[seqmap_next_id];
84-
if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < SEQMAP_TIMEOUT_IN_NS) {
85+
if (next_value->ping_ts != 0 && timestamp - next_value->ping_ts < seqmap_timeout_in_ns) {
8586
fprintf(stderr, "fping error: not enough sequence numbers available! (expire_timeout=%" PRId64 ", host_nr=%d, ping_count=%d, seqmap_next_id=%d)\n",
86-
SEQMAP_TIMEOUT_IN_NS, host_nr, ping_count, seqmap_next_id);
87+
seqmap_timeout_in_ns, host_nr, ping_count, seqmap_next_id);
8788
exit(4);
8889
}
8990

@@ -112,7 +113,7 @@ SEQMAP_VALUE* seqmap_fetch(unsigned int id, int64_t now)
112113
value = &seqmap_map[id];
113114

114115
/* verify that value is not expired */
115-
if (now - value->ping_ts >= SEQMAP_TIMEOUT_IN_NS) {
116+
if (now - value->ping_ts >= seqmap_timeout_in_ns) {
116117
dbg_printf("seqmap_fetch(%d) -> host: %d, index: %d -> DISCARDED %ld\n", id, value->host_nr, value->ping_count,
117118
now - value->ping_ts);
118119
return NULL;

src/seqmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ typedef struct seqmap_value
1414

1515
#define SEQMAP_MAXSEQ 65535
1616

17-
void seqmap_init();
17+
void seqmap_init(int64_t timeout);
1818
unsigned int seqmap_add(unsigned int host_nr, unsigned int ping_count, int64_t now);
1919
SEQMAP_VALUE *seqmap_fetch(unsigned int id, int64_t now);
2020

0 commit comments

Comments
 (0)