All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Mehaffey <mehaf@gedanken.com>
To: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] networking: Add write/clear capability to /proc/net/dev
Date: Fri, 29 May 2009 17:26:58 -0700	[thread overview]
Message-ID: <4A207D52.9000407@gedanken.com> (raw)

There is currently no way to reset networking statistics other than to
rmmod the interface and reinstall it.

This patch adds the capability to clear and/or set network statistics
counters using the /proc/net/dev file.

Please see the Documentation/networking/proc_net_dev file for full
details of the API.

Signed-off-by: John Mehaffey <mehaf_lkml@gedanken.com>
---

diff -purN orig new
--- orig/Documentation/networking/proc_net_dev.txt    Wed Dec 31 
16:00:00 1969
+++ new/Documentation/networking/proc_net_dev.txt    Fri May 29 15:59:32 
2009
@@ -0,0 +1,32 @@
+This document describes the interface provided by /proc/net/dev
+
+The proc/net/dev interface provides statistics about currently
+active network devices, both actual hardware and virtual devices.
+
+Reading /proc/net/dev provides both raw statistics and summaries
+from the struct net_dev_stats structure. If a device does not
+support statistics, an error message will print for that device.
+
+Writing /proc/net/dev can clear or set statistics for devices.
+
+There are 4 modes available for writing to /proc/net/dev.
+
+1.  echo "clearall" > /proc/net/dev
+    This will clear (0 out) all statistics for all devices.
+2.  echo "eth1 clear" > /proc/net/dev
+    Clears all stats for a single network device (eth1 in this case).
+3.  echo "eth1 0 0 0 0" > /proc/net/dev
+    Clears rx and tx bytes and packets counters. The order of counters
+    cleared is that in struct net_device_stats. Counters not included
+    in the parameter list are not altered.
+4.  echo "eth1 ,,,,0xFFFF 0xFFFF" > /proc/net/dev : sets rx and tx errors,
+    leaving byte and packet counters unchanged.  Perhaps useful for testing
+    network health monitoring software. Each comma skips an element, so if
+    you want to set consecutive elements, DO NOT use a comma separated 
list!
+
+    Whitespace is ignored, except as a separator. There is a limit of 256
+    bytes for the command.  You can use mode 4 to break setting of stats
+    into smaller chunks, if necessary.
+
+NOTE: the order of parameters is that of struct net_device_stats,
+    NOT that of the statistics returned by reading /proc/net/dev!!!
--- orig/net/core/dev.c    Fri May 29 15:13:15 2009
+++ new/net/core/dev.c    Fri May 29 14:44:18 2009
@@ -2929,6 +2929,142 @@ static void dev_seq_printf_stats(struct
            stats->tx_compressed);
 }
 
+#define USR_BUF_SIZE 256
+
+static void get_usr_buf(char *buffer, const char __user *input, size_t 
size)
+{
+    if (size < USR_BUF_SIZE) {
+        copy_from_user(buffer, input, size - 1);
+        buffer[size - 1]='\0';
+    } else {
+        printk(KERN_WARNING "Dev: Ignoring characters past size %d\n",
+                            USR_BUF_SIZE - 1);
+        copy_from_user(buffer, input, USR_BUF_SIZE - 1);
+        buffer[USR_BUF_SIZE - 1] = '\0';
+    }
+}
+
+static inline void clear_stats(struct net_device_stats *stats)
+{
+    if (stats)
+        memset(stats, 0, sizeof(struct net_device_stats));
+}
+
+static inline char *skip_whitespace(char *start)
+{
+    while (isspace(*start))
+        ++start;
+    return start;
+}
+
+static int get_net_dev(char **scan_start, struct net_device **net_dev)
+{
+    char tmp;
+    char *scan_end = *scan_start;
+
+    while ((*scan_end) && !(*scan_end == ',') && !isspace(*scan_end))
+        ++scan_end;
+
+    tmp = *scan_end;
+    if (!tmp) {
+        printk(KERN_ERR "Dev: Invalid parameter(s)\n");
+        return -EINVAL;
+    }
+
+    *scan_end = '\0';
+    *net_dev = dev_get_by_name(*scan_start);
+    if (!*net_dev) {
+        printk(KERN_ERR "Dev: network device not found: \"%s\"\n",
+                                *scan_start);
+        return -ENOENT;
+    }
+
+    *scan_end = tmp;
+    *scan_start = skip_whitespace(scan_end);
+
+    return 0;
+}
+
+static int set_stats(struct net_device *net_dev, char *scan_start)
+{
+    char * scan_end;
+    unsigned long *stat_ptr = (unsigned long *)net_dev->get_stats(net_dev);
+
+    while (*scan_start) {
+        if (isdigit(*scan_start))
+            *stat_ptr = simple_strtoul(scan_start, &scan_end, 0);
+        else if (*scan_start == ',')
+            scan_end = scan_start + 1;
+        else {
+            printk(KERN_ERR "Dev: Invalid scan character:\"%c\"\n",
+                                *scan_start);
+            return -EINVAL;
+        }
+
+        scan_start = skip_whitespace(scan_end);
+        ++stat_ptr;
+    }
+
+    return 0;
+}
+
+/*
+ * dev_stats_write - clear or set stats for network devices
+ * syntax:
+ * echo "clearall" > /proc/net/dev : clears all stats for all (current)
+ *    network devices.
+ * echo "eth1 clear" > /proc/net/dev : clears all stats for a single 
network
+ *      device (eth1 in this case).
+ * echo "eth1 0 0 0 0" > /proc/net/dev : clears rx and tx bytes and packets
+ *      counters.
+ * echo "eth1 ,,,,0xFFFF 0xFFFF" > /proc/net/dev : sets rx and tx errors,
+ *      leaving byte and packet counters unchanged.  Perhaps useful for 
testing
+ *      network health monitoring software. Each comma skips an 
element, so if
+ *      you want to set consecutive elements, DO NOT use a comma 
separated list!
+ *      Whitespace is ignored, except as a separator.
+ * NOTE: the order of parameters is that of struct net_device_stats,
+ *      NOT that of the statistics returned by reading /proc/net/dev!!!
+ */
+
+static ssize_t dev_stats_write(struct file *file, const char __user *input,
+                size_t size, loff_t *ofs)
+{
+    char usr_buf[USR_BUF_SIZE];
+    char *scan_start;
+    int retval;
+    struct net_device *net_dev = dev_base;
+
+    if (!capable(CAP_NET_ADMIN))
+                return -EPERM;
+    if (size < 2)
+        return -EINVAL;
+
+    get_usr_buf(usr_buf, input, size);
+
+    scan_start = strstrip(usr_buf);
+
+    if (!strcmp(scan_start, "clearall")) {
+        while (net_dev) {
+            clear_stats(net_dev->get_stats(net_dev));
+            net_dev = net_dev->next;
+        }
+        return size;
+    }
+
+    if ((retval = get_net_dev(&scan_start, &net_dev)))
+        return retval;
+
+    if (!strcmp(scan_start, "clear")) {
+        clear_stats(net_dev->get_stats(net_dev));
+        return size;
+    }
+
+    if ((retval = set_stats(net_dev, scan_start)))
+        return retval;
+    else
+        return size;
+}
+
 /*
  *    Called from the PROCfs module. This now uses the new arbitrary sized
  *    /proc/net interface to create /proc/net/dev
@@ -3002,6 +3138,7 @@ static const struct file_operations dev_
     .owner     = THIS_MODULE,
     .open    = dev_seq_open,
     .read    = seq_read,
+    .write   = dev_stats_write,
     .llseek  = seq_lseek,
     .release = seq_release_net,
 };
@@ -3135,7 +3272,7 @@ static int __net_init dev_proc_net_init(
 {
     int rc = -ENOMEM;
 
-    if (!proc_net_fops_create(net, "dev", S_IRUGO, &dev_seq_fops))
+    if (!proc_net_fops_create(net, "dev", S_IRUGO | S_IWUSR, 
&dev_seq_fops))
         goto out;
     if (!proc_net_fops_create(net, "softnet_stat", S_IRUGO, 
&softnet_seq_fops))
         goto out_dev;


             reply	other threads:[~2009-05-30  0:27 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-30  0:26 John Mehaffey [this message]
2009-05-30  3:49 ` [PATCH] networking: Add write/clear capability to /proc/net/dev David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A207D52.9000407@gedanken.com \
    --to=mehaf@gedanken.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.