From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0890FC282C2 for ; Fri, 25 Jan 2019 07:20:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C0BF2218DE for ; Fri, 25 Jan 2019 07:20:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HzL4xmdY" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728283AbfAYHUF (ORCPT ); Fri, 25 Jan 2019 02:20:05 -0500 Received: from mail-pf1-f195.google.com ([209.85.210.195]:33815 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726271AbfAYHUF (ORCPT ); Fri, 25 Jan 2019 02:20:05 -0500 Received: by mail-pf1-f195.google.com with SMTP id h3so4349567pfg.1 for ; Thu, 24 Jan 2019 23:20:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=M4iu5Nzz6YVMORB+ltgtDAuAsNHlc6ycQgbpCk6sDF8=; b=HzL4xmdY3ST5Ci3NzBAbHMHB9C+E7lRnrd1Y+C8ujcYY4iaELvpT47356ILJs3OT/q 5gy+WaPiQ6kw9L8yjTXsLyoown4hok4urvhRU+cDFRiZiZbLGl3/rOMyxqvoUHOvd7dk GU4nGSO/b0fwrtRvBoU6BlusI74HL7w5dBfQ2K903oc0w63m3BSh6BsEJ2BJdlinHPOz zhzLY0jOz2slhFvAZ97gNEALpuCa9csUzPwKSd42N0cGOjGDF9j4quzpqD0ceqPvHkdK BbfqUwQj0boDtPeF+Rj7sGWQq1apuHcvrSMqaxLSRsT5hTut/MjBfowKOWXpN4IEoykW QFhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=M4iu5Nzz6YVMORB+ltgtDAuAsNHlc6ycQgbpCk6sDF8=; b=il1F0mdROcUG5Cz1C9u3A76iWvL843qtLKYzufju6nOT8r8Az3Ggsyy03Sc3U4JVQv qPJQMkUC5KvMMDOAU7o5uUo+aTK8D7yd88pDVm1xZ1yLEZCYGp4vgKjX+Wsfs/IPfKfq eaxVsfQcb0MBVqsQQ+yPZiNqNMSty7/HtXVQxp0kFx/DZBEf2ugJl9F8AWcxv0/optBq 853TMOVCo3fGQHtN+6kM45/3W4xkVOrWlC90LDDPSRtJ+VmwdzwGWtNI8os6i+l8ws4w PAUpxE4AFoTfeD1r3D0gsOx/+U78GYWedO2anGgJJVbOUvdJ3WdFtmd92jSd2gpAyuJM KWcw== X-Gm-Message-State: AJcUuke4b/iwuf0cXTo0GVxoWY0HzMA3Nt7Kih4Jo0DDbq7dWU4EuWDI DOivuva9fkZcfqxaR9EvYsxrbAIPlIk= X-Google-Smtp-Source: ALg8bN4EwwvxedG0gc3z6/vr/VQsP7P8FO4aAF3BntFXyw/DsVohw1Kzpw3Sdiup9Wt0uA2aR3J7CQ== X-Received: by 2002:aa7:8758:: with SMTP id g24mr9640551pfo.250.1548400804314; Thu, 24 Jan 2019 23:20:04 -0800 (PST) Received: from btopel-mobl.isw.intel.com ([192.55.54.40]) by smtp.gmail.com with ESMTPSA id y12sm41373185pfk.70.2019.01.24.23.20.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 Jan 2019 23:20:03 -0800 (PST) From: bjorn.topel@gmail.com To: netdev@vger.kernel.org, stephen@networkplumber.org Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , magnus.karlsson@intel.com, magnus.karlsson@gmail.com Subject: [PATCH iproute2-next 2/2] ss: add AF_XDP support Date: Fri, 25 Jan 2019 08:18:48 +0100 Message-Id: <20190125071848.25959-3-bjorn.topel@gmail.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190125071848.25959-1-bjorn.topel@gmail.com> References: <20190125071848.25959-1-bjorn.topel@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Björn Töpel AF_XDP is an address family that is optimized for high performance packet processing. This patch adds AF_XDP support to ss(8) so that sockets can be queried and monitored. Signed-off-by: Björn Töpel --- man/man8/ss.8 | 9 ++- misc/ss.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 172 insertions(+), 5 deletions(-) diff --git a/man/man8/ss.8 b/man/man8/ss.8 index 553a6cf46f0e..bc120fd78716 100644 --- a/man/man8/ss.8 +++ b/man/man8/ss.8 @@ -324,16 +324,19 @@ Display SCTP sockets. .B \-\-vsock Display vsock sockets (alias for -f vsock). .TP +.B \-\-xdp +Display XDP sockets (alias for -f xdp). +.TP .B \-f FAMILY, \-\-family=FAMILY Display sockets of type FAMILY. -Currently the following families are supported: unix, inet, inet6, link, netlink, vsock. +Currently the following families are supported: unix, inet, inet6, link, netlink, vsock, xdp. .TP .B \-A QUERY, \-\-query=QUERY, \-\-socket=QUERY List of socket tables to dump, separated by commas. The following identifiers are understood: all, inet, tcp, udp, raw, unix, packet, netlink, unix_dgram, unix_stream, unix_seqpacket, packet_raw, packet_dgram, dccp, sctp, -vsock_stream, vsock_dgram. Any item in the list may optionally be prefixed by -an exclamation mark +vsock_stream, vsock_dgram, xdp Any item in the list may optionally be +prefixed by an exclamation mark .RB ( ! ) to exclude that socket table from being dumped. .TP diff --git a/misc/ss.c b/misc/ss.c index 3589ebedc5a0..8e5cc16b6f52 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -42,6 +42,7 @@ #include #include /* for MAX_ADDR_LEN */ #include +#include #include #include #include @@ -198,6 +199,7 @@ enum { VSOCK_ST_DB, VSOCK_DG_DB, TIPC_DB, + XDP_DB, MAX_DB }; @@ -309,6 +311,10 @@ static const struct filter default_dbs[MAX_DB] = { .states = TIPC_SS_CONN, .families = FAMILY_MASK(AF_TIPC), }, + [XDP_DB] = { + .states = (1 << SS_CLOSE), + .families = FAMILY_MASK(AF_XDP), + }, }; static const struct filter default_afs[AF_MAX] = { @@ -340,6 +346,10 @@ static const struct filter default_afs[AF_MAX] = { .dbs = (1 << TIPC_DB), .states = TIPC_SS_CONN, }, + [AF_XDP] = { + .dbs = (1 << XDP_DB), + .states = (1 << SS_CLOSE), + }, }; static int do_default = 1; @@ -366,7 +376,7 @@ static int filter_db_parse(struct filter *f, const char *s) ENTRY(all, UDP_DB, DCCP_DB, TCP_DB, RAW_DB, UNIX_ST_DB, UNIX_DG_DB, UNIX_SQ_DB, PACKET_R_DB, PACKET_DG_DB, NETLINK_DB, - SCTP_DB, VSOCK_ST_DB, VSOCK_DG_DB), + SCTP_DB, VSOCK_ST_DB, VSOCK_DG_DB, XDP_DB), ENTRY(inet, UDP_DB, DCCP_DB, TCP_DB, SCTP_DB, RAW_DB), ENTRY(udp, UDP_DB), ENTRY(dccp, DCCP_DB), @@ -391,6 +401,7 @@ static int filter_db_parse(struct filter *f, const char *s) ENTRY(v_str, VSOCK_ST_DB), /* alias for vsock_stream */ ENTRY(vsock_dgram, VSOCK_DG_DB), ENTRY(v_dgr, VSOCK_DG_DB), /* alias for vsock_dgram */ + ENTRY(xdp, XDP_DB), #undef ENTRY }; bool enable = true; @@ -1331,6 +1342,9 @@ static void sock_state_print(struct sockstat *s) case AF_VSOCK: sock_name = vsock_netid_name(s->type); break; + case AF_XDP: + sock_name = "xdp"; + break; default: sock_name = "unknown"; } @@ -4055,6 +4069,142 @@ static int packet_show(struct filter *f) return rc; } +static int xdp_stats_print(struct sockstat *s, const struct filter *f) +{ + const char *addr, *port; + char q_str[16]; + + s->local.family = s->remote.family = AF_XDP; + + if (f->f) { + if (run_ssfilter(f->f, s) == 0) + return 1; + } + + sock_state_print(s); + + if (s->iface) { + addr = xll_index_to_name(s->iface); + snprintf(q_str, sizeof(q_str), "q%d", s->lport); + port = q_str; + sock_addr_print(addr, ":", port, NULL); + } else { + sock_addr_print("", "*", "", NULL); + } + + sock_addr_print("", "*", "", NULL); + + proc_ctx_print(s); + + if (show_details) + sock_details_print(s); + + return 0; +} + +static void xdp_show_ring(const char *name, struct xdp_diag_ring *ring) +{ + out("\n\t%s(", name); + out("entries:%u", ring->entries); + out(")"); +} + +static void xdp_show_umem(struct xdp_diag_umem *umem, struct xdp_diag_ring *fr, + struct xdp_diag_ring *cr) +{ + out("\n\tumem("); + out("id:%u", umem->id); + out(",size:%llu", umem->size); + out(",num_pages:%u", umem->num_pages); + out(",chunk_size:%u", umem->chunk_size); + out(",headroom:%u", umem->headroom); + out(",ifindex:%u", umem->ifindex); + out(",qid:%u", umem->queue_id); + out(",zc:%u", umem->flags & XDP_DU_F_ZEROCOPY); + out(",refs:%u", umem->refs); + out(")"); + + if (fr) + xdp_show_ring("fr", fr); + if (cr) + xdp_show_ring("cr", cr); +} + +static int xdp_show_sock(struct nlmsghdr *nlh, void *arg) +{ + struct xdp_diag_ring *rx = NULL, *tx = NULL, *fr = NULL, *cr = NULL; + struct xdp_diag_msg *msg = NLMSG_DATA(nlh); + struct rtattr *tb[XDP_DIAG_MAX + 1]; + struct xdp_diag_info *info = NULL; + struct xdp_diag_umem *umem = NULL; + const struct filter *f = arg; + struct sockstat stat = {}; + + parse_rtattr(tb, XDP_DIAG_MAX, (struct rtattr *)(msg + 1), + nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg))); + + stat.type = msg->xdiag_type; + stat.ino = msg->xdiag_ino; + stat.state = SS_CLOSE; + stat.sk = cookie_sk_get(&msg->xdiag_cookie[0]); + + if (tb[XDP_DIAG_INFO]) { + info = RTA_DATA(tb[XDP_DIAG_INFO]); + stat.iface = info->ifindex; + stat.lport = info->queue_id; + } + + if (tb[XDP_DIAG_UID]) + stat.uid = rta_getattr_u32(tb[XDP_DIAG_UID]); + if (tb[XDP_DIAG_RX_RING]) + rx = RTA_DATA(tb[XDP_DIAG_RX_RING]); + if (tb[XDP_DIAG_TX_RING]) + tx = RTA_DATA(tb[XDP_DIAG_TX_RING]); + if (tb[XDP_DIAG_UMEM]) + umem = RTA_DATA(tb[XDP_DIAG_UMEM]); + if (tb[XDP_DIAG_UMEM_FILL_RING]) + fr = RTA_DATA(tb[XDP_DIAG_UMEM_FILL_RING]); + if (tb[XDP_DIAG_UMEM_COMPLETION_RING]) + cr = RTA_DATA(tb[XDP_DIAG_UMEM_COMPLETION_RING]); + if (tb[XDP_DIAG_MEMINFO]) { + __u32 *skmeminfo = RTA_DATA(tb[XDP_DIAG_MEMINFO]); + + stat.rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC]; + } + + if (xdp_stats_print(&stat, f)) + return 0; + + if (show_details) { + if (rx) + xdp_show_ring("rx", rx); + if (tx) + xdp_show_ring("tx", tx); + if (umem) + xdp_show_umem(umem, fr, cr); + } + + if (show_mem) + print_skmeminfo(tb, XDP_DIAG_MEMINFO); // really? + + + return 0; +} + +static int xdp_show(struct filter *f) +{ + DIAG_REQUEST(req, struct xdp_diag_req r); + + if (!filter_af_get(f, AF_XDP) || !(f->states & (1 << SS_CLOSE))) + return 0; + + req.r.sdiag_family = AF_XDP; + req.r.xdiag_show = XDP_SHOW_INFO | XDP_SHOW_RING_CFG | XDP_SHOW_UMEM | + XDP_SHOW_MEMINFO; + + return handle_netlink_request(f, &req.nlh, sizeof(req), xdp_show_sock); +} + static int netlink_show_one(struct filter *f, int prot, int pid, unsigned int groups, int state, int dst_pid, unsigned int dst_group, @@ -4442,6 +4592,9 @@ static int generic_show_sock(struct nlmsghdr *nlh, void *arg) case AF_VSOCK: ret = vsock_show_sock(nlh, arg); break; + case AF_XDP: + ret = xdp_show_sock(nlh, arg); + break; default: ret = -1; } @@ -4679,7 +4832,7 @@ static void _usage(FILE *dest) " --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|tipc|help}\n" +" FAMILY := {inet|inet6|link|unix|netlink|vsock|tipc|xdp|help}\n" "\n" " -K, --kill forcibly close sockets, display what was closed\n" " -H, --no-header Suppress header line\n" @@ -4765,6 +4918,9 @@ static int scan_state(const char *state) #define OPT_TIPCSOCK 257 #define OPT_TIPCINFO 258 +/* Values of 'x' are already used so a non-character is used */ +#define OPT_XDPSOCK 259 + static const struct option long_opts[] = { { "numeric", 0, 0, 'n' }, { "resolve", 0, 0, 'r' }, @@ -4802,6 +4958,7 @@ static const struct option long_opts[] = { { "tipcinfo", 0, 0, OPT_TIPCINFO}, { "kill", 0, 0, 'K' }, { "no-header", 0, 0, 'H' }, + { "xdp", 0, 0, OPT_XDPSOCK}, { 0 } }; @@ -4889,6 +5046,9 @@ int main(int argc, char *argv[]) case '0': filter_af_set(¤t_filter, AF_PACKET); break; + case OPT_XDPSOCK: + filter_af_set(¤t_filter, AF_XDP); + break; case 'f': if (strcmp(optarg, "inet") == 0) filter_af_set(¤t_filter, AF_INET); @@ -4904,6 +5064,8 @@ int main(int argc, char *argv[]) filter_af_set(¤t_filter, AF_TIPC); else if (strcmp(optarg, "vsock") == 0) filter_af_set(¤t_filter, AF_VSOCK); + else if (strcmp(optarg, "xdp") == 0) + filter_af_set(¤t_filter, AF_XDP); else if (strcmp(optarg, "help") == 0) help(); else { @@ -5101,6 +5263,8 @@ int main(int argc, char *argv[]) vsock_show(¤t_filter); if (current_filter.dbs & (1<