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