Jens Köhler wrote:
> Hello all,
> 
> I am using the rt_8139too.koo network driver. Is there a possibility to get
> a statistic about received, sent packets and errors?

Hi,

In case it could be for interest to anyone, here is a patch which adds
supports for rtnet per-device statistics, and make them accessible
through rtifconfig.

Note that to make these statistics work, you will have to write a
per-driver callback, but for most drivers the callback is already there,
you only have to uncomment it.

Note that this patch was extracted from a bunch of other stuff, so,
there may be some things missing, if it happens and this patch is of
some interest to you, let me know.

Regards.

-- 
                                                 Gilles Chanteperdrix

diff -x '*.orig' -x '*.rej' -Naurdp rtnet-0.9.8/stack/include/rtdev.h 
rtnet-0.9.8-stats/stack/include/rtdev.h
--- rtnet-0.9.8/stack/include/rtdev.h   2006-08-09 18:27:46.000000000 +0200
+++ rtnet-0.9.8-stats/stack/include/rtdev.h     2008-06-23 16:23:21.000000000 
+0200
@@ -141,6 +141,7 @@ struct rtnet_device {
 
     int                 (*do_ioctl)(struct rtnet_device *rtdev, 
                                    unsigned int request, void * cmd);
+    struct net_device_stats *(*get_stats)(struct rtnet_device *rtdev);
 };
 
 
diff -x '*.orig' -x '*.rej' -Naurdp rtnet-0.9.8/stack/rtdev.c 
rtnet-0.9.8-stats/stack/rtdev.c
--- rtnet-0.9.8/stack/rtdev.c   2006-11-08 10:49:11.000000000 +0100
+++ rtnet-0.9.8-stats/stack/rtdev.c     2008-06-23 16:23:21.000000000 +0200
@@ -29,6 +29,8 @@
 #include <linux/if_arp.h> /* ARPHRD_ETHER */
 #include <linux/netdevice.h>
 #include <linux/moduleparam.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <rtnet_internal.h>
 #include <rtskb.h>
@@ -615,6 +617,87 @@ unsigned int rt_hard_mtu(struct rtnet_de
     return rtdev->mtu;
 }
 
+#ifdef CONFIG_PROC_FS
+void *dev_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       down(&rtnet_devices_nrt_lock);
+       return *pos ? rtnet_devices[(*pos - 1)] : SEQ_START_TOKEN;
+}
+
+void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       ++*pos;
+       return v == SEQ_START_TOKEN ? rtnet_devices[0] : rtnet_devices[*pos - 
1];
+}
+
+void dev_seq_stop(struct seq_file *seq, void *v)
+{
+       up(&rtnet_devices_nrt_lock);
+}
+
+static void dev_seq_printf_stats(struct seq_file *seq, struct rtnet_device 
*dev)
+{
+       if (dev && dev->get_stats) {
+               struct net_device_stats *stats = dev->get_stats(dev);
+
+               seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
+                               "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
+                          dev->name, stats->rx_bytes, stats->rx_packets,
+                          stats->rx_errors,
+                          stats->rx_dropped + stats->rx_missed_errors,
+                          stats->rx_fifo_errors,
+                          stats->rx_length_errors + stats->rx_over_errors +
+                            stats->rx_crc_errors + stats->rx_frame_errors,
+                          stats->rx_compressed, stats->multicast,
+                          stats->tx_bytes, stats->tx_packets,
+                          stats->tx_errors, stats->tx_dropped,
+                          stats->tx_fifo_errors, stats->collisions,
+                          stats->tx_carrier_errors +
+                            stats->tx_aborted_errors +
+                            stats->tx_window_errors +
+                            stats->tx_heartbeat_errors,
+                          stats->tx_compressed);
+       } else
+               seq_printf(seq, "%6s: No statistics available.\n", dev->name);
+}
+
+/*
+ *     Called from the PROCfs module. This now uses the new arbitrary sized
+ *     /proc/net interface to create /proc/net/dev
+ */
+static int dev_seq_show(struct seq_file *seq, void *v)
+{
+       if (v == SEQ_START_TOKEN)
+               seq_puts(seq, "Inter-|   Receive                            "
+                             "                    |  Transmit\n"
+                             " face |bytes    packets errs drop fifo frame "
+                             "compressed multicast|bytes    packets errs "
+                             "drop fifo colls carrier compressed\n");
+       else
+               dev_seq_printf_stats(seq, v);
+       return 0;
+}
+
+static struct seq_operations dev_seq_ops = {
+       .start = dev_seq_start,
+       .next  = dev_seq_next,
+       .stop  = dev_seq_stop,
+       .show  = dev_seq_show,
+};
+
+static int dev_seq_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &dev_seq_ops);
+}
+
+struct file_operations rtdev_stats_seq_fops = {
+       .owner   = THIS_MODULE,
+       .open    = dev_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release,
+};
+#endif  /* CONFIG_PROC_FS */
 
 EXPORT_SYMBOL(rt_alloc_etherdev);
 EXPORT_SYMBOL(rtdev_free);
diff -x '*.orig' -x '*.rej' -Naurdp rtnet-0.9.8/stack/rtnet_module.c 
rtnet-0.9.8-stats/stack/rtnet_module.c
--- rtnet-0.9.8/stack/rtnet_module.c    2006-11-08 10:34:07.000000000 +0100
+++ rtnet-0.9.8-stats/stack/rtnet_module.c      2008-06-23 16:23:21.000000000 
+0200
@@ -146,6 +146,7 @@ static int rtnet_read_proc_version(char 
 
 static int rtnet_proc_register(void)
 {
+    extern struct file_operations rtdev_stats_seq_fops;
     struct proc_dir_entry *proc_entry;
 
     rtnet_proc_root = create_proc_entry("rtnet", S_IFDIR, 0);
@@ -170,8 +171,16 @@ static int rtnet_proc_register(void)
         goto error4;
     proc_entry->read_proc = rtnet_read_proc_version;
 
+    proc_entry = create_proc_entry("stats", S_IRUGO, rtnet_proc_root);
+    if (!proc_entry)
+       goto error5;
+    proc_entry->proc_fops = &rtdev_stats_seq_fops;
+    
     return 0;
 
+  error5:
+    remove_proc_entry("version", rtnet_proc_root);
+    
   error4:
     remove_proc_entry("rtskb", rtnet_proc_root);
 
@@ -193,6 +202,7 @@ static void rtnet_proc_unregister(void)
     remove_proc_entry("devices", rtnet_proc_root);
     remove_proc_entry("rtskb", rtnet_proc_root);
     remove_proc_entry("version", rtnet_proc_root);
+    remove_proc_entry("stats", rtnet_proc_root);
     remove_proc_entry("rtnet", 0);
 }
 #endif  /* CONFIG_PROC_FS */
diff -x '*.orig' -x '*.rej' -Naurdp rtnet-0.9.8/tools/rtifconfig.c 
rtnet-0.9.8-stats/tools/rtifconfig.c
--- rtnet-0.9.8/tools/rtifconfig.c      2006-10-09 13:47:19.000000000 +0200
+++ rtnet-0.9.8-stats/tools/rtifconfig.c        2008-06-23 16:23:21.000000000 
+0200
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <ctype.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <net/ethernet.h>
@@ -50,6 +51,111 @@
 int                     f;
 struct rtnet_core_cmd   cmd;
 
+struct user_net_device_stats {
+    unsigned long long rx_packets;     /* total packets received       */
+    unsigned long long tx_packets;     /* total packets transmitted    */
+    unsigned long long rx_bytes;       /* total bytes received         */
+    unsigned long long tx_bytes;       /* total bytes transmitted      */
+    unsigned long rx_errors;   /* bad packets received         */
+    unsigned long tx_errors;   /* packet transmit problems     */
+    unsigned long rx_dropped;  /* no space in linux buffers    */
+    unsigned long tx_dropped;  /* no space available in linux  */
+    unsigned long rx_multicast;        /* multicast packets received   */
+    unsigned long rx_compressed;
+    unsigned long tx_compressed;
+    unsigned long collisions;
+
+    /* detailed rx_errors: */
+    unsigned long rx_length_errors;
+    unsigned long rx_over_errors;      /* receiver ring buff overflow  */
+    unsigned long rx_crc_errors;       /* recved pkt with crc error    */
+    unsigned long rx_frame_errors;     /* recv'd frame alignment error */
+    unsigned long rx_fifo_errors;      /* recv'r fifo overrun          */
+    unsigned long rx_missed_errors;    /* receiver missed packet     */
+    /* detailed tx_errors */
+    unsigned long tx_aborted_errors;
+    unsigned long tx_carrier_errors;
+    unsigned long tx_fifo_errors;
+    unsigned long tx_heartbeat_errors;
+    unsigned long tx_window_errors;
+};
+
+struct itf_stats {
+       char name[IFNAMSIZ];
+       struct user_net_device_stats stats;
+       struct itf_stats *next;
+};
+
+static struct itf_stats *itf_stats_head;
+
+void parse_stats(void)
+{
+       struct itf_stats *itf;
+       char buf[512];
+       FILE *fh;
+
+       fh = fopen("/proc/rtnet/stats", "r");
+       if (!fh)
+               return;
+
+       fgets(buf, sizeof buf, fh);     /* eat headers */
+       fgets(buf, sizeof buf, fh);
+
+       while (fgets(buf, sizeof buf, fh)) {
+               char *name, *p;
+               
+               itf = malloc(sizeof(*itf));
+               if (!itf)
+                       return;
+
+               name = buf;
+               while (isspace(*name))
+                       name++;
+               p = name;
+               while (*p && *p != ':')
+                       p++;
+               *p = '\0';
+               snprintf(itf->name, sizeof(itf->name), "%s", name);
+
+               p++;
+               sscanf(p,
+                      "%llu %llu %lu %lu %lu %lu %lu %lu %llu %llu %lu %lu %lu 
%lu %lu %lu",
+                      &itf->stats.rx_bytes,
+                      &itf->stats.rx_packets,
+                      &itf->stats.rx_errors,
+                      &itf->stats.rx_dropped,
+                      &itf->stats.rx_fifo_errors,
+                      &itf->stats.rx_frame_errors,
+                      &itf->stats.rx_compressed,
+                      &itf->stats.rx_multicast,
+                      
+                      &itf->stats.tx_bytes,
+                      &itf->stats.tx_packets,
+                      &itf->stats.tx_errors,
+                      &itf->stats.tx_dropped,
+                      &itf->stats.tx_fifo_errors,
+                      &itf->stats.collisions,
+                      &itf->stats.tx_carrier_errors,
+                      &itf->stats.tx_compressed);
+
+               itf->next = itf_stats_head;
+               itf_stats_head = itf;
+       }
+
+       fclose(fh);
+}
+
+struct itf_stats *find_stats(const char *itf_name)
+{
+       struct itf_stats *itf;
+
+       for(itf = itf_stats_head; itf; itf = itf->next)
+               if(!strcmp(itf->name, itf_name))
+                       break;
+
+       return itf;
+}
+
 
 void help(void)
 {
@@ -70,6 +176,7 @@ void print_dev(void)
     struct in_addr  ip_addr;
     struct in_addr  broadcast_ip;
     unsigned int    flags;
+    struct itf_stats *itf;
 
 
     cmd.head.if_name[9] = 0;
@@ -106,13 +213,49 @@ void print_dev(void)
 
     flags = cmd.args.info.flags &
         (IFF_UP | IFF_BROADCAST | IFF_LOOPBACK | IFF_RUNNING | IFF_PROMISC);
-    printf("          %s%s%s%s%s%s MTU: %d\n\n",
+    printf("          %s%s%s%s%s%s MTU: %d\n",
            ((flags & IFF_UP) != 0) ? "UP " : "",
            ((flags & IFF_BROADCAST) != 0) ? "BROADCAST " : "",
            ((flags & IFF_LOOPBACK) != 0) ? "LOOPBACK " : "",
            ((flags & IFF_RUNNING) != 0) ? "RUNNING " : "",
            ((flags & IFF_PROMISC) != 0) ? "PROMISC " : "",
            (flags == 0) ? "[NO FLAGS] " : "", cmd.args.info.mtu);
+
+    if ((itf = find_stats(cmd.head.if_name))) {
+           unsigned long long rx, tx, short_rx, short_tx;
+           char Rext[5]="b";
+           char Text[5]="b";
+
+           printf("          ");
+           printf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu 
frame:%lu\n",
+                  itf->stats.rx_packets, itf->stats.rx_errors,
+                  itf->stats.rx_dropped, itf->stats.rx_fifo_errors,
+                  itf->stats.rx_frame_errors);
+           
+           printf("          ");
+           printf("TX packets:%llu errors:%lu dropped:%lu overruns:%lu 
carrier:%lu\n",
+                  itf->stats.tx_packets, itf->stats.tx_errors,
+                  itf->stats.tx_dropped, itf->stats.tx_fifo_errors,
+                  itf->stats.tx_carrier_errors);
+           printf("          collisions:%lu ", itf->stats.collisions);
+           printf("\n          ");
+
+           rx = itf->stats.rx_bytes;  
+           tx = itf->stats.tx_bytes;
+           short_rx = rx * 10;  
+           short_tx = tx * 10;
+           if (rx > 1048576) { short_rx /= 1048576;  strcpy(Rext, "Mb"); }
+           else if (rx > 1024) { short_rx /= 1024;  strcpy(Rext, "Kb"); }
+           if (tx > 1048576) { short_tx /= 1048576;  strcpy(Text, "Mb"); }
+           else if (tx > 1024) { short_tx /= 1024;  strcpy(Text, "Kb"); }
+
+           printf("RX bytes:%llu (%lu.%lu %s)  TX bytes:%llu (%lu.%lu %s)\n",
+                  rx, (unsigned long)(short_rx / 10),
+                  (unsigned long)(short_rx % 10), Rext, 
+                  tx, (unsigned long)(short_tx / 10), 
+                  (unsigned long)(short_tx % 10), Text);
+    }
+    printf("\n");
 }
 
 
@@ -254,6 +397,7 @@ int main(int argc, char *argv[])
         exit(1);
     }
 
+    parse_stats();
     if (argc == 1)
         do_display(PRINT_FLAG_ALL);
 

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
RTnet-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rtnet-developers

Reply via email to