From: yvs Date: Fri, 8 May 2026 12:59:36 +0000 (+0400) Subject: options: add cache mode for known hops X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=refs%2Fpull%2F623%2Fhead;p=thirdparty%2Fmtr.git options: add cache mode for known hops Port the mtr085 cache mode as a long-only option for current upstream. Upstream already uses -x for XML output, so this keeps the user-facing short-option namespace unchanged and exposes only --cache SECONDS. Ported-from: yvs2014/mtr085@0700269ce0f3f501fc33ec98176101f2f4f733eb Ported-from: yvs2014/mtr085@0cab98cf8d2e0648f8e1bdd52da5d3122d3c091d Original-author: yvs --- diff --git a/man/mtr.8.in b/man/mtr.8.in index 35bc545..d94421c 100644 --- a/man/mtr.8.in +++ b/man/mtr.8.in @@ -486,6 +486,12 @@ The number of seconds to keep probe sockets open before giving up on 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. diff --git a/ui/mtr.c b/ui/mtr.c index 32fbc75..4bf9190 100644 --- a/ui/mtr.c +++ b/ui/mtr.c @@ -121,6 +121,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out) 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 @@ -363,6 +364,9 @@ static void parse_arg( 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[] = { @@ -428,6 +432,7 @@ static void parse_arg( {"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 @@ -608,6 +613,14 @@ static void parse_arg( 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"); @@ -929,6 +942,7 @@ int main( 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; diff --git a/ui/mtr.h b/ui/mtr.h index b71b43a..7af3dcc 100644 --- a/ui/mtr.h +++ b/ui/mtr.h @@ -108,6 +108,7 @@ struct mtr_ctl { 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 */ @@ -117,7 +118,7 @@ struct mtr_ctl { 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 diff --git a/ui/net.c b/ui/net.c index ed71a56..3c82cd3 100644 --- a/ui/net.c +++ b/ui/net.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef HAVE_ERROR_H @@ -65,6 +66,7 @@ struct nethost { 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; @@ -325,6 +327,9 @@ static void net_process_ping( 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); @@ -588,7 +593,11 @@ int net_send_batch( } } - 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)