Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp947737pxa; Wed, 5 Aug 2020 17:18:12 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzef4yF4jZfwmFFH1ypFAvzOVu9Mr/uYH1jpMuSjym8Uv9ukStrEuG9AqmAzevavw0RpdYL X-Received: by 2002:aa7:cf06:: with SMTP id a6mr1742647edy.293.1596673092105; Wed, 05 Aug 2020 17:18:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1596673092; cv=none; d=google.com; s=arc-20160816; b=DAIZ+OLGkCq9APqaoptC/BuhCQbhbBiAJjHw03zGw1QSXS2X/YkwyiD18aJbvIVvEJ Wf3fL6/cCN6FIoDVrAiB3xUmRTd0k9YxSX6bDf4NpwbW/l0jcOtBuV2bLt3QvBvqvlzn opcuyqGwKi2NXnd6l1rhMYREUo6B1pyT9LD+5I9BL7TrCvOrOaBVNf8TuPw18TmuhFhM qyQ39Zxtou5/F17Yoiu9Zn/Lutsx7slEOoFWY/hZErWDPNIWXdbbV/b12qghtSC2z0sT l6H8tdZtI7BbP6etlfWXVH9uVE+C4zPaLOBcaS890A8iZdNDOudH3Qn3VWlwVARUtiBP E72A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:dkim-signature; bh=LfxCPN/4iZPLCZVOVhzdLvyoPvK+axLJbpywb7N3FLc=; b=XH+7ezvxh4JU4isvWeQluNP6ClCnd+wd01pBsvmaz7mpebcWNytFYmy5ulVBhx2Rio yNTYyLne+/jrrIo5Kg7bfoEUbFZ4Fh7yOjswW8uUu4tUlsXk0KCHNdrPqOIouMNZQmM5 zq7r+ezB5bK/QoFqUQCh4HQjQrot9lscgeQpP7LxETfqbgDJ6wynbFisKa+WKz5d3GyG UT1PG3DCPFylcGfSj8nd3OeEyn61UW7uTrTUBcA2q4AHj3KwZxEZud8Qp2KW+iUHm/dl H6ZwSQGnk45DWWBR0ihDrW6VweTlF63DYG/GrFcq/TfK2jbuWmadlwsZduF/kywRZHAG 7SBA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=L9FfO0hW; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a18si2394136ejr.262.2020.08.05.17.17.49; Wed, 05 Aug 2020 17:18:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=L9FfO0hW; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726862AbgHFAPX (ORCPT + 99 others); Wed, 5 Aug 2020 20:15:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59774 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726514AbgHFAO4 (ORCPT ); Wed, 5 Aug 2020 20:14:56 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 363B2C0617A9 for ; Wed, 5 Aug 2020 17:14:52 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id a127so59293607ybb.14 for ; Wed, 05 Aug 2020 17:14:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=LfxCPN/4iZPLCZVOVhzdLvyoPvK+axLJbpywb7N3FLc=; b=L9FfO0hW7Uu2iVdQvQ/ixa/M4r537CjMlQgMCGXcJ/u6Nu3MLyY86tPRNY5fK2GcDz qc4qeFfnS+1YeBs8bIYjcoTBwh4od41NTE8rJi3+xesXOL+ZGTXuJrWz2h5d+Ea8Bx3Y 3sacGsHAoc+7ZGqNXypsjdaLmioVWtipZe1grKepqd2yzT2r2g5rj/KN7lZkCRhY7xTV qaorXEjcJ+EH6zKdt1ftiE/f7nI1Lxo0vog+SeSMhSGB0bSpC3zABgDSpErmpyhiOb9R 5xCVXLZTEpSgKPIQBJTz6l+kAQ4N4/FXW8ZqISkOmc8HNzo6UN/K68UAKYTuNrR58gAH /HmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=LfxCPN/4iZPLCZVOVhzdLvyoPvK+axLJbpywb7N3FLc=; b=LterwENY1aZJIh61a0v+moSjm5jx92wHSp+vQ5BrBEL0ziSniNedQ3Cpw3WXtWP3zn UbJ++9Hx2DRulKQA4lfyB851gGWt3kQxJeMJJ+g/xYdIcH+CcHWHmNqMlf5VWPX+s1fA sXXxYwBXQip9646riMlqoAfl1atfgQXGs0nXVYjJ0VE4D9dhk5Ka9X79Q0hi0FINCw9R XflbUv0w4OeEBx9Ndlak+cRt5xRHmqVVtaeAkZP6inBiwww4S6q1vMgt0mAzgcCWZ5UA SY4Rn7PlNmBJwIkCqATvCa3j4VvR/gm10/ESm6PO6SjR2KRRLKPeA+yQc+iXihknj8eM 4+Yg== X-Gm-Message-State: AOAM531nVtBwznBTfI6dyg3fwZ9rBkd1uYzR9DlADKDd3o7t0WoMesuR TAyxCcnc5pNrJZgBoD0t6qIgFuZjOcMRB4eEQ2EMf32vPApVCH2fYl2P1R10gzIOV+RdXKDPDL3 pqQ9mrjybs+VboducxDW/g27a61AtYRZ68FPPJ/MuKJmQrWcIKGea4baTtga3ytnCDfggJw0= X-Received: by 2002:a25:bbd2:: with SMTP id c18mr8387526ybk.495.1596672891370; Wed, 05 Aug 2020 17:14:51 -0700 (PDT) Date: Wed, 5 Aug 2020 17:14:31 -0700 In-Reply-To: <20200806001431.2072150-1-jwadams@google.com> Message-Id: <20200806001431.2072150-8-jwadams@google.com> Mime-Version: 1.0 References: <20200806001431.2072150-1-jwadams@google.com> X-Mailer: git-send-email 2.28.0.236.gb10cc79966-goog Subject: [RFC PATCH 7/7] net-metricfs: Export /proc/net/dev via metricfs. From: Jonathan Adams To: linux-kernel@vger.kernel.org Cc: kvm@vger.kernel.org, Paolo Bonzini , Jim Mattson , David Rientjes , Jonathan Adams , Laurent Chavey Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Laurent Chavey Export /proc/net/dev statistics via metricfs. The implementation reports all the devices that are in the same network namespace as the process reading metricfs. The implementation does not report devices across network namespaces Signed-off-by: Laurent Chavey [jwadams@google.com: ported code to 5.8-pre6, cleaned up googleisms ] Signed-off-by: Jonathan Adams --- net/core/Makefile | 1 + net/core/net_metricfs.c | 194 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 net/core/net_metricfs.c diff --git a/net/core/Makefile b/net/core/Makefile index 3e2c378e5f31..7647380b9679 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_classifier.o obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o obj-$(CONFIG_LWTUNNEL) += lwtunnel.o +obj-$(CONFIG_METRICFS) += net_metricfs.o obj-$(CONFIG_LWTUNNEL_BPF) += lwt_bpf.o obj-$(CONFIG_BPF_STREAM_PARSER) += sock_map.o obj-$(CONFIG_DST_CACHE) += dst_cache.o diff --git a/net/core/net_metricfs.c b/net/core/net_metricfs.c new file mode 100644 index 000000000000..82f0f797b0b0 --- /dev/null +++ b/net/core/net_metricfs.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* net_metricfs: Exports network counters using metricfs. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct metric_def { + struct metric *metric; + size_t off; + char *name; + char *desc; +}; + +/* If needed, we could export this via a function for other /net users */ +static struct metricfs_subsys *net_root_subsys; +static struct metricfs_subsys *dev_subsys; +static struct metricfs_subsys *dev_stats_subsys; + +static struct metric_def metric_def[] = { + {NULL, offsetof(struct rtnl_link_stats64, rx_bytes), + "rx_bytes", "net device received bytes count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_packets), + "rx_packets", "net device received packets count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_errors), + "rx_errors", "net device received errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_dropped), + "rx_dropped", "net device dropped packets count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_missed_errors), + "rx_missed_errors", "net device missed errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_fifo_errors), + "rx_fifo_errors", "net device fifo errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_length_errors), + "rx_length_errors", "net device length errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_over_errors), + "rx_over_errors", "net device received overflow errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_crc_errors), + "rx_crc_errors", "net device received crc errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_frame_errors), + "rx_frame_errors", "net device received frame errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, rx_compressed), + "rx_compressed", "net device received compressed packet count"}, + {NULL, offsetof(struct rtnl_link_stats64, multicast), + "rx_multicast", "net device received multicast packet count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_bytes), + "tx_bytes", "net device transmited bytes count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_packets), + "tx_packets", "net device transmited packets count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_errors), + "tx_errors", "net device transmited errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_dropped), + "tx_dropped", "net device transmited packet drop count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_fifo_errors), + "tx_fifo_errors", "net device transmit fifo errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, collisions), + "tx_collision", "net device transmit collisions count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_carrier_errors), + "tx_carrier_errors", "net device transmit carrier errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_aborted_errors), + "tx_aborted_errors", "net device transmit aborted errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_window_errors), + "tx_window_errors", "net device transmit window errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_heartbeat_errors), + "tx_heartbeat_errors", "net device transmit heartbeat errors count"}, + {NULL, offsetof(struct rtnl_link_stats64, tx_compressed), + "tx_compressed_errors", "net device transmit compressed count"}, +}; + +static __init int init_net_subsys(void) +{ + net_root_subsys = metricfs_create_subsys("net", NULL); + if (!net_root_subsys) { + WARN_ONCE(1, "Net metricfs root not created."); + return -1; + } + return 0; +} + +late_initcall(init_net_subsys); + +static void dev_stats_emit(struct metric_emitter *e, + struct net_device *dev, + struct metric_def *metricd) +{ + struct rtnl_link_stats64 temp; + const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp); + + if (stats) { + __u8 *ptr = (((__u8 *)stats) + metricd->off); + + METRIC_EMIT_INT(e, *(__u64 *)ptr, dev->name, NULL); + } +} + +/* metricfs export function */ +static void dev_stats_fn(struct metric_emitter *e, void *parm) +{ + struct net_device *dev; + struct net *net; + struct nsproxy *nsproxy = current->nsproxy; + + rcu_read_lock(); + for_each_net_rcu(net) { + /* skip namespaces not associated with the caller */ + if (nsproxy->net_ns != net) + continue; + for_each_netdev_rcu(net, dev) { + dev_stats_emit(e, dev, (struct metric_def *)parm); + } + } + rcu_read_unlock(); +} + +static void clean_dev_stats_subsys(void) +{ + int x; + int metric_count = sizeof(metric_def) / sizeof(struct metric_def); + + for (x = 0; x < metric_count; x++) { + if (metric_def[x].metric) { + metric_unregister(metric_def[x].metric); + metric_def[x].metric = NULL; + } + } + if (dev_stats_subsys) + metricfs_destroy_subsys(dev_stats_subsys); + if (dev_subsys) + metricfs_destroy_subsys(dev_subsys); + dev_stats_subsys = NULL; + dev_subsys = NULL; +} + +static int __init init_dev_stats_subsys(void) +{ + int x; + int metric_count = sizeof(metric_def) / sizeof(struct metric_def); + + dev_subsys = NULL; + dev_stats_subsys = NULL; + if (!net_root_subsys) { + WARN_ONCE(1, "Net metricfs root not initialized."); + goto error; + } + dev_subsys = + metricfs_create_subsys("dev", net_root_subsys); + if (!dev_subsys) { + WARN_ONCE(1, "Net metricfs dev not created."); + goto error; + } + dev_stats_subsys = + metricfs_create_subsys("stats", dev_subsys); + if (!dev_stats_subsys) { + WARN_ONCE(1, "Dev metricfs stats not created."); + goto error; + } + + /* initialize each of the metrics */ + for (x = 0; x < metric_count; x++) { + metric_def[x].metric = + metric_register_parm(metric_def[x].name, + dev_stats_subsys, + metric_def[x].desc, + "interface", + NULL, + dev_stats_fn, + (void *)&metric_def[x], + false, + true, /* this is a counter */ + THIS_MODULE); + if (!metric_def[x].metric) { + WARN_ONCE(1, "Dev metricfs stats %s not registered.", + metric_def[x].name); + goto error; + } + } + return 0; +error: + clean_dev_stats_subsys(); + return -1; +} + +/* need to wait for metricfs and net metricfs root to be initialized */ +late_initcall_sync(init_dev_stats_subsys); + +static void __exit dev_stats_exit(void) +{ + clean_dev_stats_subsys(); +} -- 2.28.0.236.gb10cc79966-goog