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(&ethcmd, 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

Reply via email to