From patchwork Tue Jun 16 16:02:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Craig Gallek X-Patchwork-Id: 485073 X-Patchwork-Delegate: shemminger@vyatta.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id B120B140295 for ; Wed, 17 Jun 2015 02:03:20 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b=ew46RlEG; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754349AbbFPQDQ (ORCPT ); Tue, 16 Jun 2015 12:03:16 -0400 Received: from mail-yk0-f169.google.com ([209.85.160.169]:33423 "EHLO mail-yk0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754061AbbFPQDO (ORCPT ); Tue, 16 Jun 2015 12:03:14 -0400 Received: by ykfr66 with SMTP id r66so17260367ykf.0 for ; Tue, 16 Jun 2015 09:03:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=FmTmFbOoh3MOgmiZKKvt0JthA6fJJTN1OZdhm2JxVxw=; b=ew46RlEGRWXSfGxpaWPNH0kAb7lowu/Guq8ZPbq2kfzcTzaSh9fw0ryuHHMm3ZeFIQ ORd7N8K0FOuTnoEkS8XIKOcPInhxX2KzI9VN7pzpXyAlbkijwIYYXJgbekTESv7z7MP7 qJq4zoUKbJvXWJ6B5PvZB99hO7LP0LltvCjOFEfdp7GD5zgNZrvlfxHAPr7zHkYJWJYU Kbn0FOkkEGZtvUtjOeQE61OuTlSHPsMsXK0QUm8eeXpHhZa85sPcDAXsaFaUCFZREyzE 5XlikNIjSSnfZHdN7pKdeqjHXJbAtav0/2nlGaoiSHaaTCM/E1ib0RDqRn/xklSFOhJa XwRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=FmTmFbOoh3MOgmiZKKvt0JthA6fJJTN1OZdhm2JxVxw=; b=URtFqU/bOK4DG6blFNU1TzkWk4kayyRTSRGqCSi77IFldcHhMAG1urhpruVrE5/20V F8zSkSCkeHYhBFVoSvk1xyH/E1Av3etsfCpuG5k7d9dBdAB99w4GnLM3FiY2IjgfK/fD ERXI8L7dDsN19Ahw9E9g+413ebsd72ciLgUIqqI8r8M2wUCK3n4n9zSM8f95zndjtL/g qKCz7hCzSkj+Umro4VufgV2IT/SL58wB/Xc486IV0sI4wjA91+MS84JMbvEqPXP2KNas oF0h8Yv5zYX6/CX4Rvh4rKUI9Lxc6+ZTMbti8ULhUS4U5yHwsbb7/Ifk8JqpOvOa6x6u MPoA== X-Gm-Message-State: ALoCoQkzZn9DRdQg8aTlRHJwdZ5flAIPQapsoMy4FYmzYcWCzvWQlOUWq8KTnjaUjGE2TV0ECRzD X-Received: by 10.129.114.86 with SMTP id n83mr1363027ywc.102.1434470593104; Tue, 16 Jun 2015 09:03:13 -0700 (PDT) Received: from cgallek-warp18.nyc.corp.google.com ([172.26.105.104]) by mx.google.com with ESMTPSA id c76sm521063yhn.17.2015.06.16.09.03.11 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 16 Jun 2015 09:03:12 -0700 (PDT) From: Craig Gallek To: netdev@vger.kernel.org Cc: stephen@networkplumber.org, edumazet@google.com, Craig Gallek Subject: [PATCH iproute2] ss: Include -E option for socket destroy events Date: Tue, 16 Jun 2015 12:02:58 -0400 Message-Id: <1434470578-25796-1-git-send-email-kraig@google.com> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- include/linux/inet_diag.h | 3 +- include/linux/sock_diag.h | 10 +++++++ misc/ss.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 2 deletions(-) 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<