[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Add a /proc interface for setting rx-buffer allocation policy in



ChangeSet 1.1844, 2005/05/03 11:54:00+01:00, kaf24@xxxxxxxxxxxxxxxxxxxx

        Add a /proc interface for setting rx-buffer allocation policy in
        the netfront driver.
        e.g., 'echo 256 >/proc/xen/net/eth0/rxbuf_min' will avoid unnecessary
        packet drops by always allocating the maximum possible number of
        buffers at all times, at the expense of extra memory usage when the
        interface is idle.
        Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>



 netfront.c |  185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 177 insertions(+), 8 deletions(-)


diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c 
b/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c   2005-05-03 
07:03:53 -04:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c   2005-05-03 
07:03:53 -04:00
@@ -39,6 +39,7 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/proc_fs.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <net/arp.h>
@@ -85,6 +86,16 @@
 static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1];
 static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
 
+#ifdef CONFIG_PROC_FS
+static int xennet_proc_init(void);
+static int xennet_proc_addif(struct net_device *dev);
+static void xennet_proc_delif(struct net_device *dev);
+#else
+#define xennet_proc_init()   (0)
+#define xennet_proc_addif(d) (0)
+#define xennet_proc_delif(d) ((void)0)
+#endif
+
 static struct list_head dev_list;
 
 struct net_private
@@ -120,7 +131,7 @@
     /* Receive-ring batched refills. */
 #define RX_MIN_TARGET 8
 #define RX_MAX_TARGET NETIF_RX_RING_SIZE
-    int rx_target;
+    int rx_min_target, rx_max_target, rx_target;
     struct sk_buff_head rx_batch;
 
     /*
@@ -419,8 +430,8 @@
 
     /* Adjust our floating fill target if we risked running out of buffers. */
     if (((req_prod - np->rx->resp_prod) < (np->rx_target / 4)) &&
-         ((np->rx_target *= 2) > RX_MAX_TARGET))
-        np->rx_target = RX_MAX_TARGET;
+         ((np->rx_target *= 2) > np->rx_max_target))
+        np->rx_target = np->rx_max_target;
 }
 
 
@@ -651,8 +662,8 @@
     /* If we get a callback with very few responses, reduce fill target. */
     /* NB. Note exponential increase, linear decrease. */
     if (((np->rx->req_prod - np->rx->resp_prod) > ((3*np->rx_target) / 4)) &&
-         (--np->rx_target < RX_MIN_TARGET))
-        np->rx_target = RX_MIN_TARGET;
+         (--np->rx_target < np->rx_min_target))
+        np->rx_target = np->rx_min_target;
 
     network_alloc_rx_buffers(dev);
 
@@ -943,7 +954,9 @@
     spin_lock_init(&np->rx_lock);
 
     skb_queue_head_init(&np->rx_batch);
-    np->rx_target = RX_MIN_TARGET;
+    np->rx_target     = RX_MIN_TARGET;
+    np->rx_min_target = RX_MIN_TARGET;
+    np->rx_max_target = RX_MAX_TARGET;
 
     /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
     for (i = 0; i <= NETIF_TX_RING_SIZE; i++)
@@ -962,11 +975,17 @@
         printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err);
         goto exit;
     }
+
+    if ((err = xennet_proc_addif(dev)) != 0) {
+        unregister_netdev(dev);
+        goto exit;
+    }
+
     np->dev = dev;
     list_add(&np->list, &dev_list);
 
   exit:
-    if ((err != 0) && (dev != NULL ))
+    if ((err != 0) && (dev != NULL))
         kfree(dev);
     else if (val != NULL)
         *val = dev;
@@ -1248,6 +1267,9 @@
     if (xen_start_info.flags & SIF_INITDOMAIN)
         return 0;
 
+    if ((err = xennet_proc_init()) != 0)
+        return err;
+
     IPRINTK("Initialising virtual ethernet driver.\n");
     INIT_LIST_HEAD(&dev_list);
     (void)register_inetaddr_notifier(&notifier_inetdev);
@@ -1305,6 +1327,153 @@
     }
 }
 
+#ifdef CONFIG_PROC_FS
 
-module_init(netif_init);
+#define TARGET_MIN 0UL
+#define TARGET_MAX 1UL
+#define TARGET_CUR 2UL
+
+static int xennet_proc_read(
+    char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+    struct net_device *dev = (struct net_device *)((unsigned long)data & ~3UL);
+    struct net_private *np = netdev_priv(dev);
+    int len = 0, which_target = (int)data & 3;
+    
+    switch (which_target)
+    {
+    case TARGET_MIN:
+        len = sprintf(page, "%d\n", np->rx_min_target);
+        break;
+    case TARGET_MAX:
+        len = sprintf(page, "%d\n", np->rx_max_target);
+        break;
+    case TARGET_CUR:
+        len = sprintf(page, "%d\n", np->rx_target);
+        break;
+    }
+
+    *eof = 1;
+    return len;
+}
+
+static int xennet_proc_write(
+    struct file *file, const char __user *buffer,
+    unsigned long count, void *data)
+{
+    struct net_device *dev = (struct net_device *)((unsigned long)data & ~3UL);
+    struct net_private *np = netdev_priv(dev);
+    int which_target = (int)data & 3;
+    char string[64];
+    long target;
+
+    if (!capable(CAP_SYS_ADMIN))
+        return -EPERM;
+
+    if (count <= 1)
+        return -EBADMSG; /* runt */
+    if (count > sizeof(string))
+        return -EFBIG;   /* too long */
+
+    if (copy_from_user(string, buffer, count))
+        return -EFAULT;
+    string[sizeof(string)-1] = '\0';
+
+    target = simple_strtol(string, NULL, 10);
+    if (target < RX_MIN_TARGET)
+        target = RX_MIN_TARGET;
+    if (target > RX_MAX_TARGET)
+        target = RX_MAX_TARGET;
+
+    spin_lock(&np->rx_lock);
+
+    switch (which_target)
+    {
+    case TARGET_MIN:
+        if (target > np->rx_max_target)
+            np->rx_max_target = target;
+        np->rx_min_target = target;
+        if (target > np->rx_target)
+            np->rx_target = target;
+        break;
+    case TARGET_MAX:
+        if (target < np->rx_min_target)
+            np->rx_min_target = target;
+        np->rx_max_target = target;
+        if (target < np->rx_target)
+            np->rx_target = target;
+        break;
+    case TARGET_CUR:
+        break;
+    }
 
+    network_alloc_rx_buffers(dev);
+
+    spin_unlock(&np->rx_lock);
+
+    return count;
+}
+
+static int xennet_proc_init(void)
+{
+    if (proc_mkdir("xen/net", NULL) == NULL)
+        return -ENOMEM;
+    return 0;
+}
+
+static int xennet_proc_addif(struct net_device *dev)
+{
+    struct proc_dir_entry *dir, *min, *max, *cur;
+    char name[30];
+
+    sprintf(name, "xen/net/%s", dev->name);
+
+    dir = proc_mkdir(name, NULL);
+    if (!dir)
+        goto nomem;
+
+    min = create_proc_entry("rxbuf_min", 0644, dir);
+    max = create_proc_entry("rxbuf_max", 0644, dir);
+    cur = create_proc_entry("rxbuf_cur", 0444, dir);
+    if (!min || !max || !cur)
+        goto nomem;
+
+    min->read_proc  = xennet_proc_read;
+    min->write_proc = xennet_proc_write;
+    min->data       = (void *)((unsigned long)dev | TARGET_MIN);
+
+    max->read_proc  = xennet_proc_read;
+    max->write_proc = xennet_proc_write;
+    max->data       = (void *)((unsigned long)dev | TARGET_MAX);
+
+    cur->read_proc  = xennet_proc_read;
+    cur->write_proc = xennet_proc_write;
+    cur->data       = (void *)((unsigned long)dev | TARGET_CUR);
+
+    return 0;
+
+ nomem:
+    xennet_proc_delif(dev);
+    return -ENOMEM;
+}
+
+static void xennet_proc_delif(struct net_device *dev)
+{
+    char name[30];
+
+    sprintf(name, "xen/net/%s/rxbuf_min", dev->name);
+    remove_proc_entry(name, NULL);
+
+    sprintf(name, "xen/net/%s/rxbuf_max", dev->name);
+    remove_proc_entry(name, NULL);
+
+    sprintf(name, "xen/net/%s/rxbuf_cur", dev->name);
+    remove_proc_entry(name, NULL);
+
+    sprintf(name, "xen/net/%s", dev->name);
+    remove_proc_entry(name, NULL);
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.