On Thu, Sep 10, 2015 at 09:35:03PM +0200, Matthias Tafelmeier wrote:
> This patch just adds the -j and --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.
>
> Most importantly, with this patch, the new prepared interface to the
> generic output handlers is used to replace the accustomed output
> logic.
>
> Signed-off-by: Matthias Tafelmeier
> Suggested-by: Hagen Paul Pfeifer
> ---
> misc/ss.c | 487
> ++
> 1 file changed, 266 insertions(+), 221 deletions(-)
>
> diff --git a/misc/ss.c b/misc/ss.c
> index e7ea041..7a1b6eb 100644
> --- a/misc/ss.c
> +++ b/misc/ss.c
> @@ -26,6 +26,7 @@
> #include
> #include
> #include
> +#include
>
> #include "ss_types.h"
> #include "utils.h"
> @@ -34,6 +35,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
> #include
> @@ -101,6 +105,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;
> @@ -109,11 +114,14 @@ int addr_width;
> int serv_width;
> int screen_width;
>
> +enum out_fmt_type fmt_type = FMT_HR;
> +
> static const char *TCP_PROTO = "tcp";
> static const char *UDP_PROTO = "udp";
> static const char *RAW_PROTO = "raw";
> static const char *dg_proto = NULL;
>
> +json_writer_t *json_wr;
Not sure if doable, but IMHO this should be hidden in ss_json_fmt.c.
> #define PACKET_DBM ((1< #define UNIX_DBM ((1< @@ -716,7 +724,6 @@ static int is_ephemeral(int port)
> return (port >= ip_local_port_min && port<= ip_local_port_max);
> }
>
> -
Export changes like this one into a dedicated patch at the start of the
series?
> static const char *__resolve_service(int port)
> {
> struct scache *c;
> @@ -790,7 +797,8 @@ do_numeric:
> return buf;
> }
>
> -static void inet_addr_print(const inet_prefix *a, int port, unsigned int
> ifindex)
> +static void inet_addr_print(const inet_prefix *a, int port,
> + unsigned int ifindex, char *peer_kind)
> {
> char buf[1024];
> const char *ap = buf;
> @@ -818,8 +826,8 @@ static void inet_addr_print(const inet_prefix *a, int
> port, unsigned int ifindex
> est_len -= strlen(ifname) + 1; /* +1 for percent char */
> }
>
> - sock_addr_print_width(est_len, ap, ":", serv_width,
> resolve_service(port),
> - ifname);
> + sock_addr_fmt(ap, est_len, ":", serv_width, resolve_service(port),
> + ifname, peer_kind);
> }
>
> static int inet2_addr_match(const inet_prefix *a, const inet_prefix *p,
> @@ -1351,21 +1359,29 @@ static void inet_stats_print(struct sockstat *s, int
> protocol)
> {
> char *buf = NULL;
>
> - sock_state_print(s, proto_name(protocol));
> + sock_state_fmt(s, sstate_name, proto_name(protocol),
> + netid_width, state_width);
>
> - inet_addr_print(>local, s->lport, s->iface);
> - inet_addr_print(>remote, s->rport, 0);
> + if (json_output) {
> + jsonw_name(json_wr, "peers");
> + jsonw_start_object(json_wr);
> + }
How about an additional callback:
fmt_new_object("peers");
The hr variant will be a no op, the json variant uses it's private (see
above) json_wr object.
> + inet_addr_print(>local, s->lport, s->iface, "local");
> + inet_addr_print(>remote, s->rport, 0, "remote");
> + if (json_output)
> + jsonw_end_object(json_wr);
>
> if (show_proc_ctx || show_sock_ctx) {
> if (find_entry(s->ino, ,
> - (show_proc_ctx & show_sock_ctx) ?
> - PROC_SOCK_CTX : PROC_CTX) > 0) {
> - printf(" users:(%s)", buf);
> +(show_proc_ctx & show_sock_ctx) ?
> +PROC_SOCK_CTX : PROC_CTX) > 0) {
> + sock_users_fmt(buf);
> free(buf);
> }
> } else if (show_users) {
> if (find_entry(s->ino, , USERS) > 0) {
> - printf(" users:(%s)", buf);
> + sock_users_fmt(buf);
> free(buf);
> }
> }
> @@ -1469,16 +1485,16 @@ static int tcp_show_line(char *line, const struct
> filter *f, int family)
> inet_stats_print(, IPPROTO_TCP);
>
> if (show_options)
> - tcp_timer_print();
> + tcp_timer_fmt();
>
> if (show_details) {
> -