Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751496AbdH1TVp (ORCPT ); Mon, 28 Aug 2017 15:21:45 -0400 Received: from mail.savoirfairelinux.com ([208.88.110.44]:36334 "EHLO mail.savoirfairelinux.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751194AbdH1TVk (ORCPT ); Mon, 28 Aug 2017 15:21:40 -0400 From: Vivien Didelot To: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kernel@savoirfairelinux.com, "David S. Miller" , Florian Fainelli , Andrew Lunn , Egil Hjelmeland , John Crispin , Woojung Huh , Sean Wang , Nikita Yushchenko , Chris Healy , Vivien Didelot Subject: [PATCH net-next v2 04/10] net: dsa: debugfs: add port stats Date: Mon, 28 Aug 2017 15:17:42 -0400 Message-Id: <20170828191748.19492-5-vivien.didelot@savoirfairelinux.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170828191748.19492-1-vivien.didelot@savoirfairelinux.com> References: <20170828191748.19492-1-vivien.didelot@savoirfairelinux.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4520 Lines: 122 Add a debug filesystem "stats" entry to query a port's hardware statistics through the DSA switch .get_sset_count, .get_strings and .get_ethtool_stats operations. This allows one to get statistics about DSA links interconnecting switches, which is very convenient because this kind of port is not exposed to userspace. Here are the stats of a zii-rev-b DSA and CPU ports: # pr -mt switch0/port{5,6}/stats in_good_octets : 0 in_good_octets : 13824 in_bad_octets : 0 in_bad_octets : 0 in_unicast : 0 in_unicast : 0 in_broadcasts : 0 in_broadcasts : 216 in_multicasts : 0 in_multicasts : 0 in_pause : 0 in_pause : 0 in_undersize : 0 in_undersize : 0 in_fragments : 0 in_fragments : 0 in_oversize : 0 in_oversize : 0 in_jabber : 0 in_jabber : 0 in_rx_error : 0 in_rx_error : 0 in_fcs_error : 0 in_fcs_error : 0 out_octets : 9216 out_octets : 0 out_unicast : 0 out_unicast : 0 out_broadcasts : 144 out_broadcasts : 0 out_multicasts : 0 out_multicasts : 0 out_pause : 0 out_pause : 0 excessive : 0 excessive : 0 collisions : 0 collisions : 0 deferred : 0 deferred : 0 single : 0 single : 0 multiple : 0 multiple : 0 out_fcs_error : 0 out_fcs_error : 0 late : 0 late : 0 hist_64bytes : 0 hist_64bytes : 0 hist_65_127bytes : 0 hist_65_127bytes : 0 hist_128_255bytes : 0 hist_128_255bytes : 0 hist_256_511bytes : 0 hist_256_511bytes : 0 hist_512_1023bytes : 0 hist_512_1023bytes : 0 hist_1024_max_bytes : 0 hist_1024_max_bytes : 0 sw_in_discards : 0 sw_in_discards : 0 sw_in_filtered : 0 sw_in_filtered : 0 sw_out_filtered : 0 sw_out_filtered : 216 Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Reviewed-by: Andrew Lunn --- net/dsa/debugfs.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/net/dsa/debugfs.c b/net/dsa/debugfs.c index 8a0e4311ff8c..997bbc8eb502 100644 --- a/net/dsa/debugfs.c +++ b/net/dsa/debugfs.c @@ -109,6 +109,43 @@ static int dsa_debugfs_create_file(struct dsa_switch *ds, struct dentry *dir, return 0; } +static void dsa_debugfs_stats_read_count(struct dsa_switch *ds, int id, + struct seq_file *seq, int count) +{ + u8 strings[count * ETH_GSTRING_LEN]; + u64 stats[count]; + int i; + + ds->ops->get_strings(ds, id, strings); + ds->ops->get_ethtool_stats(ds, id, stats); + + for (i = 0; i < count; i++) + seq_printf(seq, "%-20s: %lld\n", strings + i * ETH_GSTRING_LEN, + stats[i]); +} + +static int dsa_debugfs_stats_read(struct dsa_switch *ds, int id, + struct seq_file *seq) +{ + int count; + + if (!ds->ops->get_sset_count || !ds->ops->get_strings || + !ds->ops->get_ethtool_stats) + return -EOPNOTSUPP; + + count = ds->ops->get_sset_count(ds); + if (count < 0) + return count; + + dsa_debugfs_stats_read_count(ds, id, seq, count); + + return 0; +} + +static const struct dsa_debugfs_ops dsa_debugfs_stats_ops = { + .read = dsa_debugfs_stats_read, +}; + static int dsa_debugfs_tag_protocol_read(struct dsa_switch *ds, int id, struct seq_file *seq) { @@ -143,6 +180,7 @@ static int dsa_debugfs_create_port(struct dsa_switch *ds, int port) { struct dentry *dir; char name[32]; + int err; snprintf(name, sizeof(name), DSA_PORT_FMT, port); @@ -150,6 +188,11 @@ static int dsa_debugfs_create_port(struct dsa_switch *ds, int port) if (IS_ERR_OR_NULL(dir)) return -EFAULT; + err = dsa_debugfs_create_file(ds, dir, "stats", port, + &dsa_debugfs_stats_ops); + if (err) + return err; + return 0; } -- 2.14.1