Message ID | 1521813662-9954-2-git-send-email-mohan.krishna.ghanta.krishnamurthy@ericsson.com |
---|---|
State | Accepted, archived |
Delegated to: | David Ahern |
Headers | show |
Series | iproute2: add TIPC statistics support in ss | expand |
Hi Mohan, I remember you mentioned the possibility to add this functionality to the tipc tool, too. Would it be easy to add a 'tipc ss' command that just calls 'ss' with the same parameters? I.e., no duplication of functionality ? ///jon > -----Original Message----- > From: Mohan Krishna Ghanta Krishnamurthy > Sent: Friday, March 23, 2018 10:01 > To: tipc-discussion@lists.sourceforge.net; Jon Maloy > <jon.maloy@ericsson.com>; maloy@donjonn.com; > ying.xue@windriver.com; Mohan Krishna Ghanta Krishnamurthy > <mohan.krishna.ghanta.krishnamurthy@ericsson.com>; > netdev@vger.kernel.org; stephen@networkplumber.org > Cc: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@gmail.com> > Subject: [iproute2 1/1] 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 <jon.maloy@ericsson.com> > Signed-off-by: GhantaKrishnamurthy MohanKrishna > <mohan.krishna.ghanta.krishnamurthy@ericsson.com> > Signed-off-by: Parthasarathy Bhuvaragan > <parthasarathy.bhuvaragan@gmail.com> > --- > misc/ss.c | 166 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++- > 1 file changed, 164 insertions(+), 2 deletions(-) > > diff --git a/misc/ss.c b/misc/ss.c > index e047f9c04582..812f45717af9 100644 > --- a/misc/ss.c > +++ b/misc/ss.c > @@ -45,6 +45,10 @@ > #include <linux/netlink_diag.h> > #include <linux/sctp.h> > #include <linux/vm_sockets_diag.h> > +#include <linux/net.h> > +#include <linux/tipc.h> > +#include <linux/tipc_netlink.h> > +#include <linux/tipc_sockets_diag.h> > > #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<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV) > )) > +#define TIPC_SS_CONN > ((1<<SS_ESTABLISHED)|(1<<SS_LISTEN)|(1<<SS_CLOSE)) > > #include "ssfilter.h" > > @@ -297,6 +304,10 @@ static const struct filter default_dbs[MAX_DB] = { > .states = SS_CONN, > .families = FAMILY_MASK(AF_VSOCK), > }, > + [TIPC_DB] = { > + .states = TIPC_SS_CONN, > + .families = FAMILY_MASK(AF_TIPC), > + }, > }; > > static const struct filter default_afs[AF_MAX] = { @@ -324,6 +335,10 @@ > static const struct filter default_afs[AF_MAX] = { > .dbs = VSOCK_DBM, > .states = SS_CONN, > }, > + [AF_TIPC] = { > + .dbs = (1 << TIPC_DB), > + .states = TIPC_SS_CONN, > + }, > }; > > static int do_default = 1; > @@ -364,6 +379,7 @@ static void filter_default_dbs(struct filter *f) > filter_db_set(f, SCTP_DB); > filter_db_set(f, VSOCK_ST_DB); > filter_db_set(f, VSOCK_DG_DB); > + filter_db_set(f, TIPC_DB); > } > > static void filter_states_set(struct filter *f, int states) @@ -748,6 +764,14 > @@ static const char *sctp_sstate_name[] = { > [SCTP_STATE_SHUTDOWN_ACK_SENT] = "ACK_SENT", }; > > +static const char * const stype_nameg[] = { > + "UNKNOWN", > + [SOCK_STREAM] = "STREAM", > + [SOCK_DGRAM] = "DGRAM", > + [SOCK_RDM] = "RDM", > + [SOCK_SEQPACKET] = "SEQPACKET", > +}; > + > struct sockstat { > struct sockstat *next; > unsigned int type; > @@ -888,6 +912,22 @@ static const char *vsock_netid_name(int type) > } > } > > +static const char *tipc_netid_name(int type) { > + switch (type) { > + case SOCK_STREAM: > + return "ti_st"; > + case SOCK_DGRAM: > + return "ti_dg"; > + case SOCK_RDM: > + return "ti_rd"; > + case SOCK_SEQPACKET: > + return "ti_sq"; > + default: > + return "???"; > + } > +} > + > /* Allocate and initialize a new buffer chunk */ static struct buf_chunk > *buf_chunk_new(void) { @@ -1274,6 +1314,9 @@ static void > sock_state_print(struct sockstat *s) > case AF_NETLINK: > sock_name = "nl"; > break; > + case AF_TIPC: > + sock_name = tipc_netid_name(s->type); > + break; > case AF_VSOCK: > sock_name = vsock_netid_name(s->type); > break; > @@ -4250,6 +4293,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; > }; > @@ -4494,6 +4636,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" > @@ -4510,15 +4653,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|pac > ket|netlink|vsock_stream|vsock_dgram}[,QUERY]\n" > +" QUERY := > {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|pac > ket|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" > @@ -4594,6 +4738,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' }, > @@ -4610,6 +4758,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' }, > @@ -4627,6 +4776,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 } > @@ -4699,6 +4849,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; > @@ -4725,6 +4878,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) @@ -4801,6 > +4956,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(); > @@ -4848,6 +5005,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; > @@ -4979,6 +5139,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<<TIPC_DB)) > + tipc_show(¤t_filter); > > if (show_users || show_proc_ctx || show_sock_ctx) > user_ent_destroy(); > -- > 2.1.4
On Fri, 23 Mar 2018 15:01:02 +0100 GhantaKrishnamurthy MohanKrishna <mohan.krishna.ghanta.krishnamurthy@ericsson.com> wrote: > For iproute 4.x > Allow TIPC socket statistics to be dumped with --tipc > and tipc specific info with --tipcinfo. > > Acked-by: Jon Maloy <jon.maloy@ericsson.com> > Signed-off-by: GhantaKrishnamurthy MohanKrishna <mohan.krishna.ghanta.krishnamurthy@ericsson.com> > Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@gmail.com> > --- > misc/ss.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 164 insertions(+), 2 deletions(-) > > diff --git a/misc/ss.c b/misc/ss.c > index e047f9c04582..812f45717af9 100644 > --- a/misc/ss.c > +++ b/misc/ss.c > @@ -45,6 +45,10 @@ > #include <linux/netlink_diag.h> > #include <linux/sctp.h> > #include <linux/vm_sockets_diag.h> > +#include <linux/net.h> > +#include <linux/tipc.h> > +#include <linux/tipc_netlink.h> > +#include <linux/tipc_sockets_diag.h> This needs to be against iproute2-next, not master since there is no tipc_sockets_diag.h in Linus's tree. All the header files for iproute2 include/uapi/linux come from upstream kernel via 'make headers_install'. Therefore you need to have tipc_sockets_diag.h in kernel already.
diff --git a/misc/ss.c b/misc/ss.c index e047f9c04582..812f45717af9 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -45,6 +45,10 @@ #include <linux/netlink_diag.h> #include <linux/sctp.h> #include <linux/vm_sockets_diag.h> +#include <linux/net.h> +#include <linux/tipc.h> +#include <linux/tipc_netlink.h> +#include <linux/tipc_sockets_diag.h> #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<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV))) +#define TIPC_SS_CONN ((1<<SS_ESTABLISHED)|(1<<SS_LISTEN)|(1<<SS_CLOSE)) #include "ssfilter.h" @@ -297,6 +304,10 @@ static const struct filter default_dbs[MAX_DB] = { .states = SS_CONN, .families = FAMILY_MASK(AF_VSOCK), }, + [TIPC_DB] = { + .states = TIPC_SS_CONN, + .families = FAMILY_MASK(AF_TIPC), + }, }; static const struct filter default_afs[AF_MAX] = { @@ -324,6 +335,10 @@ static const struct filter default_afs[AF_MAX] = { .dbs = VSOCK_DBM, .states = SS_CONN, }, + [AF_TIPC] = { + .dbs = (1 << TIPC_DB), + .states = TIPC_SS_CONN, + }, }; static int do_default = 1; @@ -364,6 +379,7 @@ static void filter_default_dbs(struct filter *f) filter_db_set(f, SCTP_DB); filter_db_set(f, VSOCK_ST_DB); filter_db_set(f, VSOCK_DG_DB); + filter_db_set(f, TIPC_DB); } static void filter_states_set(struct filter *f, int states) @@ -748,6 +764,14 @@ static const char *sctp_sstate_name[] = { [SCTP_STATE_SHUTDOWN_ACK_SENT] = "ACK_SENT", }; +static const char * const stype_nameg[] = { + "UNKNOWN", + [SOCK_STREAM] = "STREAM", + [SOCK_DGRAM] = "DGRAM", + [SOCK_RDM] = "RDM", + [SOCK_SEQPACKET] = "SEQPACKET", +}; + struct sockstat { struct sockstat *next; unsigned int type; @@ -888,6 +912,22 @@ static const char *vsock_netid_name(int type) } } +static const char *tipc_netid_name(int type) +{ + switch (type) { + case SOCK_STREAM: + return "ti_st"; + case SOCK_DGRAM: + return "ti_dg"; + case SOCK_RDM: + return "ti_rd"; + case SOCK_SEQPACKET: + return "ti_sq"; + default: + return "???"; + } +} + /* Allocate and initialize a new buffer chunk */ static struct buf_chunk *buf_chunk_new(void) { @@ -1274,6 +1314,9 @@ static void sock_state_print(struct sockstat *s) case AF_NETLINK: sock_name = "nl"; break; + case AF_TIPC: + sock_name = tipc_netid_name(s->type); + break; case AF_VSOCK: sock_name = vsock_netid_name(s->type); break; @@ -4250,6 +4293,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; }; @@ -4494,6 +4636,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" @@ -4510,15 +4653,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" @@ -4594,6 +4738,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' }, @@ -4610,6 +4758,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' }, @@ -4627,6 +4776,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 } @@ -4699,6 +4849,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; @@ -4725,6 +4878,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) @@ -4801,6 +4956,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(); @@ -4848,6 +5005,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; @@ -4979,6 +5139,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<<TIPC_DB)) + tipc_show(¤t_filter); if (show_users || show_proc_ctx || show_sock_ctx) user_ent_destroy();