direct-io.hg

changeset 10348:1e49997c8146

[NET] front: Discard packets in tx ring rather than attempting retransmit
when reconnecting to backend driver (e.g., after save/restore or migrate).

Two main reasons for this:
1. The retransmit code is broken for fragmented packets. It would need
a rewrite to cope with the new scatter-gather format.
2. We will drop packets anyway, in both directions (e.g., takes some
time for received packets to be redirected to new virtual interface;
also further transmitted packets from the network stack are dropped
after we call netif_carrier_off(), so even if we retransmite what's
already in the ring it is likely that some subsequent packets will
already be lost).

If this causes downtimes that are too long (particularly for live
relocation) then the whole strategy for buffering packets while the
frontend-backend connection is severed needs to be considered.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Jun 14 13:11:44 2006 +0100 (2006-06-14)
parents 8070050cc30f
children 578e306b0bd4
files linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Wed Jun 14 12:36:06 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Wed Jun 14 13:11:44 2006 +0100
     1.3 @@ -1072,68 +1072,39 @@ static void xennet_set_features(struct n
     1.4  
     1.5  static void network_connect(struct net_device *dev)
     1.6  {
     1.7 -	struct netfront_info *np;
     1.8 +	struct netfront_info *np = netdev_priv(dev);
     1.9  	int i, requeue_idx;
    1.10 -	struct netif_tx_request *tx;
    1.11  	struct sk_buff *skb;
    1.12  
    1.13  	xennet_set_features(dev);
    1.14  
    1.15 -	np = netdev_priv(dev);
    1.16  	spin_lock_irq(&np->tx_lock);
    1.17  	spin_lock(&np->rx_lock);
    1.18  
    1.19 -	/* Recovery procedure: */
    1.20 -
    1.21  	/*
    1.22 -	 * Step 1: Rebuild the RX and TX ring contents.
    1.23 -	 * NB. We could just free the queued TX packets now but we hope
    1.24 -	 * that sending them out might do some good.  We have to rebuild
    1.25 -	 * the RX ring because some of our pages are currently flipped out
    1.26 -	 * so we can't just free the RX skbs.
    1.27 -	 * NB2. Freelist index entries are always going to be less than
    1.28 +         * Recovery procedure:
    1.29 +	 *  NB. Freelist index entries are always going to be less than
    1.30  	 *  PAGE_OFFSET, whereas pointers to skbs will always be equal or
    1.31 -	 * greater than PAGE_OFFSET: we use this property to distinguish
    1.32 -	 * them.
    1.33 -	 */
    1.34 +	 *  greater than PAGE_OFFSET: we use this property to distinguish
    1.35 +	 *  them.
    1.36 +         */
    1.37  
    1.38 -	/*
    1.39 -	 * Rebuild the TX buffer freelist and the TX ring itself.
    1.40 -	 * NB. This reorders packets.  We could keep more private state
    1.41 -	 * to avoid this but maybe it doesn't matter so much given the
    1.42 -	 * interface has been down.
    1.43 -	 */
    1.44 +	/* Step 1: Discard all pending TX packet fragments. */
    1.45  	for (requeue_idx = 0, i = 1; i <= NET_TX_RING_SIZE; i++) {
    1.46  		if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET)
    1.47  			continue;
    1.48  
    1.49  		skb = np->tx_skbs[i];
    1.50 -
    1.51 -		tx = RING_GET_REQUEST(&np->tx, requeue_idx);
    1.52 -		requeue_idx++;
    1.53 -
    1.54 -		tx->id = i;
    1.55 -		gnttab_grant_foreign_access_ref(
    1.56 -			np->grant_tx_ref[i], np->xbdev->otherend_id,
    1.57 -			virt_to_mfn(np->tx_skbs[i]->data),
    1.58 -			GNTMAP_readonly);
    1.59 -		tx->gref = np->grant_tx_ref[i];
    1.60 -		tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
    1.61 -		tx->size = skb->len;
    1.62 -		tx->flags = 0;
    1.63 -		if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
    1.64 -			tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
    1.65 -		if (skb->proto_data_valid) /* remote but checksummed? */
    1.66 -			tx->flags |= NETTXF_data_validated;
    1.67 -
    1.68 -		np->stats.tx_bytes += skb->len;
    1.69 -		np->stats.tx_packets++;
    1.70 +		gnttab_end_foreign_access_ref(
    1.71 +			np->grant_tx_ref[i], GNTMAP_readonly);
    1.72 +		gnttab_release_grant_reference(
    1.73 +			&np->gref_tx_head, np->grant_tx_ref[i]);
    1.74 +		np->grant_tx_ref[i] = GRANT_INVALID_REF;
    1.75 +		add_id_to_freelist(np->tx_skbs, i);
    1.76 +		dev_kfree_skb_irq(skb);
    1.77  	}
    1.78  
    1.79 -	np->tx.req_prod_pvt = requeue_idx;
    1.80 -	RING_PUSH_REQUESTS(&np->tx);
    1.81 -
    1.82 -	/* Rebuild the RX buffer freelist and the RX ring itself. */
    1.83 +	/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
    1.84  	for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) {
    1.85  		if ((unsigned long)np->rx_skbs[i] < PAGE_OFFSET)
    1.86  			continue;
    1.87 @@ -1150,7 +1121,7 @@ static void network_connect(struct net_d
    1.88  	RING_PUSH_REQUESTS(&np->rx);
    1.89  
    1.90  	/*
    1.91 -	 * Step 2: All public and private state should now be sane.  Get
    1.92 +	 * Step 3: All public and private state should now be sane.  Get
    1.93  	 * ready to start sending and receiving packets and give the driver
    1.94  	 * domain a kick because we've probably just requeued some
    1.95  	 * packets.
    1.96 @@ -1158,6 +1129,7 @@ static void network_connect(struct net_d
    1.97  	netif_carrier_on(dev);
    1.98  	notify_remote_via_irq(np->irq);
    1.99  	network_tx_buf_gc(dev);
   1.100 +	network_alloc_rx_buffers(dev);
   1.101  
   1.102  	spin_unlock(&np->rx_lock);
   1.103  	spin_unlock_irq(&np->tx_lock);