From: Matthias Tafelmeier <matthias.tafelmeier@gmx.net>
To: netdev@vger.kernel.org
Cc: hagen@jauu.net, shemminger@osdl.org, fw@strlen.de,
edumazet@google.com, daniel@iogearbox.net
Subject: [PATCH 05/10] ss: framed skeleton for json output in ss
Date: Mon, 10 Aug 2015 01:13:21 +0200 [thread overview]
Message-ID: <1439162006-11421-6-git-send-email-matthias.tafelmeier@gmx.net> (raw)
In-Reply-To: <1439162006-11421-1-git-send-email-matthias.tafelmeier@gmx.net>
This patch just adds the --json flag to ss. Also it ensures proper
stats components bracketization – that goes for ex. TCP, UDP, NETLINK etc.
Moreover, this patch prevents human readable headers to be printed. The
first element flag ensures, that every first output json container
element is treated specially, while all the others are treated equally.
That is, only the first one does not print a coma ahead of itself. The
rest does. This mechanism ensures the correct coma setting as demaned by
the spec. Illustration in the following:
PSEUDOCODE:
{ >>>> no comma
{first }
>>>> ,
{sec}
>>>> ,
{third}
.
.
.
}
Signed-off-by: Matthias Tafelmeier <matthias.tafelmeier@gmx.net>
Suggested-by: Hagen Paul Pfeifer <hagen@jauu.net>
---
misc/ss.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 157 insertions(+), 43 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index 1b3ef90..f563710 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -34,6 +34,9 @@
#include "libnetlink.h"
#include "namespace.h"
#include "SNAPSHOT.h"
+#include "ss_out_fmt.h"
+#include "ss_json_fmt.h"
+#include "ss_types.h"
#include <linux/tcp.h>
#include <linux/sock_diag.h>
@@ -101,6 +104,7 @@ int show_sock_ctx = 0;
/* If show_users & show_proc_ctx only do user_ent_hash_build() once */
int user_ent_hash_build_init = 0;
int follow_events = 0;
+int json_output = 0;
int netid_width;
int state_width;
@@ -714,7 +718,6 @@ static int is_ephemeral(int port)
return (port >= ip_local_port_min && port<= ip_local_port_max);
}
-
static const char *__resolve_service(int port)
{
struct scache *c;
@@ -3064,6 +3067,9 @@ static int print_summary(void)
printf("\n");
+ if (json_output && has_successor)
+ printf(",\n");
+
return 0;
}
@@ -3090,6 +3096,7 @@ static void _usage(FILE *dest)
" -z, --contexts display process and socket SELinux security contexts\n"
" -N, --net switch to the specified network namespace name\n"
"\n"
+" -j, --json format output in JSON\n"
" -4, --ipv4 display only IP version 4 sockets\n"
" -6, --ipv6 display only IP version 6 sockets\n"
" -0, --packet display PACKET sockets\n"
@@ -3189,6 +3196,7 @@ static const struct option long_opts[] = {
{ "help", 0, 0, 'h' },
{ "context", 0, 0, 'Z' },
{ "contexts", 0, 0, 'z' },
+ { "json", 0, 0, 'j' },
{ "net", 1, 0, 'N' },
{ 0 }
@@ -3204,7 +3212,7 @@ int main(int argc, char *argv[])
int ch;
int state_filter = 0;
- while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbEf:miA:D:F:vVzZN:",
+ while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbEf:miA:D:F:vVzZN:j",
long_opts, NULL)) != EOF) {
switch(ch) {
case 'n':
@@ -3383,6 +3391,10 @@ int main(int argc, char *argv[])
if (netns_switch(optarg))
exit(1);
break;
+ case 'j':
+ fmt_type = FMT_JSON;
+ json_output = 1;
+ break;
case 'h':
case '?':
help();
@@ -3464,11 +3476,34 @@ int main(int argc, char *argv[])
exit(-1);
}
}
+ printf("\"TCP\": [\n");
inet_show_netlink(¤t_filter, dump_fp, IPPROTO_TCP);
+ res_json_fmt_branch(current_filter.dbs & (1<<NETLINK_DB) ||
+ current_filter.dbs & PACKET_DBM ||
+ current_filter.dbs & UNIX_DBM ||
+ current_filter.dbs & (1<<RAW_DB) ||
+ current_filter.dbs & (1<<UDP_DB) ||
+ current_filter.dbs & (1<<TCP_DB) ||
+ current_filter.dbs & (1<<DCCP_DB), ']');
fflush(dump_fp);
exit(0);
}
+ if (do_summary) {
+ print_summary(current_filter.dbs & PACKET_DBM ||
+ current_filter.dbs & UNIX_DBM ||
+ current_filter.dbs & (1<<RAW_DB) ||
+ current_filter.dbs & (1<<UDP_DB) ||
+ current_filter.dbs & (1<<TCP_DB) ||
+ current_filter.dbs & (1<<DCCP_DB));
+ if (do_default && argc == 0) {
+ if (json_output) {
+ printf("}\n");
+ }
+ exit(0);
+ }
+ }
+
if (ssfilter_parse(¤t_filter.f, argc, argv, filter_fp))
usage();
@@ -3490,62 +3525,141 @@ int main(int argc, char *argv[])
}
}
- addrp_width = screen_width;
- addrp_width -= netid_width+1;
- addrp_width -= state_width+1;
- addrp_width -= 14;
+ if (!json_output) {
+
+ addrp_width = screen_width;
+ addrp_width -= netid_width + 1;
+ addrp_width -= state_width + 1;
+ addrp_width -= 14;
+
+ if (addrp_width & 1) {
+ if (netid_width)
+ netid_width++;
+ else if (state_width)
+ state_width++;
+ }
+
+ addrp_width /= 2;
+ addrp_width--;
+
+ serv_width = resolve_services ? 7 : 5;
+
+ if (addrp_width < 15 + serv_width + 1)
+ addrp_width = 15 + serv_width + 1;
- if (addrp_width&1) {
+ addr_width = addrp_width - serv_width - 1;
if (netid_width)
- netid_width++;
- else if (state_width)
- state_width++;
- }
+ printf("%-*s ", netid_width, "Netid");
+ if (state_width)
+ printf("%-*s ", state_width, "State");
+ printf("%-6s %-6s ", "Recv-Q", "Send-Q");
+
+ /* Make enough space for the local/remote port field */
+ addr_width -= 13;
+ serv_width += 13;
- addrp_width /= 2;
- addrp_width--;
+ printf("%*s:%-*s %*s:%-*s\n",
+ addr_width, "Local Address", serv_width, "Port",
+ addr_width, "Peer Address", serv_width, "Port");
+ }
- serv_width = resolve_services ? 7 : 5;
+ fflush(stdout);
- if (addrp_width < 15+serv_width+1)
- addrp_width = 15+serv_width+1;
+ if (current_filter.dbs & (1<<NETLINK_DB)) {
+ if (json_output) {
+ printf("\"NETLINK\": [\n");
+ netlink_show(¤t_filter);
+ json_first_elem = 1;
+ res_json_fmt_branch(current_filter.dbs & PACKET_DBM ||
+ current_filter.dbs & UNIX_DBM ||
+ current_filter.dbs & (1<<RAW_DB) ||
+ current_filter.dbs & (1<<UDP_DB) ||
+ current_filter.dbs & (1<<TCP_DB) ||
+ current_filter.dbs & (1<<DCCP_DB), ']');
+ } else
+ netlink_show(¤t_filter);
+ }
+ if (current_filter.dbs & PACKET_DBM) {
+ if (json_output) {
+ printf("\"PACKET\": [\n");
+ packet_show(¤t_filter);
+ json_first_elem = 1;
+ res_json_fmt_branch(
+ current_filter.dbs & UNIX_DBM ||
+ current_filter.dbs & (1<<RAW_DB) ||
+ current_filter.dbs & (1<<UDP_DB) ||
+ current_filter.dbs & (1<<TCP_DB) ||
+ current_filter.dbs & (1<<DCCP_DB), ']');
+ } else
+ packet_show(¤t_filter);
+ }
+ if (current_filter.dbs & UNIX_DBM) {
+ if (json_output) {
+ printf("\"UNIX\": [\n");
+ unix_show(¤t_filter);
+ json_first_elem = 1;
+ res_json_fmt_branch(
+ current_filter.dbs & (1<<RAW_DB) ||
+ current_filter.dbs & (1<<UDP_DB) ||
+ current_filter.dbs & (1<<TCP_DB) ||
+ current_filter.dbs & (1<<DCCP_DB), ']');
- addr_width = addrp_width - serv_width - 1;
+ } else
+ unix_show(¤t_filter);
+ }
+ if (current_filter.dbs & (1<<RAW_DB)) {
+ if (json_output) {
+ printf("\"RAW\": [\n");
+ raw_show(¤t_filter);
+ json_first_elem = 1;
+ res_json_fmt_branch(
+ current_filter.dbs & (1<<UDP_DB) ||
+ current_filter.dbs & (1<<TCP_DB) ||
+ current_filter.dbs & (1<<DCCP_DB), ']');
- if (netid_width)
- printf("%-*s ", netid_width, "Netid");
- if (state_width)
- printf("%-*s ", state_width, "State");
- printf("%-6s %-6s ", "Recv-Q", "Send-Q");
+ } else
+ raw_show(¤t_filter);
+ }
+ if (current_filter.dbs & (1<<UDP_DB)) {
+ if (json_output) {
+ printf("\"UDP\": [\n");
+ udp_show(¤t_filter);
+ json_first_elem = 1;
+ res_json_fmt_branch(
+ current_filter.dbs & (1<<TCP_DB) ||
+ current_filter.dbs & (1<<DCCP_DB), ']');
- /* Make enough space for the local/remote port field */
- addr_width -= 13;
- serv_width += 13;
+ } else
+ udp_show(¤t_filter);
+ }
+ if (current_filter.dbs & (1<<TCP_DB)) {
+ if (json_output) {
+ printf("\"TCP\": [\n");
+ tcp_show(¤t_filter, IPPROTO_TCP);
+ json_first_elem = 1;
+ res_json_fmt_branch(
+ current_filter.dbs & (1<<DCCP_DB), ']');
+ } else
+ tcp_show(¤t_filter, IPPROTO_TCP);
+ }
+ if (current_filter.dbs & (1<<DCCP_DB)) {
+ if (json_output) {
+ printf("\"DCCP\": [\n");
+ tcp_show(¤t_filter, IPPROTO_DCCP);
+ printf("]\n");
+ } else
+ tcp_show(¤t_filter, IPPROTO_DCCP);
+ }
- printf("%*s:%-*s %*s:%-*s\n",
- addr_width, "Local Address", serv_width, "Port",
- addr_width, "Peer Address", serv_width, "Port");
+ if (json_output) {
+ printf("}\n");
+ }
fflush(stdout);
if (follow_events)
exit(handle_follow_request(¤t_filter));
- if (current_filter.dbs & (1<<NETLINK_DB))
- netlink_show(¤t_filter);
- if (current_filter.dbs & PACKET_DBM)
- packet_show(¤t_filter);
- if (current_filter.dbs & UNIX_DBM)
- unix_show(¤t_filter);
- if (current_filter.dbs & (1<<RAW_DB))
- raw_show(¤t_filter);
- if (current_filter.dbs & (1<<UDP_DB))
- udp_show(¤t_filter);
- if (current_filter.dbs & (1<<TCP_DB))
- tcp_show(¤t_filter, IPPROTO_TCP);
- if (current_filter.dbs & (1<<DCCP_DB))
- tcp_show(¤t_filter, IPPROTO_DCCP);
-
if (show_users || show_proc_ctx || show_sock_ctx)
user_ent_destroy();
--
1.9.1
next prev parent reply other threads:[~2015-08-09 23:13 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-09 23:13 full ss json support and general output simplification Matthias Tafelmeier
2015-08-09 23:13 ` [PATCH 01/10] ss: rooted out ss type declarations for output formatters Matthias Tafelmeier
2015-08-09 23:13 ` [PATCH 02/10] ss: created formatters for json and hr Matthias Tafelmeier
2015-08-09 23:13 ` [PATCH 03/10] ss: removed obsolet fmt functions Matthias Tafelmeier
2015-08-09 23:13 ` [PATCH 04/10] ss: prepare timer for output handler usage Matthias Tafelmeier
2015-08-09 23:13 ` Matthias Tafelmeier [this message]
2015-08-09 23:13 ` [PATCH 06/10] ss: replaced old output mechanisms with fmt handlers interfaces Matthias Tafelmeier
2015-08-09 23:13 ` [PATCH 07/10] ss: renaming and export of current_filter Matthias Tafelmeier
2015-08-09 23:13 ` [PATCH 08/10] ss: symmetrical subhandler output extension example Matthias Tafelmeier
2015-08-10 12:19 ` Sergei Shtylyov
2015-08-10 14:53 ` Eric Dumazet
2015-08-10 17:06 ` Matthias Tafelmeier
2015-08-10 18:19 ` Sergei Shtylyov
2015-08-09 23:13 ` [PATCH 09/10] ss: symmetrical formatter " Matthias Tafelmeier
2015-08-09 23:13 ` [PATCH 10/10] ss: fixed free on local array for valid json output Matthias Tafelmeier
-- strict thread matches above, loose matches on Subject: below --
2015-08-10 18:52 V2 iproute2: full ss json support and general output simplification Matthias Tafelmeier
2015-08-10 18:52 ` [PATCH 05/10] ss: framed skeleton for json output in ss Matthias Tafelmeier
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=1439162006-11421-6-git-send-email-matthias.tafelmeier@gmx.net \
--to=matthias.tafelmeier@gmx.net \
--cc=daniel@iogearbox.net \
--cc=edumazet@google.com \
--cc=fw@strlen.de \
--cc=hagen@jauu.net \
--cc=netdev@vger.kernel.org \
--cc=shemminger@osdl.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;
as well as URLs for NNTP newsgroup(s).