netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Adams <jwadams@google.com>
To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Cc: netdev@vger.kernel.org, kvm@vger.kernel.org,
	Paolo Bonzini <pbonzini@redhat.com>,
	Greg KH <gregkh@linuxfoundation.org>,
	Jim Mattson <jmattson@google.com>,
	David Rientjes <rientjes@google.com>,
	Jonathan Adams <jwadams@google.com>,
	Laurent Chavey <chavey@google.com>
Subject: [RFC PATCH 7/7] net-metricfs: Export /proc/net/dev via metricfs.
Date: Fri,  7 Aug 2020 14:29:16 -0700	[thread overview]
Message-ID: <20200807212916.2883031-8-jwadams@google.com> (raw)
In-Reply-To: <20200807212916.2883031-1-jwadams@google.com>

From: Laurent Chavey <chavey@google.com>

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 <chavey@google.com>
[jwadams@google.com: ported code to 5.8-pre6, cleaned up googleisms ]
Signed-off-by: Jonathan Adams <jwadams@google.com>
---
 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 <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/metricfs.h>
+#include <linux/netdevice.h>
+#include <linux/nsproxy.h>
+#include <linux/rcupdate.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <net/net_namespace.h>
+
+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


  parent reply	other threads:[~2020-08-07 21:30 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-07 21:29 [RFC PATCH 0/7] metricfs metric file system and examples Jonathan Adams
2020-08-07 21:29 ` [RFC PATCH 1/7] core/metricfs: Create metricfs, standardized files under debugfs Jonathan Adams
2020-08-08  5:41   ` Greg KH
2020-08-07 21:29 ` [RFC PATCH 2/7] core/metricfs: add support for percpu metricfs files Jonathan Adams
2020-08-08  5:43   ` Greg KH
2020-08-07 21:29 ` [RFC PATCH 3/7] core/metricfs: metric for kernel warnings Jonathan Adams
2020-08-08  5:45   ` Greg KH
2020-08-07 21:29 ` [RFC PATCH 4/7] core/metricfs: expose softirq information through metricfs Jonathan Adams
2020-08-08  5:46   ` Greg KH
2020-08-07 21:29 ` [RFC PATCH 5/7] core/metricfs: expose scheduler stat " Jonathan Adams
2020-08-07 21:29 ` [RFC PATCH 6/7] core/metricfs: expose x86-specific irq " Jonathan Adams
2020-08-13 10:11   ` Thomas Gleixner
2020-08-13 11:47     ` Paolo Bonzini
2020-08-13 12:13       ` Thomas Gleixner
2020-08-13 14:10         ` Paolo Bonzini
2020-08-13 14:21           ` Thomas Gleixner
2020-08-07 21:29 ` Jonathan Adams [this message]
2020-08-08  2:06 ` [RFC PATCH 0/7] metricfs metric file system and examples Andrew Lunn
2020-08-08 15:59   ` David Ahern
2020-08-10 18:20     ` Jakub Kicinski
2020-08-10  9:23 ` Pavel Machek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200807212916.2883031-8-jwadams@google.com \
    --to=jwadams@google.com \
    --cc=chavey@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=rientjes@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).