Message ID | 1434470578-25796-1-git-send-email-kraig@google.com |
---|---|
State | Superseded, archived |
Delegated to: | stephen hemminger |
Headers | show |
On Tue, 2015-06-16 at 12:02 -0400, Craig Gallek wrote: > Use the IPv4/IPv6/TCP/UDP multicast groups of NETLINK_SOCK_DIAG > to filter and display socket statistics as they are destroyed. > > Kernel support patch series: 24029a3603cfa633e8bc2b3fb3e48e76c497831d > > Signed-off-by: Craig Gallek <kraig@google.com> > --- > include/linux/inet_diag.h | 3 +- > include/linux/sock_diag.h | 10 +++++++ > misc/ss.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++- > 3 files changed, 83 insertions(+), 2 deletions(-) I am not sure filter works, and apparently some fields are not properly reported ? (source port for example looks wrong) (Note : you probably need to filter in user space, but ss should already have support for this) lpaa23:~# ./ss -Eit dst 10.246.7.152 State Recv-Q Send-Q Local Address:Port Peer Address:Port UNCONN 0 1 ::ffff:10.246.7.151:* ::ffff:10.126.178.16:14354 wscale:7,7 rto:221 rtt:20.165/5.91 ato:40 mss:1448 cwnd:10 send 5.7Mbps lastsnd:21 lastrcv:15023 lastack:1 pacing_rate 11.5Mbps unacked:1 rcv_rtt:20 rcv_space:28960 UNCONN 0 1 127.0.0.1:* 127.0.0.1:9551 rto:1000 mss:524 cwnd:10 lastsnd:67817 lastrcv:67817 lastack:67817 unacked:1 UNCONN 0 1 127.0.0.1:* 127.0.0.1:9551 rto:1000 mss:524 cwnd:10 lastsnd:67818 lastrcv:67818 lastack:67818 unacked:1 UNCONN 0 1 127.0.0.1:* 127.0.0.1:9551 rto:1000 mss:524 cwnd:10 lastsnd:68742 lastrcv:68742 lastack:68742 unacked:1 UNCONN 0 0 10.246.7.151:* 10.246.7.152:50227 wscale:7,7 rto:201 rtt:0.203/0.209 mss:1448 cwnd:254 ssthresh:251 send 14494.3Mbps lastsnd:1 lastrcv:71533 pacing_rate 28970.7Mbps retrans:0/5 rcv_space:29200 UNCONN 0 0 10.246.7.151:* 10.246.7.152:12865 wscale:7,7 rto:201 rtt:0.363/0.375 ato:40 mss:1448 cwnd:10 ssthresh:293 send 319.1Mbps lastsnd:1004 lastrcv:1 lastack:1 pacing_rate 636.7Mbps rcv_rtt:126.125 rcv_space:29200 UNCONN 0 1 127.0.0.1:* 127.0.0.1:9551 rto:1000 mss:524 cwnd:10 lastsnd:73036 lastrcv:73036 lastack:73036 unacked:1 ^C -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> I am not sure filter works, and apparently some fields are not properly > reported ? (source port for example looks wrong) > > (Note : you probably need to filter in user space, but ss should already > have support for this) Ah, good catch on the filter. It can be fixed by - if ((err = inet_show_sock(h, NULL, diag_arg->protocol)) < 0) + if ((err = inet_show_sock(h, diag_arg->f, diag_arg->protocol)) < 0) in show_one_inet_sock. I believe this worked previously because the filter determined the parameters of the netlink request, effectively causing the filtering to happen in the kernel. However, if the ssfilter defined a parameter that could not be used select sockets via the netlink request (either because it is a concept not available in the request structure or because the multicast groups have no request concept), this user space filtering parameter would be necessary. Perhaps this was an optimization to not do userspace filtering when we know we won't need it? In that case, my updated version of this patch should probably set the filter parameter of inet_diag_arg to NULL in the case of a get request and to the actual userspace filter in the case of monitoring the broadcast data. The source port issue is a harder problem (related to the kernel patches, not this one). The point at which socket information is broadcast happens after the unhash callback of the appropriate protocol (called in sk_common_release). This process sets the source port of the socket to zero (via __inet_put_port for tcp and udp_lib_unhash for udp). If we want the source port to be returned, I believe the only options are broadcasting earlier in the destruction path (potentially missing any activity that may happen after that point) or to store the source port in an additional location for later use... -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index 0fb76bb..e83340b 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -111,9 +111,10 @@ enum { INET_DIAG_SKMEMINFO, INET_DIAG_SHUTDOWN, INET_DIAG_DCTCPINFO, + INET_DIAG_PROTOCOL, /* response attribute only */ }; -#define INET_DIAG_MAX INET_DIAG_DCTCPINFO +#define INET_DIAG_MAX INET_DIAG_PROTOCOL /* INET_DIAG_MEM */ diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h index 78996e2..024e1f4 100644 --- a/include/linux/sock_diag.h +++ b/include/linux/sock_diag.h @@ -23,4 +23,14 @@ enum { SK_MEMINFO_VARS, }; +enum sknetlink_groups { + SKNLGRP_NONE, + SKNLGRP_INET_TCP_DESTROY, + SKNLGRP_INET_UDP_DESTROY, + SKNLGRP_INET6_TCP_DESTROY, + SKNLGRP_INET6_UDP_DESTROY, + __SKNLGRP_MAX, +}; +#define SKNLGRP_MAX (__SKNLGRP_MAX - 1) + #endif /* __SOCK_DIAG_H__ */ diff --git a/misc/ss.c b/misc/ss.c index dba0901..9e59257 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -99,6 +99,7 @@ int show_proc_ctx = 0; 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 netid_width; int state_width; @@ -2030,6 +2031,9 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol) if (f && f->f && run_ssfilter(f->f, &s) == 0) return 0; + if (tb[INET_DIAG_PROTOCOL]) + protocol = *(__u8 *)RTA_DATA(tb[INET_DIAG_PROTOCOL]); + inet_stats_print(&s, protocol); if (show_options) { @@ -3217,6 +3221,64 @@ static int netlink_show(struct filter *f) return 0; } +struct sock_diag_msg { + __u8 sdiag_family; +}; + +static int generic_show_sock(const struct sockaddr_nl *addr, + struct nlmsghdr *nlh, void *arg) +{ + struct sock_diag_msg *r = NLMSG_DATA(nlh); + struct inet_diag_arg inet_arg = { .f = arg, .protocol = IPPROTO_MAX }; + + switch (r->sdiag_family) { + case AF_INET: + case AF_INET6: + return show_one_inet_sock(addr, nlh, &inet_arg); + case AF_UNIX: + return unix_show_sock(addr, nlh, arg); + case AF_PACKET: + return packet_show_sock(addr, nlh, arg); + case AF_NETLINK: + return netlink_show_sock(addr, nlh, arg); + default: + return -1; + } +} + +static int handle_follow_request(struct filter *f) +{ + int ret = -1; + int groups = 0; + struct rtnl_handle rth; + + if (f->families & (1 << AF_INET) && f->dbs & (1 << TCP_DB)) + groups |= 1 << (SKNLGRP_INET_TCP_DESTROY - 1); + if (f->families & (1 << AF_INET) && f->dbs & (1 << UDP_DB)) + groups |= 1 << (SKNLGRP_INET_UDP_DESTROY - 1); + if (f->families & (1 << AF_INET6) && f->dbs & (1 << TCP_DB)) + groups |= 1 << (SKNLGRP_INET6_TCP_DESTROY - 1); + if (f->families & (1 << AF_INET6) && f->dbs & (1 << UDP_DB)) + groups |= 1 << (SKNLGRP_INET6_UDP_DESTROY - 1); + + if (groups == 0) + return -1; + + if (rtnl_open_byproto(&rth, groups, NETLINK_SOCK_DIAG)) + return -1; + + rth.dump = 0; + rth.local.nl_pid = 0; + + if (rtnl_dump_filter(&rth, generic_show_sock, f)) + goto Exit; + + ret = 0; +Exit: + rtnl_close(&rth); + return ret; +} + struct snmpstat { int tcp_estab; @@ -3399,6 +3461,7 @@ static void _usage(FILE *dest) " -i, --info show internal TCP 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" " -Z, --context display process SELinux security contexts\n" " -z, --contexts display process and socket SELinux security contexts\n" " -N, --net switch to the specified network namespace name\n" @@ -3481,6 +3544,7 @@ static const struct option long_opts[] = { { "info", 0, 0, 'i' }, { "processes", 0, 0, 'p' }, { "bpf", 0, 0, 'b' }, + { "events", 0, 0, 'E' }, { "dccp", 0, 0, 'd' }, { "tcp", 0, 0, 't' }, { "udp", 0, 0, 'u' }, @@ -3516,7 +3580,7 @@ int main(int argc, char *argv[]) int ch; int state_filter = 0; - while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbf:miA:D:F:vVzZN:", + while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbEf:miA:D:F:vVzZN:", long_opts, NULL)) != EOF) { switch(ch) { case 'n': @@ -3546,6 +3610,9 @@ int main(int argc, char *argv[]) show_options = 1; show_bpf++; break; + case 'E': + follow_events = 1; + break; case 'd': filter_db_set(¤t_filter, DCCP_DB); break; @@ -3838,6 +3905,9 @@ int main(int argc, char *argv[]) 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)
Use the IPv4/IPv6/TCP/UDP multicast groups of NETLINK_SOCK_DIAG to filter and display socket statistics as they are destroyed. Kernel support patch series: 24029a3603cfa633e8bc2b3fb3e48e76c497831d Signed-off-by: Craig Gallek <kraig@google.com> --- include/linux/inet_diag.h | 3 +- include/linux/sock_diag.h | 10 +++++++ misc/ss.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 2 deletions(-)