* [PATCH iproute2-next v2 0/3] ip mptcp monitor: add JSON support
@ 2026-02-23 15:28 Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 1/3] mptcp: uniform stream closure Matthieu Baerts (NGI0)
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Matthieu Baerts (NGI0) @ 2026-02-23 15:28 UTC (permalink / raw)
To: Stephen Hemminger, David Ahern; +Cc: netdev, mptcp, Matthieu Baerts (NGI0)
With this series, the command 'ip [-t[s]] mptcp monitor' produces an
output with the JSON format.
- Patch 1: a small refactoring to uniform the code.
- Patch 2: add JSON support in print_timestamp() helper.
- Patch 3: add JSON support to 'ip mptcp monitor' as requested by
Stephen.
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
Changes in v2:
- Patch 1: clearly mention the "fix".
- Patch 2: ignore argument.
- Patch 3: print token with 0xhex, use atexit().
- Link to v1: https://patch.msgid.link/20260220-ipr-monitor-json-v1-0-eb4b0d5f7820@kernel.org
---
Matthieu Baerts (NGI0) (3):
mptcp: uniform stream closure
utils: timestamp: add JSON support
mptcp: monitor: add JSON support
ip/ipmptcp.c | 94 +++++++++++++++++++++++++++++++++++++++++-------------------
lib/utils.c | 12 ++++----
2 files changed, 71 insertions(+), 35 deletions(-)
---
base-commit: f120cdb35da76ca99932d0428a0917bd01a843da
change-id: 20260220-ipr-monitor-json-1573371524c1
Best regards,
--
Matthieu Baerts (NGI0) <matttbe@kernel.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH iproute2-next v2 1/3] mptcp: uniform stream closure
2026-02-23 15:28 [PATCH iproute2-next v2 0/3] ip mptcp monitor: add JSON support Matthieu Baerts (NGI0)
@ 2026-02-23 15:28 ` Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 2/3] utils: timestamp: add JSON support Matthieu Baerts (NGI0)
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Matthieu Baerts (NGI0) @ 2026-02-23 15:28 UTC (permalink / raw)
To: Stephen Hemminger, David Ahern; +Cc: netdev, mptcp, Matthieu Baerts (NGI0)
Use print_nl() instead of print_string(), close the json object, then flush
the stream to flush the end of the JSON object ASAP.
Note that in print_mptcp_limit(), the flush should have been done before
closing the JSON object, but because there is only one object and the
closure was done just before exiting, there was no visual impact.
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
ip/ipmptcp.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/ip/ipmptcp.c b/ip/ipmptcp.c
index ec9ef62a..18ec05a8 100644
--- a/ip/ipmptcp.c
+++ b/ip/ipmptcp.c
@@ -273,8 +273,8 @@ static int print_mptcp_addrinfo(struct rtattr *addrinfo)
}
}
+ print_nl();
close_json_object();
- print_string(PRINT_FP, NULL, "\n", NULL);
fflush(stdout);
return 0;
@@ -426,9 +426,11 @@ static int print_mptcp_limit(struct nlmsghdr *n, void *arg)
print_uint(PRINT_ANY, "subflows", "subflows %d ", val);
}
- print_string(PRINT_FP, NULL, "%s", "\n");
- fflush(stdout);
+
+ print_nl();
close_json_object();
+ fflush(stdout);
+
return 0;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH iproute2-next v2 2/3] utils: timestamp: add JSON support
2026-02-23 15:28 [PATCH iproute2-next v2 0/3] ip mptcp monitor: add JSON support Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 1/3] mptcp: uniform stream closure Matthieu Baerts (NGI0)
@ 2026-02-23 15:28 ` Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 3/3] mptcp: monitor: " Matthieu Baerts (NGI0)
2026-02-25 16:30 ` [PATCH iproute2-next v2 0/3] ip mptcp " patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: Matthieu Baerts (NGI0) @ 2026-02-23 15:28 UTC (permalink / raw)
To: Stephen Hemminger, David Ahern; +Cc: netdev, mptcp, Matthieu Baerts (NGI0)
Supporting JSON is easy with the helpers. The biggest modification is to
extract the end value. Different keys are used depending on the short or
long timestamp option being used, to ease the parsing.
No behavioural changes intended for the moment, this is a preparation for a
future usage of print_timestamp() within a JSON context.
Like in other helpers supporting JSON, the output stream 'fp' is ignored,
which is fine, because it is always set to 'stdout'.
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
v2: ignore 'fp' which is always set to 'stdout' (Stephen)
---
lib/utils.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/lib/utils.c b/lib/utils.c
index 13e8c098..1215fe31 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1277,21 +1277,23 @@ int print_timestamp(FILE *fp)
{
struct timeval tv;
struct tm *tm;
+ char ts[40];
gettimeofday(&tv, NULL);
tm = localtime(&tv.tv_sec);
if (timestamp_short) {
- char tshort[40];
+ size_t len;
- strftime(tshort, sizeof(tshort), "%Y-%m-%dT%H:%M:%S", tm);
- fprintf(fp, "[%s.%06ld] ", tshort, tv.tv_usec);
+ len = strftime(ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tm);
+ snprintf(ts + len, sizeof(ts) - len, ".%06ld", tv.tv_usec);
+ print_string(PRINT_ANY, "timestamp_short", "[%s] ", ts);
} else {
char *tstr = asctime(tm);
tstr[strlen(tstr)-1] = 0;
- fprintf(fp, "Timestamp: %s %ld usec\n",
- tstr, tv.tv_usec);
+ snprintf(ts, sizeof(ts), "%s %ld usec", tstr, tv.tv_usec);
+ print_string(PRINT_ANY, "timestamp", "Timestamp: %s\n", ts);
}
return 0;
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH iproute2-next v2 3/3] mptcp: monitor: add JSON support
2026-02-23 15:28 [PATCH iproute2-next v2 0/3] ip mptcp monitor: add JSON support Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 1/3] mptcp: uniform stream closure Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 2/3] utils: timestamp: add JSON support Matthieu Baerts (NGI0)
@ 2026-02-23 15:28 ` Matthieu Baerts (NGI0)
2026-02-25 16:30 ` [PATCH iproute2-next v2 0/3] ip mptcp " patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: Matthieu Baerts (NGI0) @ 2026-02-23 15:28 UTC (permalink / raw)
To: Stephen Hemminger, David Ahern; +Cc: netdev, mptcp, Matthieu Baerts (NGI0)
The command 'ip [-t[s]] mptcp monitor' now produces an output with the JSON
format.
The previous text output has been preserved.
The JSON support has been added thanks to the print_*() helpers. Note that
it is also needed to add a signal handler to exit without errors in case of
SIGINT or SIGTERM, and close the JSON. This last step will print the final
']' when stopping 'ip -j mptcp monitor'.
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
v2:
- print token with print_0xhex(), and add missing space after ',' (AI)
- use atexit() to close the JSON (Stephen)
- always call delete_json_obj(): nothing is done when JSON is not used.
---
ip/ipmptcp.c | 86 +++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 59 insertions(+), 27 deletions(-)
diff --git a/ip/ipmptcp.c b/ip/ipmptcp.c
index 18ec05a8..3df89db5 100644
--- a/ip/ipmptcp.c
+++ b/ip/ipmptcp.c
@@ -2,6 +2,7 @@
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -476,8 +477,9 @@ static void print_addr(const char *key, int af, struct rtattr *value)
char str[INET6_ADDRSTRLEN];
if (inet_ntop(af, data, str, sizeof(str))) {
- printf(" %s=", key);
- color_fprintf(stdout, ifa_family_color(af), "%s", str);
+ print_string(PRINT_FP, NULL, " %s=", key);
+ print_color_string(PRINT_ANY, ifa_family_color(af), key, "%s",
+ str);
}
}
@@ -485,12 +487,13 @@ static void print_iface(int index)
{
const char *ifname;
- printf(" ifindex=%d", index);
+ print_int(PRINT_ANY, "ifindex", " ifindex=%d", index);
ifname = index ? ll_index_to_name(index) : NULL;
if (ifname) {
- printf(" dev=");
- color_fprintf(stdout, COLOR_IFNAME, "%s", ifname);
+ print_string(PRINT_FP, NULL, " dev=", NULL);
+ print_color_string(PRINT_ANY, COLOR_IFNAME, "dev", "%s",
+ ifname);
}
}
@@ -509,30 +512,34 @@ static int mptcp_monitor_msg(struct rtnl_ctrl_data *ctrl,
if (n->nlmsg_type != genl_family)
return 0;
+ open_json_object(NULL);
+
if (timestamp)
print_timestamp(stdout);
- if (ghdr->cmd >= ARRAY_SIZE(event_to_str)) {
- printf("[UNKNOWN %u]\n", ghdr->cmd);
+ if (ghdr->cmd >= ARRAY_SIZE(event_to_str) ||
+ event_to_str[ghdr->cmd] == NULL) {
+ char event[40];
+
+ snprintf(event, sizeof(event), "UNKNOWN %u", ghdr->cmd);
+ print_string(PRINT_ANY, "event", "[%s]", event);
goto out;
}
- if (event_to_str[ghdr->cmd] == NULL) {
- printf("[UNKNOWN %u]\n", ghdr->cmd);
- goto out;
- }
-
- printf("[%16s]", event_to_str[ghdr->cmd]);
+ print_string(PRINT_ANY, "event", "[%16s]", event_to_str[ghdr->cmd]);
parse_rtattr(tb, MPTCP_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
if (tb[MPTCP_ATTR_TOKEN])
- printf(" token=%08x", rta_getattr_u32(tb[MPTCP_ATTR_TOKEN]));
+ print_0xhex(PRINT_ANY, "token", " token=%08x",
+ rta_getattr_u32(tb[MPTCP_ATTR_TOKEN]));
if (tb[MPTCP_ATTR_REM_ID])
- printf(" remid=%u", rta_getattr_u8(tb[MPTCP_ATTR_REM_ID]));
+ print_uint(PRINT_ANY, "remid", " remid=%u",
+ rta_getattr_u8(tb[MPTCP_ATTR_REM_ID]));
if (tb[MPTCP_ATTR_LOC_ID])
- printf(" locid=%u", rta_getattr_u8(tb[MPTCP_ATTR_LOC_ID]));
+ print_uint(PRINT_ANY, "locid", " locid=%u",
+ rta_getattr_u8(tb[MPTCP_ATTR_LOC_ID]));
if (tb[MPTCP_ATTR_SADDR4])
print_addr("saddr4", AF_INET, tb[MPTCP_ATTR_SADDR4]);
@@ -543,49 +550,74 @@ static int mptcp_monitor_msg(struct rtnl_ctrl_data *ctrl,
if (tb[MPTCP_ATTR_DADDR6])
print_addr("daddr6", AF_INET6, tb[MPTCP_ATTR_DADDR6]);
if (tb[MPTCP_ATTR_SPORT])
- printf(" sport=%u", rta_getattr_be16(tb[MPTCP_ATTR_SPORT]));
+ print_uint(PRINT_ANY, "sport", " sport=%u",
+ rta_getattr_be16(tb[MPTCP_ATTR_SPORT]));
if (tb[MPTCP_ATTR_DPORT])
- printf(" dport=%u", rta_getattr_be16(tb[MPTCP_ATTR_DPORT]));
+ print_uint(PRINT_ANY, "dport", " dport=%u",
+ rta_getattr_be16(tb[MPTCP_ATTR_DPORT]));
if (tb[MPTCP_ATTR_BACKUP])
- printf(" backup=%u", rta_getattr_u8(tb[MPTCP_ATTR_BACKUP]));
+ print_uint(PRINT_ANY, "backup", " backup=%u",
+ rta_getattr_u8(tb[MPTCP_ATTR_BACKUP]));
if (tb[MPTCP_ATTR_ERROR])
- printf(" error=%u", rta_getattr_u8(tb[MPTCP_ATTR_ERROR]));
+ print_uint(PRINT_ANY, "error", " error=%u",
+ rta_getattr_u8(tb[MPTCP_ATTR_ERROR]));
if (tb[MPTCP_ATTR_TIMEOUT])
- printf(" timeout=%u", rta_getattr_u32(tb[MPTCP_ATTR_TIMEOUT]));
+ print_uint(PRINT_ANY, "timeout", " timeout=%u",
+ rta_getattr_u32(tb[MPTCP_ATTR_TIMEOUT]));
if (tb[MPTCP_ATTR_IF_IDX])
print_iface(rta_getattr_s32(tb[MPTCP_ATTR_IF_IDX]));
if (tb[MPTCP_ATTR_RESET_REASON])
- printf(" reset_reason=%u", rta_getattr_u32(tb[MPTCP_ATTR_RESET_REASON]));
+ print_uint(PRINT_ANY, "reset_reason", " reset_reason=%u",
+ rta_getattr_u32(tb[MPTCP_ATTR_RESET_REASON]));
if (tb[MPTCP_ATTR_RESET_FLAGS])
- printf(" reset_flags=0x%x", rta_getattr_u32(tb[MPTCP_ATTR_RESET_FLAGS]));
+ print_0xhex(PRINT_ANY, "reset_flags", " reset_flags=%#x",
+ rta_getattr_u32(tb[MPTCP_ATTR_RESET_FLAGS]));
if (tb[MPTCP_ATTR_FLAGS])
flags = rta_getattr_u16(tb[MPTCP_ATTR_FLAGS]);
if ((flags & MPTCP_PM_EV_FLAG_SERVER_SIDE) ||
(tb[MPTCP_ATTR_SERVER_SIDE] && rta_getattr_u8(tb[MPTCP_ATTR_SERVER_SIDE]))) {
flags &= ~MPTCP_PM_EV_FLAG_SERVER_SIDE;
- printf(" server_side");
+ print_string(PRINT_FP, NULL, " server_side", NULL);
+ print_bool(PRINT_JSON, "server_side", NULL, true);
}
if (flags & MPTCP_PM_EV_FLAG_DENY_JOIN_ID0) {
flags &= ~MPTCP_PM_EV_FLAG_DENY_JOIN_ID0;
- printf(" deny_join_id0");
+ print_string(PRINT_FP, NULL, " deny_join_id0", NULL);
+ print_bool(PRINT_JSON, "deny_join_id0", NULL, true);
}
if (flags) /* remaining bits */
- printf(" flags=0x%x", flags);
+ print_0xhex(PRINT_ANY, "flags", " flags=%#x", flags);
- puts("");
out:
+ print_nl();
+ close_json_object();
fflush(stdout);
+
return 0;
}
+static void sig_exit(int signo)
+{
+ exit(0);
+}
+
static int mptcp_monitor(void)
{
+ struct sigaction sa = { .sa_handler = sig_exit,
+ .sa_flags = SA_RESTART };
+
if (genl_add_mcast_grp(&genl_rth, genl_family, MPTCP_PM_EV_GRP_NAME) < 0) {
perror("can't subscribe to mptcp events");
return 1;
}
+ new_json_obj(json);
+ atexit(delete_json_obj);
+
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
if (rtnl_listen(&genl_rth, mptcp_monitor_msg, stdout) < 0)
return 2;
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH iproute2-next v2 0/3] ip mptcp monitor: add JSON support
2026-02-23 15:28 [PATCH iproute2-next v2 0/3] ip mptcp monitor: add JSON support Matthieu Baerts (NGI0)
` (2 preceding siblings ...)
2026-02-23 15:28 ` [PATCH iproute2-next v2 3/3] mptcp: monitor: " Matthieu Baerts (NGI0)
@ 2026-02-25 16:30 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-02-25 16:30 UTC (permalink / raw)
To: Matthieu Baerts; +Cc: stephen, dsahern, netdev, mptcp
Hello:
This series was applied to iproute2/iproute2-next.git (main)
by David Ahern <dsahern@kernel.org>:
On Mon, 23 Feb 2026 16:28:37 +0100 you wrote:
> With this series, the command 'ip [-t[s]] mptcp monitor' produces an
> output with the JSON format.
>
> - Patch 1: a small refactoring to uniform the code.
>
> - Patch 2: add JSON support in print_timestamp() helper.
>
> [...]
Here is the summary with links:
- [iproute2-next,v2,1/3] mptcp: uniform stream closure
https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=fa0217870a8b
- [iproute2-next,v2,2/3] utils: timestamp: add JSON support
https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=1fea8c6f3d9b
- [iproute2-next,v2,3/3] mptcp: monitor: add JSON support
https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=d37b3aed28c0
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-02-25 16:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-23 15:28 [PATCH iproute2-next v2 0/3] ip mptcp monitor: add JSON support Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 1/3] mptcp: uniform stream closure Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 2/3] utils: timestamp: add JSON support Matthieu Baerts (NGI0)
2026-02-23 15:28 ` [PATCH iproute2-next v2 3/3] mptcp: monitor: " Matthieu Baerts (NGI0)
2026-02-25 16:30 ` [PATCH iproute2-next v2 0/3] ip mptcp " patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox