* RESEND: [PATCH] Interface Stat Clearing Framework, skge support, ethtool support]
@ 2006-05-18 8:23 Phil Dibowitz
0 siblings, 0 replies; only message in thread
From: Phil Dibowitz @ 2006-05-18 8:23 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
[-- Attachment #1.1: Type: text/plain, Size: 1340 bytes --]
Resending this - saw no response.
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: 6419 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: 3685 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 --]
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2006-05-18 8:23 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-18 8:23 RESEND: [PATCH] Interface Stat Clearing Framework, skge support, ethtool support] Phil Dibowitz
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).