From: Eric Dumazet <edumazet@google.com>
To: David Ahern <dsahern@kernel.org>,
Stephen Hemminger <stephen@networkplumber.org>
Cc: "David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>,
Kuniyuki Iwashima <kuniyu@google.com>,
netdev@vger.kernel.org, eric.dumazet@gmail.com,
Eric Dumazet <edumazet@google.com>
Subject: [PATCH iproute2-next] utils: add fflush_monitor() helper
Date: Fri, 24 Apr 2026 17:11:51 +0000 [thread overview]
Message-ID: <20260424171151.1190882-1-edumazet@google.com> (raw)
Some fflush() calls only make sense for monitor programs.
For other cases, forcing a flush is expensive.
After this patch, ip, tc and ss are correctly buffering their
output when redirected to a file.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/utils.h | 7 +++++++
ip/ipaddress.c | 12 +++++++-----
ip/iplink.c | 4 ++--
ip/ipmonitor.c | 1 +
ip/iproute.c | 4 ++--
lib/utils.c | 1 +
misc/ss.c | 3 ++-
tc/tc_class.c | 2 +-
tc/tc_filter.c | 2 +-
tc/tc_monitor.c | 1 +
tc/tc_qdisc.c | 2 +-
11 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/include/utils.h b/include/utils.h
index b68d6bc4edcf9ca335148f731cd240871b6c809b..9099a78b1593738c5ba181274d784d0a1913407a 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -38,6 +38,7 @@ extern int numeric;
extern bool do_all;
extern int echo_request;
extern int use_iec;
+extern int monitor_mode;
#define SPRINT_BSIZE 64
#define SPRINT_BUF(x) char x[SPRINT_BSIZE]
@@ -399,4 +400,10 @@ FILE *generic_proc_open(const char *env, const char *name);
int open_fds_add(int fd);
void open_fds_close(void);
+static inline void fflush_monitor(FILE *fp)
+{
+ if (monitor_mode)
+ fflush_monitor(fp);
+}
+
#endif /* __UTILS_H__ */
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 4d93a04a8555e141ae30a4aaeb42ac607a181c9b..14aa98e77452c9681c9d3660f6a882df56b44f1c 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -894,7 +894,7 @@ static int print_linkinfo_brief(FILE *fp, const char *name,
print_string(PRINT_FP, NULL, "%s", "\n");
}
- fflush(fp);
+ fflush_monitor(fp);
return 0;
}
@@ -1346,10 +1346,12 @@ int print_linkinfo(struct nlmsghdr *n, void *arg)
}
print_string(PRINT_FP, NULL, "%s", "\n");
- fflush(fp);
+ fflush_monitor(fp);
/* prettier here if stderr and stdout go to the same place */
- if (truncated_vfs)
+ if (truncated_vfs) {
+ fflush(fp);
fprintf(stderr, "Truncated VF list: %s\n", name);
+ }
return 1;
}
@@ -1732,7 +1734,7 @@ int print_addrinfo(struct nlmsghdr *n, void *arg)
}
print_string(PRINT_FP, NULL, "%s", "\n");
brief_exit:
- fflush(fp);
+ fflush_monitor(fp);
return 0;
}
@@ -1768,7 +1770,7 @@ static int print_selected_addrinfo(struct ifinfomsg *ifi,
if (brief) {
print_string(PRINT_FP, NULL, "%s", "\n");
- fflush(fp);
+ fflush_monitor(fp);
}
return 0;
}
diff --git a/ip/iplink.c b/ip/iplink.c
index fce6631d2d821a8739d28805e13d98f6804bda30..806f86987ed7c8af5ddd40f04a44fb8ce8debfaf 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -1296,7 +1296,7 @@ static void print_mpls_stats(FILE *fp, struct rtattr *attr)
print_nl();
print_mpls_link_stats(fp, stats, " ");
print_string(PRINT_FP, NULL, "%s", "\n");
- fflush(fp);
+ fflush_monitor(fp);
}
static void print_af_stats_attr(FILE *fp, int ifindex, struct rtattr *attr)
@@ -1359,7 +1359,7 @@ static int print_af_stats(struct nlmsghdr *n, void *arg)
if (tb[IFLA_STATS_AF_SPEC])
print_af_stats_attr(fp, ifsm->ifindex, tb[IFLA_STATS_AF_SPEC]);
- fflush(fp);
+ fflush_monitor(fp);
return 0;
}
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
index 1f4e860f8d6726edffcf9bf81636c6555757dd09..23bd667a2f7a27e620d0f6dd13a16476c1ac0d08 100644
--- a/ip/ipmonitor.c
+++ b/ip/ipmonitor.c
@@ -324,6 +324,7 @@ int do_ipmonitor(int argc, char **argv)
return err;
}
+ monitor_mode = 1;
if (rtnl_open(&rth, groups) < 0)
exit(1);
diff --git a/ip/iproute.c b/ip/iproute.c
index c2538894da633b56f5b926ecafda4960a48e9fbd..c6a6ba9dd37076acfceb9b259874a50e7cd3c3d0 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -1012,7 +1012,7 @@ int print_route(struct nlmsghdr *n, void *arg)
print_string(PRINT_FP, NULL, "\n", NULL);
close_json_object();
- fflush(fp);
+ fflush_monitor(fp);
return 0;
}
@@ -2035,7 +2035,7 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
}
delete_json_obj();
- fflush(stdout);
+ fflush_monitor(stdout);
return 0;
}
diff --git a/lib/utils.c b/lib/utils.c
index 1215fe31cb3f63c0fa768fef60da77a641c51581..7017b0e6afacd8e770fb9f8b26aa5a319c1279e7 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -41,6 +41,7 @@ int timestamp_short;
int pretty;
int use_iec;
int human_readable;
+int monitor_mode;
const char *_SL_ = "\n";
static int open_fds[5];
diff --git a/misc/ss.c b/misc/ss.c
index 14e9f27a75321556240a5f290b8bcf51c605a4c2..0f9b37177d375ddf70cb34674992723b5c4883be 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -5544,7 +5544,7 @@ static int generic_show_sock(struct nlmsghdr *nlh, void *arg)
render();
- fflush(stdout);
+ fflush_monitor(stdout);
return ret;
}
@@ -5580,6 +5580,7 @@ static int handle_follow_request(struct filter *f)
f->rth_for_killing = &rth2;
}
+ monitor_mode = 1;
if (rtnl_dump_filter(&rth, generic_show_sock, f))
ret = -1;
diff --git a/tc/tc_class.c b/tc/tc_class.c
index 6d707d8c924f4b5e90201d4de8e9779f82ce17f3..8197566281fad47d4efcf4768ed406ab809dd08a 100644
--- a/tc/tc_class.c
+++ b/tc/tc_class.c
@@ -380,7 +380,7 @@ int print_class(struct nlmsghdr *n, void *arg)
close_json_object();
}
close_json_object();
- fflush(fp);
+ fflush_monitor(fp);
return 0;
}
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index 7db850bda11a3408ec66b457c9fc590f3a734f65..633f027d79865d98ba1ccba48af71d247dfc7a48 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -374,7 +374,7 @@ int print_filter(struct nlmsghdr *n, void *arg)
print_ext_msg(tb);
close_json_object();
- fflush(fp);
+ fflush_monitor(fp);
return 0;
}
diff --git a/tc/tc_monitor.c b/tc/tc_monitor.c
index 5b9bccbed4140241a4d7a5cffc50865106224867..49bd4b6a460fbfe41a35e06f92f07dbe56a6be2d 100644
--- a/tc/tc_monitor.c
+++ b/tc/tc_monitor.c
@@ -100,6 +100,7 @@ int do_tcmonitor(int argc, char **argv)
return ret;
}
+ monitor_mode = 1;
if (rtnl_open(&rth, groups) < 0)
exit(1);
diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c
index 7eb9a31baa31fb91a8141c9eca1135e76a52fa8b..a8ef8fc9f70d91609d6ed61c2a46b29120512fd2 100644
--- a/tc/tc_qdisc.c
+++ b/tc/tc_qdisc.c
@@ -344,7 +344,7 @@ int print_qdisc(struct nlmsghdr *n, void *arg)
print_ext_msg(tb);
close_json_object();
- fflush(fp);
+ fflush_monitor(fp);
return 0;
}
--
2.54.0.545.g6539524ca2-goog
next reply other threads:[~2026-04-24 17:11 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-24 17:11 Eric Dumazet [this message]
2026-04-24 19:30 ` [PATCH iproute2-next] utils: add fflush_monitor() helper David Ahern
2026-04-27 7:39 ` Eric Dumazet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260424171151.1190882-1-edumazet@google.com \
--to=edumazet@google.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=eric.dumazet@gmail.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stephen@networkplumber.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox