From: GhantaKrishnamurthy MohanKrishna Date: Fri, 23 Mar 2018 14:01:02 +0000 (+0100) Subject: ss: Add support for TIPC socket diag in ss tool X-Git-Tag: v4.17.0~49^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5caf79a0bcb71a7cbf9c900a1c802540109ddcf0;p=thirdparty%2Fiproute2.git ss: Add support for TIPC socket diag in ss tool For iproute 4.x Allow TIPC socket statistics to be dumped with --tipc and tipc specific info with --tipcinfo. Acked-by: Jon Maloy Signed-off-by: GhantaKrishnamurthy MohanKrishna Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David Ahern --- diff --git a/misc/ss.c b/misc/ss.c index c76ad66ef..ffc6f27b6 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -45,6 +45,10 @@ #include #include #include +#include +#include +#include +#include #define MAGIC_SEQ 123456 #define BUF_CHUNK (1024 * 1024) @@ -104,6 +108,7 @@ int show_sock_ctx; int show_header = 1; int follow_events; int sctp_ino; +int show_tipcinfo; enum col_id { COL_NETID, @@ -191,6 +196,7 @@ enum { SCTP_DB, VSOCK_ST_DB, VSOCK_DG_DB, + TIPC_DB, MAX_DB }; @@ -230,6 +236,7 @@ enum { #define SS_ALL ((1 << SS_MAX) - 1) #define SS_CONN (SS_ALL & ~((1<type); + break; case AF_VSOCK: sock_name = vsock_netid_name(s->type); break; @@ -4277,6 +4320,105 @@ static int vsock_show(struct filter *f) return handle_netlink_request(f, &req.nlh, sizeof(req), vsock_show_sock); } +static void tipc_sock_addr_print(struct rtattr *net_addr, struct rtattr *id) +{ + uint32_t node = rta_getattr_u32(net_addr); + uint32_t identity = rta_getattr_u32(id); + + SPRINT_BUF(addr) = {}; + SPRINT_BUF(port) = {}; + + sprintf(addr, "%u", node); + sprintf(port, "%u", identity); + sock_addr_print(addr, ":", port, NULL); + +} + +static int tipc_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh, + void *arg) +{ + struct rtattr *stat[TIPC_NLA_SOCK_STAT_MAX + 1] = {}; + struct rtattr *attrs[TIPC_NLA_SOCK_MAX + 1] = {}; + struct rtattr *con[TIPC_NLA_CON_MAX + 1] = {}; + struct rtattr *info[TIPC_NLA_MAX + 1] = {}; + struct rtattr *msg_ref; + struct sockstat ss = {}; + + parse_rtattr(info, TIPC_NLA_MAX, NLMSG_DATA(nlh), + NLMSG_PAYLOAD(nlh, 0)); + + if (!info[TIPC_NLA_SOCK]) + return 0; + + msg_ref = info[TIPC_NLA_SOCK]; + parse_rtattr(attrs, TIPC_NLA_SOCK_MAX, RTA_DATA(msg_ref), + RTA_PAYLOAD(msg_ref)); + + msg_ref = attrs[TIPC_NLA_SOCK_STAT]; + parse_rtattr(stat, TIPC_NLA_SOCK_STAT_MAX, + RTA_DATA(msg_ref), RTA_PAYLOAD(msg_ref)); + + + ss.local.family = AF_TIPC; + ss.type = rta_getattr_u32(attrs[TIPC_NLA_SOCK_TYPE]); + ss.state = rta_getattr_u32(attrs[TIPC_NLA_SOCK_TIPC_STATE]); + ss.uid = rta_getattr_u32(attrs[TIPC_NLA_SOCK_UID]); + ss.ino = rta_getattr_u32(attrs[TIPC_NLA_SOCK_INO]); + ss.rq = rta_getattr_u32(stat[TIPC_NLA_SOCK_STAT_RCVQ]); + ss.wq = rta_getattr_u32(stat[TIPC_NLA_SOCK_STAT_SENDQ]); + ss.sk = rta_getattr_u64(attrs[TIPC_NLA_SOCK_COOKIE]); + + sock_state_print (&ss); + + tipc_sock_addr_print(attrs[TIPC_NLA_SOCK_ADDR], + attrs[TIPC_NLA_SOCK_REF]); + + msg_ref = attrs[TIPC_NLA_SOCK_CON]; + if (msg_ref) { + parse_rtattr(con, TIPC_NLA_CON_MAX, + RTA_DATA(msg_ref), RTA_PAYLOAD(msg_ref)); + + tipc_sock_addr_print(con[TIPC_NLA_CON_NODE], + con[TIPC_NLA_CON_SOCK]); + } else + sock_addr_print("", "-", "", NULL); + + if (show_details) + sock_details_print(&ss); + + proc_ctx_print(&ss); + + if (show_tipcinfo) { + out("\n type:%s", stype_nameg[ss.type]); + out(" cong:%s ", + stat[TIPC_NLA_SOCK_STAT_LINK_CONG] ? "link" : + stat[TIPC_NLA_SOCK_STAT_CONN_CONG] ? "conn" : "none"); + out(" drop:%d ", + rta_getattr_u32(stat[TIPC_NLA_SOCK_STAT_DROP])); + + if (attrs[TIPC_NLA_SOCK_HAS_PUBL]) + out(" publ"); + + if (con[TIPC_NLA_CON_FLAG]) + out(" via {%u,%u} ", + rta_getattr_u32(con[TIPC_NLA_CON_TYPE]), + rta_getattr_u32(con[TIPC_NLA_CON_INST])); + } + + return 0; +} + +static int tipc_show(struct filter *f) +{ + DIAG_REQUEST(req, struct tipc_sock_diag_req r); + + memset(&req.r, 0, sizeof(req.r)); + req.r.sdiag_family = AF_TIPC; + req.r.tidiag_states = f->states; + + return handle_netlink_request(f, &req.nlh, sizeof(req), tipc_show_sock); +} + struct sock_diag_msg { __u8 sdiag_family; }; @@ -4531,6 +4673,7 @@ static void _usage(FILE *dest) " -m, --memory show socket memory usage\n" " -p, --processes show process using socket\n" " -i, --info show internal TCP information\n" +" --tipcinfo show internal tipc socket information\n" " -s, --summary show socket usage summary\n" " -b, --bpf show bpf filter socket information\n" " -E, --events continually display sockets as they are destroyed\n" @@ -4547,15 +4690,16 @@ static void _usage(FILE *dest) " -d, --dccp display only DCCP sockets\n" " -w, --raw display only RAW sockets\n" " -x, --unix display only Unix domain sockets\n" +" --tipc display only TIPC sockets\n" " --vsock display only vsock sockets\n" " -f, --family=FAMILY display sockets of type FAMILY\n" -" FAMILY := {inet|inet6|link|unix|netlink|vsock|help}\n" +" FAMILY := {inet|inet6|link|unix|netlink|vsock|tipc|help}\n" "\n" " -K, --kill forcibly close sockets, display what was closed\n" " -H, --no-header Suppress header line\n" "\n" " -A, --query=QUERY, --socket=QUERY\n" -" QUERY := {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink|vsock_stream|vsock_dgram}[,QUERY]\n" +" QUERY := {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink|vsock_stream|vsock_dgram|tipc}[,QUERY]\n" "\n" " -D, --diag=FILE Dump raw information about TCP sockets to FILE\n" " -F, --filter=FILE read filter information from FILE\n" @@ -4631,6 +4775,10 @@ static int scan_state(const char *state) /* Values 'v' and 'V' are already used so a non-character is used */ #define OPT_VSOCK 256 +/* Values of 't' are already used so a non-character is used */ +#define OPT_TIPCSOCK 257 +#define OPT_TIPCINFO 258 + static const struct option long_opts[] = { { "numeric", 0, 0, 'n' }, { "resolve", 0, 0, 'r' }, @@ -4647,6 +4795,7 @@ static const struct option long_opts[] = { { "udp", 0, 0, 'u' }, { "raw", 0, 0, 'w' }, { "unix", 0, 0, 'x' }, + { "tipc", 0, 0, OPT_TIPCSOCK}, { "vsock", 0, 0, OPT_VSOCK }, { "all", 0, 0, 'a' }, { "listening", 0, 0, 'l' }, @@ -4664,6 +4813,7 @@ static const struct option long_opts[] = { { "context", 0, 0, 'Z' }, { "contexts", 0, 0, 'z' }, { "net", 1, 0, 'N' }, + { "tipcinfo", 0, 0, OPT_TIPCINFO}, { "kill", 0, 0, 'K' }, { "no-header", 0, 0, 'H' }, { 0 } @@ -4735,6 +4885,9 @@ int main(int argc, char *argv[]) case OPT_VSOCK: filter_af_set(¤t_filter, AF_VSOCK); break; + case OPT_TIPCSOCK: + filter_af_set(¤t_filter, AF_TIPC); + break; case 'a': state_filter = SS_ALL; break; @@ -4761,6 +4914,8 @@ int main(int argc, char *argv[]) filter_af_set(¤t_filter, AF_UNIX); else if (strcmp(optarg, "netlink") == 0) filter_af_set(¤t_filter, AF_NETLINK); + else if (strcmp(optarg, "tipc") == 0) + filter_af_set(¤t_filter, AF_TIPC); else if (strcmp(optarg, "vsock") == 0) filter_af_set(¤t_filter, AF_VSOCK); else if (strcmp(optarg, "help") == 0) @@ -4837,6 +4992,8 @@ int main(int argc, char *argv[]) } else if (strcmp(p, "vsock_dgram") == 0 || strcmp(p, "v_dgr") == 0) { filter_db_set(¤t_filter, VSOCK_DG_DB); + } else if (strcmp(optarg, "tipc") == 0) { + filter_db_set(¤t_filter, TIPC_DB); } else { fprintf(stderr, "ss: \"%s\" is illegal socket table id\n", p); usage(); @@ -4884,6 +5041,9 @@ int main(int argc, char *argv[]) if (netns_switch(optarg)) exit(1); break; + case OPT_TIPCINFO: + show_tipcinfo = 1; + break; case 'K': current_filter.kill = 1; break; @@ -5006,6 +5166,8 @@ int main(int argc, char *argv[]) sctp_show(¤t_filter); if (current_filter.dbs & VSOCK_DBM) vsock_show(¤t_filter); + if (current_filter.dbs & (1<