Re: [PATCH updated] net: add ability to clear per-interface networkstatistics via procfs

From: Eric Dumazet
Date: Fri May 16 2008 - 12:21:23 EST


James Cammarata a écrit :
From: James Cammarata <jimi@xxxxxxxx>

Added the ability to write to /proc/net/dev in order to clear the interface counters for a given interface. The ability to zero out counters (especially the error counters) is extremely useful when troubleshooting interface issues. Now diffed against 2.6.25.4, and added some sanity checking.

Hello James

1) Every call to get_proc_net() should be paired with a call to put_net(), or else you leak struct net.

2) I am not sure this is the right way to do this... Did you consider to extend ethtool instead ?

Syntax:
echo 'net clear-stats ifdev' > /proc/net/dev
Where "ifdev" is the device name you wish to clear.

This code is based mainly on the code found in drivers/scsi/scsi_proc.c

Signed-off-by: James Cammarata <jimi@xxxxxxxx>
---

--- linux-2.6.25.4/net/core/dev.c 2008-05-15 10:00:12.000000000 -0500
+++ linux-2.6.25.4-jcammara/net/core/dev.c 2008-05-16 07:02:48.000000000 -0500
@@ -2455,2 +2455,78 @@

+/**
+ * proc_net_dev_write - handle writes to /proc/net/dev
+ * @file: not used
+ * @buf: buffer to write
+ * @length: length of buf, at most PAGE_SIZE
+ * @ppos: not used
+ *
+ * Description: this provides a mechanism to clear statistics on a
+ * per-interface basis
+ * "echo 'net clear-stats ifdev' >/proc/net/dev"
+ * with "ifdev" replaced by the device name you wish to clear.
+ *
+ */
+static ssize_t proc_net_dev_write(struct file *file, const char __user *buf,
+ size_t length, loff_t *ppos)
+{
+ char *buffer, *p;
+ char devname[IFNAMSIZ];
+ struct net *net;
+ struct net_device *dev;
+ int err;
+
+ if (!buf || length > PAGE_SIZE)
+ return -EINVAL;
+
+ buffer = (char *)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ err = -EFAULT;
+ if (copy_from_user(buffer, buf, length))
+ goto out;
+
+ err = -EINVAL;
+ if (length < PAGE_SIZE)
+ buffer[length] = '\0';
+ else if (buffer[PAGE_SIZE-1])
+ goto out;
+
+ err = -ENXIO;
+ net = get_proc_net(file->f_dentry->d_inode);
+ if (!net)
+ goto out;
+
+ /*
+ * Usage: echo "net clear-stats ifdev" >/proc/net/dev
+ * with "ifdev" replaced by the device name you wish to clear.
+ */
+ if (!strncmp("net clear-stats",buffer,15)) {
+ p = buffer + 16;
+ if(sscanf(p,"%16s",devname)>0) {
+ dev = dev_get_by_name(net,devname);
+ if (dev) {
+ if (dev->get_stats) {
+ struct net_device_stats *stats =
+ dev->get_stats(dev);
+ memset(stats,0,
+ sizeof(struct net_device_stats));
+ }
+ dev_put(dev);
+ }
+ }
+ }
+
+ /*
+ * convert success returns so that we return the
+ * number of bytes consumed.
+ */
+ if (!err)
+ err = length;
+
Here probably, you should add

put_net(net);

+ out:
+ free_page((unsigned long)buffer);
+ return err;
+}
+
static void *softnet_seq_start(struct seq_file *seq, loff_t *pos)
@@ -2498,2 +2574,3 @@
.read = seq_read,
+ .write = proc_net_dev_write,
.llseek = seq_lseek,






--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/