ia64/xen-unstable

changeset 11735:224b80785d02

[NET] back: Disable packet queuing when a client has no receive buffers.

This turns out to be dangerous as packets can be queued indefinitely,
introducing resource dependencies between guests (if the queued
packets originate from another virtual machine). For example, this
can prevent interfaces from being torn down and hence defunct
virtual machines from being destroyed.

The queuing functionality is retained as a module option, but a
warning is printed if it is enabled. It is not intended for general use!

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Oct 04 16:12:35 2006 +0100 (2006-10-04)
parents 6a8ae4c34abe
children 2dd375ce153d
files linux-2.6-xen-sparse/drivers/xen/netback/interface.c linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Wed Oct 04 09:43:45 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Wed Oct 04 16:12:35 2006 +0100
     1.3 @@ -34,6 +34,24 @@
     1.4  #include <linux/ethtool.h>
     1.5  #include <linux/rtnetlink.h>
     1.6  
     1.7 +/*
     1.8 + * Module parameter 'queue_length':
     1.9 + * 
    1.10 + * Enables queuing in the network stack when a client has run out of receive
    1.11 + * descriptors. Although this feature can improve receive bandwidth by avoiding
    1.12 + * packet loss, it can also result in packets sitting in the 'tx_queue' for
    1.13 + * unbounded time. This is bad if those packets hold onto foreign resources.
    1.14 + * For example, consider a packet that holds onto resources belonging to the
    1.15 + * guest for which it is queued (e.g., packet received on vif1.0, destined for
    1.16 + * vif1.1 which is not activated in the guest): in this situation the guest
    1.17 + * will never be destroyed, unless vif1.1 is taken down (which flushes the
    1.18 + * 'tx_queue').
    1.19 + * 
    1.20 + * Only set this parameter to non-zero value if you know what you are doing!
    1.21 + */
    1.22 +static unsigned long netbk_queue_length = 0;
    1.23 +module_param_named(queue_length, netbk_queue_length, ulong, 0);
    1.24 +
    1.25  static void __netif_up(netif_t *netif)
    1.26  {
    1.27  	enable_irq(netif->irq);
    1.28 @@ -144,11 +162,10 @@ netif_t *netif_alloc(domid_t domid, unsi
    1.29  
    1.30  	SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
    1.31  
    1.32 -	/*
    1.33 -	 * Reduce default TX queuelen so that each guest interface only
    1.34 -	 * allows it to eat around 6.4MB of host memory.
    1.35 -	 */
    1.36 -	dev->tx_queue_len = 100;
    1.37 +	dev->tx_queue_len = netbk_queue_length;
    1.38 +	if (dev->tx_queue_len != 0)
    1.39 +		printk(KERN_WARNING "netbk: WARNING: device '%s' has non-zero "
    1.40 +		       "queue length (%lu)!\n", dev->name, dev->tx_queue_len);
    1.41  
    1.42  	for (i = 0; i < ETH_ALEN; i++)
    1.43  		if (be_mac[i] != 0)
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Wed Oct 04 09:43:45 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Wed Oct 04 16:12:35 2006 +0100
     2.3 @@ -366,6 +366,10 @@ static void connect(struct backend_info 
     2.4  	be->netif->remaining_credit = be->netif->credit_bytes;
     2.5  
     2.6  	xenbus_switch_state(dev, XenbusStateConnected);
     2.7 +
     2.8 +	/* May not get a kick from the frontend, so start the tx_queue now. */
     2.9 +	if (!netbk_can_queue(be->netif->dev))
    2.10 +		netif_start_queue(be->netif->dev);
    2.11  }
    2.12  
    2.13  
    2.14 @@ -403,14 +407,16 @@ static int connect_rings(struct backend_
    2.15  	}
    2.16  	be->netif->copying_receiver = !!rx_copy;
    2.17  
    2.18 -	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-rx-notify", "%d",
    2.19 -			 &val) < 0)
    2.20 -		val = 0;
    2.21 -	if (val)
    2.22 -		be->netif->can_queue = 1;
    2.23 -	else
    2.24 -		/* Must be non-zero for pfifo_fast to work. */
    2.25 -		be->netif->dev->tx_queue_len = 1;
    2.26 +	if (be->netif->dev->tx_queue_len != 0) {
    2.27 +		if (xenbus_scanf(XBT_NIL, dev->otherend,
    2.28 +				 "feature-rx-notify", "%d", &val) < 0)
    2.29 +			val = 0;
    2.30 +		if (val)
    2.31 +			be->netif->can_queue = 1;
    2.32 +		else
    2.33 +			/* Must be non-zero for pfifo_fast to work. */
    2.34 +			be->netif->dev->tx_queue_len = 1;
    2.35 +	}
    2.36  
    2.37  	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", "%d", &val) < 0)
    2.38  		val = 0;