ia64/xen-unstable

changeset 8248:4e9c643968ff

Fix netfront to accept received packets at a wider range of
offsets within a memory page. Also fix, skb realloc-and-copy
when copying really is required (we were forgetting whether
the packet data is known valid, and checksumming packets that
do not have the csum field filled in).

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Dec 06 15:02:54 2005 +0100 (2005-12-06)
parents 8b5c047f6e23
children c976c1ff806a
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	Tue Dec 06 12:49:05 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Tue Dec 06 15:02:54 2005 +0100
     1.3 @@ -76,9 +76,6 @@
     1.4          skb_shinfo(_skb)->frag_list = NULL;           \
     1.5      } while (0)
     1.6  
     1.7 -/* Allow headroom on each rx pkt for Ethernet header, alignment padding, ... */
     1.8 -#define RX_HEADROOM 200
     1.9 -
    1.10  static unsigned long rx_pfn_array[NET_RX_RING_SIZE];
    1.11  static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1];
    1.12  static mmu_update_t rx_mmu[NET_RX_RING_SIZE];
    1.13 @@ -153,14 +150,15 @@ static char *be_state_name[] = {
    1.14  #endif
    1.15  
    1.16  #ifdef DEBUG
    1.17 -#define DPRINTK(fmt, args...) \
    1.18 -	printk(KERN_ALERT "netfront (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
    1.19 +#define DPRINTK(fmt, args...)						\
    1.20 +	printk(KERN_ALERT "netfront (%s:%d) " fmt, __FUNCTION__,	\
    1.21 +	       __LINE__, ##args)
    1.22  #else
    1.23  #define DPRINTK(fmt, args...) ((void)0)
    1.24  #endif
    1.25 -#define IPRINTK(fmt, args...) \
    1.26 +#define IPRINTK(fmt, args...)				\
    1.27  	printk(KERN_INFO "netfront: " fmt, ##args)
    1.28 -#define WPRINTK(fmt, args...) \
    1.29 +#define WPRINTK(fmt, args...)				\
    1.30  	printk(KERN_WARNING "netfront: " fmt, ##args)
    1.31  
    1.32  
    1.33 @@ -537,7 +535,9 @@ static void network_alloc_rx_buffers(str
    1.34  	 */
    1.35  	batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
    1.36  	for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
    1.37 -		skb = alloc_xen_skb(dev->mtu + RX_HEADROOM);
    1.38 +		skb = alloc_xen_skb(
    1.39 +			(PAGE_SIZE - sizeof(struct skb_shared_info)) &
    1.40 +			(-SKB_DATA_ALIGN(1)));
    1.41  		if (skb == NULL)
    1.42  			break;
    1.43  		__skb_queue_tail(&np->rx_batch, skb);
    1.44 @@ -567,7 +567,8 @@ static void network_alloc_rx_buffers(str
    1.45  		rx_pfn_array[i] = virt_to_mfn(skb->head);
    1.46  
    1.47  		/* Remove this page from map before passing back to Xen. */
    1.48 -		set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
    1.49 +		set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT,
    1.50 +				    INVALID_P2M_ENTRY);
    1.51  
    1.52  		MULTI_update_va_mapping(rx_mcl+i, (unsigned long)skb->head,
    1.53  					__pte(0), 0);
    1.54 @@ -809,36 +810,43 @@ static int netif_poll(struct net_device 
    1.55  	}
    1.56  
    1.57  	while ((skb = __skb_dequeue(&rxq)) != NULL) {
    1.58 +		if (skb->len > (dev->mtu + ETH_HLEN)) {
    1.59 +			if (net_ratelimit())
    1.60 +				printk(KERN_INFO "Received packet too big for "
    1.61 +				       "MTU (%d > %d)\n",
    1.62 +				       skb->len - ETH_HLEN, dev->mtu);
    1.63 +			skb->len  = 0;
    1.64 +			skb->tail = skb->data;
    1.65 +			init_skb_shinfo(skb);
    1.66 +			dev_kfree_skb(skb);
    1.67 +			continue;
    1.68 +		}
    1.69 +
    1.70  		/*
    1.71  		 * Enough room in skbuff for the data we were passed? Also,
    1.72  		 * Linux expects at least 16 bytes headroom in each rx buffer.
    1.73  		 */
    1.74  		if (unlikely(skb->tail > skb->end) || 
    1.75  		    unlikely((skb->data - skb->head) < 16)) {
    1.76 -			nskb = NULL;
    1.77 -
    1.78 -			/* Only copy the packet if it fits in the MTU. */
    1.79 -			if (skb->len <= (dev->mtu + ETH_HLEN)) {
    1.80 -				if ((skb->tail > skb->end) && net_ratelimit())
    1.81 +			if (net_ratelimit()) {
    1.82 +				if (skb->tail > skb->end)
    1.83  					printk(KERN_INFO "Received packet "
    1.84 -					       "needs %zd bytes more "
    1.85 -					       "headroom.\n",
    1.86 +					       "is %zd bytes beyond tail.\n",
    1.87  					       skb->tail - skb->end);
    1.88 +				else
    1.89 +					printk(KERN_INFO "Received packet "
    1.90 +					       "is %zd bytes before head.\n",
    1.91 +					       16 - (skb->data - skb->head));
    1.92 +			}
    1.93  
    1.94 -				nskb = alloc_xen_skb(skb->len + 2);
    1.95 -				if (nskb != NULL) {
    1.96 -					skb_reserve(nskb, 2);
    1.97 -					skb_put(nskb, skb->len);
    1.98 -					memcpy(nskb->data,
    1.99 -					       skb->data,
   1.100 -					       skb->len);
   1.101 -					nskb->dev = skb->dev;
   1.102 -				}
   1.103 +			nskb = alloc_xen_skb(skb->len + 2);
   1.104 +			if (nskb != NULL) {
   1.105 +				skb_reserve(nskb, 2);
   1.106 +				skb_put(nskb, skb->len);
   1.107 +				memcpy(nskb->data, skb->data, skb->len);
   1.108 +				nskb->dev = skb->dev;
   1.109 +				nskb->ip_summed = skb->ip_summed;
   1.110  			}
   1.111 -			else if (net_ratelimit())
   1.112 -				printk(KERN_INFO "Received packet too big for "
   1.113 -				       "MTU (%d > %d)\n",
   1.114 -				       skb->len - ETH_HLEN, dev->mtu);
   1.115  
   1.116  			/* Reinitialise and then destroy the old skbuff. */
   1.117  			skb->len  = 0;