Roberto Nibali wrote:
It looks like the e1000 driver gathers all kinds of stats. How do I
access these from userspace?
/proc/net/dev will have many of the common ones, and ethtool should
get the rest.
If you want a hack, I have a patch against the ethtool logic that
allows user-space to grab the netdev->stats struct and copy it
directly to user-space. This is easier and most likely more efficient
than parsing the /proc/net/dev file.
Yes, please ;). I'd be interested in this patch as well.
I'm manually pasting this out of my consolidated patch..it's against 2.6.15.
You should be able to ignore the send-to-self and crc related logic w/out
incident.
If this won't work, I can send you a link to my full patch, but it has a lot
more than just this netdev stats hack in it....
Here is how you use it in user-space:
struct my_net_device_stats_32 {
uint32 rx_packets; /* total packets received */
uint32 tx_packets; /* total packets transmitted */
uint32 rx_bytes; /* total bytes received */
uint32 tx_bytes; /* total bytes transmitted */
uint32 rx_errors; /* bad packets received */
uint32 tx_errors; /* packet transmit problems */
uint32 rx_dropped; /* no space in linux buffers */
uint32 tx_dropped; /* no space available in linux */
uint32 multicast; /* multicast packets received */
uint32 collisions;
/* detailed rx_errors: */
uint32 rx_length_errors;
uint32 rx_over_errors; /* receiver ring buff overflow */
uint32 rx_crc_errors; /* recved pkt with crc error */
uint32 rx_frame_errors; /* recv'd frame alignment error */
uint32 rx_fifo_errors; /* recv'r fifo overrun */
uint32 rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
uint32 tx_aborted_errors;
uint32 tx_carrier_errors;
uint32 tx_fifo_errors;
uint32 tx_heartbeat_errors;
uint32 tx_window_errors;
/* for cslip etc */
uint32 rx_compressed;
uint32 tx_compressed;
};
struct cmd_my_net_device_stats_32 {
uint32 ecmd; /* ethtool command */
struct my_net_device_stats_32 stats_32;
};
struct cmd_my_net_device_stats_32 cmd_stats_32;
memset(&cmd_stats_32, 0, sizeof(cmd_stats_32));
struct ifreq ifr;
int fd = socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
cerr << "ERROR: socket: " << strerror(errno) << endl;
}
else {
memset(&ifr, 0, sizeof(struct ifreq));
strcpy(ifr.ifr_name, dev_name);
ifr.ifr_addr.sa_family = AF_INET;
cmd_stats_32.ecmd = /*ETHTOOL_GNDSTATS*/ 0x70;
ifr.ifr_data = (char*)(&cmd_stats_32);
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
use_gndstats = false;
}
else {
found_one = true;
}
close(fd);
}
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -1,4 +1,4 @@
-/*
+/* -*-linux-c-*-
* ethtool.h: Defines for Linux ethtool.
*
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
@@ -307,7 +307,11 @@ int ethtool_op_set_ufo(struct net_device
* phys_id: Identify the device
* get_stats: Return statistics about the device
* get_perm_addr: Gets the permanent hardware address
- *
+ * set_rx_all: Set or clear IFF_ACCEPT_ALL_FRAMES, see if.h
+ * get_rx_all: Return 1 if set, 0 if not.
+ * set_save_fcs: Set or clear IFF_SAVE_FCS, see if.h
+ * get_save_fcs: Return 1 if set, 0 if not.
+ *
* Description:
*
* get_settings:
@@ -366,12 +370,24 @@ struct ethtool_ops {
int (*get_stats_count)(struct net_device *);
void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats
*, u64 *);
int (*get_perm_addr)(struct net_device *, struct ethtool_perm_addr
*, u8 *);
+ int (*set_rx_all)(struct net_device *, u32);
+ int (*get_rx_all)(struct net_device *, u32 *);
+ int (*set_save_fcs)(struct net_device *, u32);
+ int (*get_save_fcs)(struct net_device *, u32 *);
int (*begin)(struct net_device *);
void (*complete)(struct net_device *);
u32 (*get_ufo)(struct net_device *);
int (*set_ufo)(struct net_device *, u32);
};
+
+/* for dumping net-device statistics */
+struct ethtool_ndstats {
+ u32 cmd; /* ETHTOOL_GNDSTATS */
+ u8 data[0]; /* sizeof(struct net_device_stats) */
+};
+
+
/* CMDs currently supported */
#define ETHTOOL_GSET 0x00000001 /* Get settings. */
#define ETHTOOL_SSET 0x00000002 /* Set settings. */
@@ -409,6 +425,15 @@ struct ethtool_ops {
#define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */
#define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */
+
+#define ETHTOOL_GNDSTATS 0x00000070 /* get standard net-device
statistics */
+#define ETHTOOL_GETRXALL 0x00000071 /* Retrieve whether or not
+ * IFF_ACCEPT_ALL_FRAMES is set. */
+#define ETHTOOL_SETRXALL 0x00000072 /* Set IFF_ACCEPT_ALL_FRAMES */
+#define ETHTOOL_GETRXFCS 0x00000073 /* Set IFF_SAVE_FCS */
+#define ETHTOOL_SETRXFCS 0x00000074 /* Set IFF_SAVE_FCS */
+
+
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
#define SPARC_ETH_SSET ETHTOOL_SSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1,4 +1,4 @@
-/*
+/* -*- linux-c -*-
* net/core/ethtool.c - Ethtool ioctl handler
* Copyright (c) 2003 Matthew Wilcox <[EMAIL PROTECTED]>
*
@@ -32,6 +32,12 @@ u32 ethtool_op_get_tx_csum(struct net_de
return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0;
}
+u32 ethtool_op_get_rx_all(struct net_device *dev, u32* retval)
+{
+ *retval = ((dev->priv_flags & IFF_ACCEPT_ALL_FRAMES) != 0);
+ return 0;
+}
+
int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
{
if (data)
@@ -773,6 +779,88 @@ static int ethtool_get_perm_addr(struct
return ret;
}
+
+static int ethtool_get_rx_all(struct net_device *dev, char *useraddr)
+{
+ struct ethtool_value edata = { ETHTOOL_GSG };
+ int rv = 0;
+
+ if (!dev->ethtool_ops->get_rx_all)
+ return -EOPNOTSUPP;
+
+ if ((rv = dev->ethtool_ops->get_rx_all(dev, &edata.data)) < 0) {
+ return rv;
+ }
+
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+}
+
+
+static int ethtool_set_rx_all(struct net_device *dev, void *useraddr)
+{
+ struct ethtool_value id;
+
+ if (!dev->ethtool_ops->set_rx_all)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&id, useraddr, sizeof(id)))
+ return -EFAULT;
+
+ return dev->ethtool_ops->set_rx_all(dev, id.data);
+}
+
+static int ethtool_get_rx_fcs(struct net_device *dev, char *useraddr)
+{
+ struct ethtool_value edata = { ETHTOOL_GSG };
+ int rv = 0;
+
+ if (!dev->ethtool_ops->get_save_fcs)
+ return -EOPNOTSUPP;
+
+ if ((rv = dev->ethtool_ops->get_save_fcs(dev, &edata.data)) < 0) {
+ return rv;
+ }
+
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+}
+
+
+static int ethtool_set_rx_fcs(struct net_device *dev, void *useraddr)
+{
+ struct ethtool_value id;
+
+ if (!dev->ethtool_ops->set_save_fcs)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&id, useraddr, sizeof(id)))
+ return -EFAULT;
+
+ return dev->ethtool_ops->set_save_fcs(dev, id.data);
+}
+
+
+/* Handle some generic ethtool commands here */
+static int ethtool_get_netdev_stats(struct net_device *dev, void *useraddr) {
+
+ struct ethtool_ndstats* nds = (struct ethtool_ndstats*)(useraddr);
+
+ struct net_device_stats *stats = dev->get_stats(dev);
+ if (stats) {
+ if (copy_to_user(nds->data, stats, sizeof(*stats))) {
+ return -EFAULT;
+ }
+ }
+ else {
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
/* The main entry point in this file. Called from net/core/dev.c */
int dev_ethtool(struct ifreq *ifr)
@@ -793,18 +881,28 @@ int dev_ethtool(struct ifreq *ifr)
if (!dev || !netif_device_present(dev))
return -ENODEV;
- if (!dev->ethtool_ops)
- goto ioctl;
-
if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd)))
return -EFAULT;
- if(dev->ethtool_ops->begin)
+ if(dev->ethtool_ops && dev->ethtool_ops->begin)
if ((rc = dev->ethtool_ops->begin(dev)) < 0)
return rc;
old_features = dev->features;
-
+
+ /* Handle some generic operations that do not require specific
+ * ethtool handlers.
+ */
+ switch (ethcmd) {
+ case ETHTOOL_GNDSTATS:
+ return ethtool_get_netdev_stats(dev, useraddr);
+ default:
+ break;
+ }
+
+ if (!dev->ethtool_ops)
+ goto ioctl;
+
switch (ethcmd) {
case ETHTOOL_GSET:
rc = ethtool_get_settings(dev, useraddr);
@@ -893,6 +991,18 @@ int dev_ethtool(struct ifreq *ifr)
case ETHTOOL_PHYS_ID:
rc = ethtool_phys_id(dev, useraddr);
break;
+ case ETHTOOL_SETRXALL:
+ rc = ethtool_set_rx_all(dev, useraddr);
+ break;
+ case ETHTOOL_GETRXALL:
+ rc = ethtool_get_rx_all(dev, useraddr);
+ break;
+ case ETHTOOL_SETRXFCS:
+ rc = ethtool_set_rx_fcs(dev, useraddr);
+ break;
+ case ETHTOOL_GETRXFCS:
+ rc = ethtool_get_rx_fcs(dev, useraddr);
+ break;
case ETHTOOL_GSTATS:
rc = ethtool_get_stats(dev, useraddr);
break;
Regards,
Roberto Nibali, ratz
--
Ben Greear <[EMAIL PROTECTED]>
Candela Technologies Inc http://www.candelatech.com
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html