the connection. Using large values for this, especially combined with
a short interval, will use up a lot of file descriptors.
.TP
+.B \-\-cache \fISECONDS
+Skip probes to hops that have replied within the last
+.IR SECONDS .
+This reduces probe traffic on stable paths, but cached hops keep their
+previous statistics until they are probed again.
+.TP
.B \-M \fIMARK\fR, \fB\-\-mark \fIMARK
Set the mark for each packet sent through this socket similar to the
netfilter MARK target but socket-based.
fputs(" -Q, --tos NUMBER type of service field in IP header\n", out);
fputs(" -e, --mpls display information from ICMP extensions\n", out);
fputs(" -Z, --timeout SECONDS seconds to keep probe sockets open\n", out);
+ fputs(" --cache SECONDS skip recently seen hops for SECONDS\n", out);
#ifdef SO_MARK
fputs(" -M, --mark MARK mark each sent packet\n", out);
#endif
OPT_IPINFO4 = CHAR_MAX + 2,
#ifdef ENABLE_IPV6
OPT_IPINFO6 = CHAR_MAX + 3,
+ OPT_CACHE = CHAR_MAX + 4,
+#else
+ OPT_CACHE = CHAR_MAX + 3,
#endif /* ifdef ENABLE_IPV6 */
};
static const struct option long_options[] = {
{"localport", 1, NULL, 'L'}, /* source port number for UDP */
{"timeout", 1, NULL, 'Z'}, /* timeout for probe sockets */
{"gracetime", 1, NULL, 'G'}, /* gracetime for replies after last probe */
+ {"cache", 1, NULL, OPT_CACHE}, /* skip probes to recently seen hops */
#ifdef SO_MARK
{"mark", 1, NULL, 'M'}, /* use SO_MARK */
#endif
error(EXIT_FAILURE, 0, "wait time must be positive");
}
break;
+ case OPT_CACHE:
+ ctl->cache_timeout =
+ strtoint_or_err(optarg, "invalid argument");
+ if (ctl->cache_timeout <= 0) {
+ error(EXIT_FAILURE, 0, "cache timeout must be positive");
+ }
+ ctl->cache = 1;
+ break;
case 'Q':
ctl->tos =
strtoint_or_err(optarg, "invalid argument");
ctl.MaxPing = 10;
ctl.WaitTime = 1.0;
ctl.GraceTime = 5.0;
+ ctl.cache_timeout = 60;
ctl.dns = 1;
ctl.use_dns = 1;
ctl.cpacketsize = 64;
int remoteport; /* target port for TCP tracing */
int localport; /* source port for UDP tracing */
int probe_timeout; /* timeout for probe sockets */
+ int cache_timeout; /* seconds to skip probes for recently seen hops */
unsigned char fld_active[2 * MAXFLD]; /* SO_MARK to set for ping packet */
int display_mode; /* display mode selector */
int fld_index[FLD_INDEX_SZ]; /* default display field (defined by key in net.h) and order */
void *gtk_data; /* pointer to hold arbitrary gtk data */
unsigned int /* bit field to hold named booleans */
ForceMaxPing:1,
- use_dns:1,
+ use_dns:1, cache:1,
show_ips:1,
enablempls:1, dns:1, reportwide:1, Interactive:1, DisplayMode:5, CompactLayout:1;
#ifdef HAVE_IPINFO
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
+#include <time.h>
#include <unistd.h>
#ifdef HAVE_ERROR_H
int jworst; /* max jitter */
int jinta; /* estimated variance,? rfc1889's "Interarrival Jitter" */
int transit;
+ time_t seen;
int saved[SAVED_PINGS];
int saved_seq_offset;
struct mplslen mpls;
nh->sent = 0;
nh->up = 1;
nh->transit = 0;
+ if (ctl->cache) {
+ nh->seen = time(NULL);
+ }
net_save_return(index, sequence[seq].saved_seq, totusec);
display_rawping(ctl, index, totusec, seq);
}
}
- net_send_query(ctl, batch_at, abs(packetsize));
+ if (!ctl->cache || !host[batch_at].up ||
+ host[batch_at].seen == 0 ||
+ time(NULL) - host[batch_at].seen > ctl->cache_timeout) {
+ net_send_query(ctl, batch_at, abs(packetsize));
+ }
for (i = ctl->fstTTL - 1; i < batch_at; i++) {
if (host_addr_cmp(i, &ctl->unspec_addr, ctl->af) == 0)