All of lore.kernel.org
 help / color / mirror / Atom feed
From: Phil Dibowitz <phil@ipom.com>
To: netdev@vger.kernel.org
Subject: [PATCH] Interface Stat Clearing Framework, skge support, ethtool support
Date: Sat, 29 Apr 2006 20:16:54 -0700	[thread overview]
Message-ID: <44542C26.4070409@ipom.com> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 1305 bytes --]

Hey folks,

A few months back I posted an in-progress patch for adding a clear_stats
framework similar to the get_stats framework and implimenting support
for it in the skge driver (the one NIC I have access to), as well as
adding the ethtool support for it.

While a few people said they didn't see the need for it, other people
did see the need for it, and I know it's a common request on many
sysadmin mailing lists I'm on.

Since no one seemed to have any technical issue with the patch, I've
cleaned up the patch, tested it, and fixed a few minor issues.

Unless someone has an objection, I'd think this would be useful to a lot
of people.

There are two patches attached:

interface_stats_clear.patch - the kernel patch against 2.6.17-rc3-git2
ethtool3-clearstats.patch - the ethtool patch to add the -z flag to
		support it.

If the kernel patch gets accepted I'll send a more complete ethtool
patch with documentation updates, etc.

Thanks.
-- 
Phil Dibowitz                             phil@ipom.com
Freeware and Technical Pages              Insanity Palace of Metallica
http://www.phildev.net/                   http://www.ipom.com/

"Be who you are and say what you feel, because those who mind don't
matter and those who matter don't mind."
 - Dr. Suess



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: interface_stats_clear.patch --]
[-- Type: text/x-patch; name="interface_stats_clear.patch", Size: 6417 bytes --]



This patch adds support for clearing interface statistics using the ethtool interface adding a new 0x23 command. It adds a clear_stats function pointer to the net_device struct, and then impliments local functions in the driver much the say get_stats works. The ethtool funtion pointer points to the same functions. The driver-local functions are currently only implimented in the skge driver.

Signed-off-by: Phil Dibowitz <phil@ipom.com>

---


diff -puN include/linux/netdevice.h~interface_stats_clear include/linux/netdevice.h
--- linux-2.6.17-rc3-git2/include/linux/netdevice.h~interface_stats_clear	2006-04-29 19:44:41.000000000 -0700
+++ linux-2.6.17-rc3-git2-phil/include/linux/netdevice.h	2006-04-29 19:44:41.000000000 -0700
@@ -319,6 +319,7 @@ struct net_device
 
 
 	struct net_device_stats* (*get_stats)(struct net_device *dev);
+	void (*clear_stats)(struct net_device *dev);
 	struct iw_statistics*	(*get_wireless_stats)(struct net_device *dev);
 
 	/* List of functions to handle Wireless Extensions (instead of ioctl).
diff -puN drivers/net/skge.c~interface_stats_clear drivers/net/skge.c
--- linux-2.6.17-rc3-git2/drivers/net/skge.c~interface_stats_clear	2006-04-29 19:44:41.000000000 -0700
+++ linux-2.6.17-rc3-git2-phil/drivers/net/skge.c	2006-04-29 19:44:41.000000000 -0700
@@ -44,7 +44,7 @@
 #include "skge.h"
 
 #define DRV_NAME		"skge"
-#define DRV_VERSION		"1.5"
+#define DRV_VERSION		"1.6"
 #define PFX			DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE	128
@@ -97,6 +97,8 @@ static int xm_phy_write(struct skge_hw *
 static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
 static void genesis_get_stats(struct skge_port *skge, u64 *data);
 static void yukon_get_stats(struct skge_port *skge, u64 *data);
+static void genesis_clear_stats(struct skge_port *skge);
+static void yukon_clear_stats(struct skge_port *skge);
 static void yukon_init(struct skge_hw *hw, int port);
 static void genesis_mac_init(struct skge_hw *hw, int port);
 static void genesis_link_up(struct skge_port *skge);
@@ -366,6 +368,15 @@ static struct net_device_stats *skge_get
 	return &skge->net_stats;
 }
 
+static void skge_clear_stats(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	if (skge->hw->chip_id == CHIP_ID_GENESIS)
+		genesis_clear_stats(skge);
+	else
+		yukon_clear_stats(skge);
+}
+
 static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 {
 	int i;
@@ -722,6 +733,7 @@ static struct ethtool_ops skge_ethtool_o
 	.phys_id	= skge_phys_id,
 	.get_stats_count = skge_get_stats_count,
 	.get_ethtool_stats = skge_get_ethtool_stats,
+	.clear_ethtool_stats = skge_clear_stats,
 	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
@@ -1383,6 +1395,20 @@ static void genesis_get_stats(struct skg
 		data[i] = xm_read32(hw, port, skge_stats[i].xmac_offset);
 }
 
+static void genesis_clear_stats(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	/*
+	 * This is based on reading other parts of the driver
+	 * and is not yet tested.
+	 */
+
+	xm_write16(hw, port, XM_STAT_CMD, 0 | XM_SC_CLR_RXC
+			| XM_SC_CLR_TXC);
+}
+
 static void genesis_mac_intr(struct skge_hw *hw, int port)
 {
 	struct skge_port *skge = netdev_priv(hw->dev[port]);
@@ -1871,6 +1897,21 @@ static void yukon_get_stats(struct skge_
 					  skge_stats[i].gma_offset);
 }
 
+static void yukon_clear_stats(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	u16 reg;
+	int i;
+
+	reg = gma_read16(hw, port, GM_PHY_ADDR);
+	/* this read is important, or we sometimes get no effect */
+	gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+	for (i = 0; i < GM_MIB_CNT_SIZE; i++)
+		gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i);
+	gma_write16(hw, port, GM_PHY_ADDR, reg);
+}
+
 static void yukon_mac_intr(struct skge_hw *hw, int port)
 {
 	struct net_device *dev = hw->dev[port];
@@ -3183,6 +3224,7 @@ static struct net_device *skge_devinit(s
 	dev->do_ioctl = skge_ioctl;
 	dev->hard_start_xmit = skge_xmit_frame;
 	dev->get_stats = skge_get_stats;
+	dev->clear_stats = skge_clear_stats;
 	if (hw->chip_id == CHIP_ID_GENESIS)
 		dev->set_multicast_list = genesis_set_multicast;
 	else
diff -puN include/linux/ethtool.h~interface_stats_clear include/linux/ethtool.h
--- linux-2.6.17-rc3-git2/include/linux/ethtool.h~interface_stats_clear	2006-04-29 19:44:41.000000000 -0700
+++ linux-2.6.17-rc3-git2-phil/include/linux/ethtool.h	2006-04-29 19:44:41.000000000 -0700
@@ -365,6 +365,7 @@ struct ethtool_ops {
 	int	(*phys_id)(struct net_device *, u32);
 	int	(*get_stats_count)(struct net_device *);
 	void	(*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *);
+	void    (*clear_ethtool_stats)(struct net_device *);
 	int	(*get_perm_addr)(struct net_device *, struct ethtool_perm_addr *, u8 *);
 	int	(*begin)(struct net_device *);
 	void	(*complete)(struct net_device *);
@@ -408,6 +409,7 @@ struct ethtool_ops {
 #define ETHTOOL_GPERMADDR	0x00000020 /* Get permanent hardware address */
 #define ETHTOOL_GUFO		0x00000021 /* Get UFO enable (ethtool_value) */
 #define ETHTOOL_SUFO		0x00000022 /* Set UFO enable (ethtool_value) */
+#define ETHTOOL_CSTATS		0x00000023 /* Clear NIC-specific statistics */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff -puN net/core/ethtool.c~interface_stats_clear net/core/ethtool.c
--- linux-2.6.17-rc3-git2/net/core/ethtool.c~interface_stats_clear	2006-04-29 19:44:41.000000000 -0700
+++ linux-2.6.17-rc3-git2-phil/net/core/ethtool.c	2006-04-29 19:44:41.000000000 -0700
@@ -741,6 +741,17 @@ static int ethtool_get_stats(struct net_
 	return ret;
 }
 
+static int ethtool_clear_stats(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_ops *ops = dev->ethtool_ops;
+	if (!ops->clear_ethtool_stats)
+		return -EOPNOTSUPP;
+
+	ops->clear_ethtool_stats(dev);
+
+	return 0;
+}
+
 static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_perm_addr epaddr;
@@ -906,6 +917,9 @@ int dev_ethtool(struct ifreq *ifr)
 	case ETHTOOL_SUFO:
 		rc = ethtool_set_ufo(dev, useraddr);
 		break;
+	case ETHTOOL_CSTATS:
+		rc = ethtool_clear_stats(dev, useraddr);
+		break;
 	default:
 		rc =  -EOPNOTSUPP;
 	}
_

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: ethtool3-clearstats.patch --]
[-- Type: text/x-patch; name="ethtool3-clearstats.patch", Size: 3683 bytes --]

--- ethtool-3/ethtool.c.b4phil	2006-04-29 19:01:18.000000000 -0700
+++ ethtool-3/ethtool.c	2006-04-29 19:01:36.000000000 -0700
@@ -66,6 +66,7 @@
 static int do_goffload(int fd, struct ifreq *ifr);
 static int do_soffload(int fd, struct ifreq *ifr);
 static int do_gstats(int fd, struct ifreq *ifr);
+static int do_cstats(int fd, struct ifreq *ifr);
 static int send_ioctl(int fd, struct ifreq *ifr);
 static int check_for_pre24_kernel();
 
@@ -242,6 +243,7 @@
 	MODE_GOFFLOAD,
 	MODE_SOFFLOAD,
 	MODE_GSTATS,
+	MODE_CSTATS,
 } mode = MODE_GSET;
 
 static int goffload_changed = 0;
@@ -470,6 +472,8 @@
 				mode = MODE_TEST;
 			else if (!strcmp(argp[i], "-S"))
 				mode = MODE_GSTATS;
+			else if (!strcmp(argp[i], "-z"))
+				mode = MODE_CSTATS;
 			else if (!strcmp(argp[i], "-h"))
 				show_usage(0);
 			else
@@ -492,6 +496,7 @@
 			    (mode == MODE_GOFFLOAD) ||
 			    (mode == MODE_SOFFLOAD) ||
 			    (mode == MODE_GSTATS) ||
+			    (mode == MODE_CSTATS) ||
 			    (mode == MODE_PHYS_ID)) {
 				devname = argp[i];
 				break;
@@ -1266,6 +1271,8 @@
 		return do_soffload(fd, &ifr);
 	} else if (mode == MODE_GSTATS) {
 		return do_gstats(fd, &ifr);
+	} else if (mode == MODE_CSTATS) {
+		return do_cstats(fd, &ifr);
 	}
 
 	return 69;
@@ -2010,6 +2017,79 @@
 	return 0;
 }
 
+static int do_cstats(int fd, struct ifreq *ifr)
+{
+	struct ethtool_drvinfo drvinfo;
+	struct ethtool_gstrings *strings;
+	struct ethtool_stats *stats;
+	unsigned int n_stats, sz_str, sz_stats, i;
+	int err;
+
+	drvinfo.cmd = ETHTOOL_GDRVINFO;
+	ifr->ifr_data = (caddr_t)&drvinfo;
+	err = send_ioctl(fd, ifr);
+	if (err < 0) {
+		perror("Cannot get driver information");
+		return 71;
+	}
+
+	n_stats = drvinfo.n_stats;
+	if (n_stats < 1) {
+		fprintf(stderr, "no stats available\n");
+		return 94;
+	}
+
+	sz_str = n_stats * ETH_GSTRING_LEN;
+	sz_stats = n_stats * sizeof(u64);
+
+	strings = calloc(1, sz_str + sizeof(struct ethtool_gstrings));
+	stats = calloc(1, sz_stats + sizeof(struct ethtool_stats));
+	if (!strings || !stats) {
+		fprintf(stderr, "no memory available\n");
+		return 95;
+	}
+
+	strings->cmd = ETHTOOL_GSTRINGS;
+	strings->string_set = ETH_SS_STATS;
+	strings->len = n_stats;
+	ifr->ifr_data = (caddr_t) strings;
+	err = send_ioctl(fd, ifr);
+	if (err < 0) {
+		perror("Cannot get stats strings information");
+		free(strings);
+		free(stats);
+		return 96;
+	}
+
+	stats->cmd = ETHTOOL_CSTATS;
+	stats->n_stats = n_stats;
+	ifr->ifr_data = (caddr_t) stats;
+	err = send_ioctl(fd, ifr);
+	if (err < 0) {
+		perror("Cannot get stats information");
+		free(strings);
+		free(stats);
+		return 97;
+	}
+
+	/* todo - pretty-print the strings per-driver */
+	/*
+	fprintf(stdout, "NIC statistics:\n");
+	for (i = 0; i < n_stats; i++) {
+		char s[ETH_GSTRING_LEN];
+
+		strncpy(s, &strings->data[i * ETH_GSTRING_LEN],
+			ETH_GSTRING_LEN);
+		fprintf(stdout, "     %s: %llu\n",
+			s, stats->data[i]);
+	}
+	*/
+	free(strings);
+	free(stats);
+
+	return 0;
+}
+
 static int send_ioctl(int fd, struct ifreq *ifr)
 {
 	int err;
--- ethtool-3/ethtool-copy.h.b4phil	2006-04-29 19:01:26.000000000 -0700
+++ ethtool-3/ethtool-copy.h	2006-04-29 19:01:36.000000000 -0700
@@ -283,6 +283,7 @@
 #define ETHTOOL_GSTATS		0x0000001d /* get NIC-specific statistics */
 #define ETHTOOL_GTSO		0x0000001e /* Get TSO enable (ethtool_value) */
 #define ETHTOOL_STSO		0x0000001f /* Set TSO enable (ethtool_value) */
+#define ETHTOOL_CSTATS		0x00000023 /* get NIC-specific statistics */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

                 reply	other threads:[~2006-04-30  3:17 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=44542C26.4070409@ipom.com \
    --to=phil@ipom.com \
    --cc=netdev@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.